From ac9290c995c116063b753b9bebe6b3593f44b5dc Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 5 Aug 2023 14:11:55 +0200 Subject: [PATCH 001/141] WIP --- declarative/annotations/pom.xml | 30 +++++++ .../declarative/annotations/Dataset.java | 34 ++++++++ .../declarative/annotations/Graph.java | 34 ++++++++ .../declarative/annotations/Resource.java | 34 ++++++++ declarative/pom.xml | 32 ++++++++ declarative/processor/pom.xml | 71 +++++++++++++++++ .../declarative/processor/Processor.java | 51 ++++++++++++ .../javax.annotation.processing.Processor | 1 + declarative/template/pom.xml | 35 ++++++++ .../declarative/template/ExampleDataset.java | 33 ++++++++ .../template/ExampleDataset_$impl.java | 52 ++++++++++++ .../declarative/template/ExampleGraph.java | 33 ++++++++ .../template/ExampleGraph_$impl.java | 61 ++++++++++++++ .../declarative/template/ExampleNode1.java | 7 ++ .../template/ExampleNode1_$impl.java | 53 +++++++++++++ .../declarative/template/ExampleNode2.java | 27 +++++++ .../template/ExampleNode2_$impl.java | 53 +++++++++++++ .../declarative/template/Manager.java | 79 +++++++++++++++++++ .../declarative/template/package-info.java | 25 ++++++ .../template/ExampleGraphTest.java | 60 ++++++++++++++ declarative/test/pom.xml | 49 ++++++++++++ .../rdf/wrapping/declarative/test/X.java | 35 ++++++++ pom.xml | 1 + 23 files changed, 890 insertions(+) create mode 100644 declarative/annotations/pom.xml create mode 100644 declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Dataset.java create mode 100644 declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Graph.java create mode 100644 declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Resource.java create mode 100644 declarative/pom.xml create mode 100644 declarative/processor/pom.xml create mode 100644 declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java create mode 100644 declarative/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor create mode 100644 declarative/template/pom.xml create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java create mode 100644 declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java create mode 100644 declarative/test/pom.xml create mode 100644 declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java diff --git a/declarative/annotations/pom.xml b/declarative/annotations/pom.xml new file mode 100644 index 000000000..0a405c7c7 --- /dev/null +++ b/declarative/annotations/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + com.inrupt.rdf + inrupt-rdf-wrapping-declarative + 1.0.1-SNAPSHOT + + + inrupt-rdf-wrapping-declarative-annotations + Inrupt RDF Wrapping Declarative - Annotations + + + 1.8 + 1.8 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.jacoco + jacoco-maven-plugin + + + + diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Dataset.java b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Dataset.java new file mode 100644 index 000000000..9003b1491 --- /dev/null +++ b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Dataset.java @@ -0,0 +1,34 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.annotations; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target(TYPE) +@Retention(CLASS) +@Documented +public @interface Dataset { +} diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Graph.java b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Graph.java new file mode 100644 index 000000000..62a893e49 --- /dev/null +++ b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Graph.java @@ -0,0 +1,34 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.annotations; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target(TYPE) +@Retention(CLASS) +@Documented +public @interface Graph { +} diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Resource.java b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Resource.java new file mode 100644 index 000000000..c7b2ca60e --- /dev/null +++ b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Resource.java @@ -0,0 +1,34 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.annotations; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target(TYPE) +@Retention(CLASS) +@Documented +public @interface Resource { +} diff --git a/declarative/pom.xml b/declarative/pom.xml new file mode 100644 index 000000000..0f46267e3 --- /dev/null +++ b/declarative/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + com.inrupt.rdf + inrupt-rdf-wrapping + 1.0.1-SNAPSHOT + + + inrupt-rdf-wrapping-declarative + Inrupt RDF Wrapping Declarative + pom + + + annotations + processor + test + template + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + diff --git a/declarative/processor/pom.xml b/declarative/processor/pom.xml new file mode 100644 index 000000000..442c3b455 --- /dev/null +++ b/declarative/processor/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + com.inrupt.rdf + inrupt-rdf-wrapping-declarative + 1.0.1-SNAPSHOT + + + inrupt-rdf-wrapping-declarative-processor + Inrupt RDF Wrapping Declarative - Processor + + + + + + 1.8 + 1.8 + + 3.0.1.Final + + + + + com.inrupt.rdf + inrupt-rdf-wrapping-declarative-annotations + ${project.version} + + + + org.jboss.logmanager + jboss-logmanager + ${jboss.logmanager.version} + + + + org.junit.jupiter + junit-jupiter-api + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + default-compile + compile + + compile + + + -proc:none + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.jacoco + jacoco-maven-plugin + + + + diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java new file mode 100644 index 000000000..6ae1bd13f --- /dev/null +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -0,0 +1,51 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +import org.jboss.logging.Logger; + +@SupportedAnnotationTypes("com.inrupt.rdf.wrapping.declarative.annotations.*") +@SupportedSourceVersion(SourceVersion.RELEASE_8) +public class Processor extends AbstractProcessor { + private static final Logger LOG = Logger.getLogger(Processor.class); + + @Override + public boolean process(final Set annotations, final RoundEnvironment roundEnv) { + LOG.infov("annotations {0}", annotations); + + for (TypeElement annotation : annotations) { + final Set annotatedElements = roundEnv.getElementsAnnotatedWith(annotation); + LOG.infov("annotatedElements {0}", annotatedElements); + } + + return true; + } +} diff --git a/declarative/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/declarative/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 000000000..63e203cdb --- /dev/null +++ b/declarative/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +com.inrupt.rdf.wrapping.declarative.processor.Processor diff --git a/declarative/template/pom.xml b/declarative/template/pom.xml new file mode 100644 index 000000000..ce9de407d --- /dev/null +++ b/declarative/template/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + com.inrupt.rdf + inrupt-rdf-wrapping-declarative + 1.0.1-SNAPSHOT + + + inrupt-rdf-wrapping-declarative-template + Inrupt RDF Wrapping Declarative - Template + + Examples of wrapper interfaces and the implementations the Processor should generate from them + + + + 17 + 17 + + + + + com.inrupt.rdf + inrupt-rdf-wrapping-jena + ${project.version} + + + + org.junit.jupiter + junit-jupiter + test + + + diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java new file mode 100644 index 000000000..82e41a0c5 --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java @@ -0,0 +1,33 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.template; + +import org.apache.jena.query.Dataset; + +// @Dataset +public interface ExampleDataset { + static ExampleDataset wrap(final Dataset original) { + return Manager.wrap(ExampleDataset.class, original); + } + + // @DefaultGraph + ExampleGraph getGraph(); +} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java new file mode 100644 index 000000000..586b6640c --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java @@ -0,0 +1,52 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.template; + +import javax.annotation.processing.Generated; + +import org.apache.jena.query.Dataset; +import org.apache.jena.sparql.core.DatasetGraph; +import org.apache.jena.sparql.core.DatasetGraphFactory; +import org.apache.jena.sparql.core.DatasetImpl; + +/** + * Warning this class consists of generated code. + */ +@Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") +public class ExampleDataset_$impl extends DatasetImpl implements ExampleDataset { + + protected ExampleDataset_$impl(final DatasetGraph original) { + super(original); + } + + public static ExampleDataset wrap(final Dataset original) { + return new ExampleDataset_$impl(original.asDatasetGraph()); + } + + public static ExampleDataset create() { + return new ExampleDataset_$impl(DatasetGraphFactory.create()); + } + + @Override + public ExampleGraph getGraph() { + return ExampleGraph.wrap(getDefaultModel()); + } +} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java new file mode 100644 index 000000000..534360337 --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java @@ -0,0 +1,33 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.template; + +import org.apache.jena.rdf.model.Model; + +// @Graph +public interface ExampleGraph { + static ExampleGraph wrap(final Model original) { + return Manager.wrap(ExampleGraph.class, original); + } + + // @FirstSubjectOf(RDF.type, "urn:example:C") + ExampleNode1 getResource(); +} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java new file mode 100644 index 000000000..3bff32501 --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java @@ -0,0 +1,61 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.template; + +import javax.annotation.processing.Generated; + +import org.apache.jena.graph.Graph; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.rdf.model.impl.ModelCom; +import org.apache.jena.sparql.graph.GraphFactory; +import org.apache.jena.vocabulary.RDF; + +/** + * Warning this class consists of generated code. + */ +@Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") +public class ExampleGraph_$impl extends ModelCom implements ExampleGraph { + protected ExampleGraph_$impl(final Graph base) { + super(base); + + getPersonality() + .add(ExampleNode1_$impl.class, ExampleNode1_$impl.factory) + .add(ExampleNode2_$impl.class, ExampleNode2_$impl.factory); + } + + public static ExampleGraph wrap(final Model original) { + return new ExampleGraph_$impl(original.getGraph()); + } + + public static ExampleGraph create() { + return new ExampleGraph_$impl(GraphFactory.createDefaultGraph()); + } + + @Override + public ExampleNode1 getResource() { + return listResourcesWithProperty( + RDF.type, + ResourceFactory.createResource("urn:example:C")) + .nextResource() + .as(ExampleNode1_$impl.class); + } +} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java new file mode 100644 index 000000000..b84325c35 --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java @@ -0,0 +1,7 @@ +package com.inrupt.rdf.wrapping.declarative.template; + +// @Resource +public interface ExampleNode1 { + // @Property(predicate = "urn:example:p1", type = PropertyMappingTypes.anyOrNull, mapping = ValueMappingTypes.as) + ExampleNode2 getP1(); +} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java new file mode 100644 index 000000000..9564cb17e --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java @@ -0,0 +1,53 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.template; + +import static org.apache.jena.rdf.model.ResourceFactory.*; + +import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; +import com.inrupt.rdf.wrapping.jena.ValueMappings; +import com.inrupt.rdf.wrapping.jena.WrapperResource; + +import javax.annotation.processing.Generated; + +import org.apache.jena.enhanced.EnhGraph; +import org.apache.jena.enhanced.Implementation; +import org.apache.jena.graph.Node; +import org.apache.jena.rdf.model.ResourceFactory; + +/** + * Warning this class consists of generated code. + */ +@Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") +public class ExampleNode1_$impl extends WrapperResource implements ExampleNode1 { + static final Implementation factory = new UriOrBlankFactory(ExampleNode1_$impl::new); + + protected ExampleNode1_$impl(Node node, EnhGraph model) { + super(node, model); + } + + @Override + public ExampleNode2 getP1() { + return anyOrNull( + createProperty("urn:example:p1"), + ValueMappings.as(ExampleNode2_$impl.class)); + } +} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java new file mode 100644 index 000000000..c8af94dff --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java @@ -0,0 +1,27 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.template; + +// @Resource +public interface ExampleNode2 { + // @Property(predicate = "urn:example:p2", type = PropertyMappingTypes.anyOrNull, mapping = ValueMappingTypes.literalAsString) + String getP2(); +} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java new file mode 100644 index 000000000..10b045ab8 --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java @@ -0,0 +1,53 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.template; + +import static org.apache.jena.rdf.model.ResourceFactory.*; + +import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; +import com.inrupt.rdf.wrapping.jena.ValueMappings; +import com.inrupt.rdf.wrapping.jena.WrapperResource; + +import javax.annotation.processing.Generated; + +import org.apache.jena.enhanced.EnhGraph; +import org.apache.jena.enhanced.Implementation; +import org.apache.jena.graph.Node; +import org.apache.jena.rdf.model.ResourceFactory; + +/** + * Warning this class consists of generated code. + */ +@Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") +public class ExampleNode2_$impl extends WrapperResource implements ExampleNode2 { + static final Implementation factory = new UriOrBlankFactory(ExampleNode2_$impl::new); + + protected ExampleNode2_$impl(Node node, EnhGraph model) { + super(node, model); + } + + @Override + public String getP2() { + return anyOrNull( + createProperty("urn:example:p2"), + ValueMappings::literalAsString); + } +} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java new file mode 100644 index 000000000..d225d2d3a --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java @@ -0,0 +1,79 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.template; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.jena.query.Dataset; +import org.apache.jena.rdf.model.Model; + +/** + * A utility class that aids wrapper interfaces to find generated implementations + */ +// TODO: Move to processor module +// TODO: Should this be SPI? +public final class Manager { + private Manager() { + } + + public static T wrap(final Class type, final Model original) { + return wrap(type, original, Model.class); + } + + public static T wrap(final Class type, final Dataset original) { + return wrap(type, original, Dataset.class); + } + + private static T wrap(final Class type, final Object original, Class xtype) { + final ClassLoader classLoader = type.getClassLoader(); + final String implTypeName = type.getName() + "_$impl"; + + Class implClass; + try { + implClass = Class.forName(implTypeName, true, classLoader).asSubclass(type); + } catch (ClassNotFoundException e) { + throw new RuntimeException("implementation not found", e); + } catch (ClassCastException e) { + // TODO: probably not needed as it's generated, match on $impl + throw new RuntimeException("implementation type mismatch", e); + } + + + final Method wrapMethod; + try { + wrapMethod = implClass.getMethod("wrap", xtype); + } catch (NoSuchMethodException e) { + throw new RuntimeException("wrap method not found", e); + } + + try { + return type.cast(wrapMethod.invoke(null, original)); + } catch (IllegalAccessException e) { + throw new RuntimeException("wrap method inaccessible", e); + } catch (InvocationTargetException e) { + throw new RuntimeException("wrap method threw exception", e); + } catch (ClassCastException e) { + // TODO: probably not needed as it's generated, match on $impl + throw new RuntimeException("wrap method return type mismatch", e); + } + } +} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java new file mode 100644 index 000000000..cb90dd82b --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java @@ -0,0 +1,25 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * Examples of wrapper interfaces and the implementations the Processor should generate from them + */ +package com.inrupt.rdf.wrapping.declarative.template; diff --git a/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java b/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java new file mode 100644 index 000000000..5578d7613 --- /dev/null +++ b/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java @@ -0,0 +1,60 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.template; + +import com.github.jsonldjava.shaded.com.google.common.base.Charsets; + +import org.apache.commons.io.IOUtils; +import org.apache.jena.query.Dataset; +import org.apache.jena.query.DatasetFactory; +import org.apache.jena.riot.Lang; +import org.apache.jena.riot.RDFDataMgr; +import org.junit.jupiter.api.Test; + +class ExampleGraphTest { + @Test + void test() { + final Dataset dataset = datasetFrom(""" + PREFIX : + + [ + a :C ; + :p1 [ + :p2 "XXX" ; + ] ; + ] . + """); + + final var wrap = ExampleDataset.wrap(dataset); + final var graph = wrap.getGraph(); + final var resource = graph.getResource(); + final var p1 = resource.getP1(); + final var p2 = p1.getP2(); + + System.out.println(p2); + } + + private static Dataset datasetFrom(final String rdf) { + final var dataset = DatasetFactory.create(); + RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); + return dataset; + } +} diff --git a/declarative/test/pom.xml b/declarative/test/pom.xml new file mode 100644 index 000000000..5939a9bbb --- /dev/null +++ b/declarative/test/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + com.inrupt.rdf + inrupt-rdf-wrapping-declarative + 1.0.1-SNAPSHOT + + + inrupt-rdf-wrapping-declarative-test + Inrupt RDF Wrapping Declarative - Test + + + + + + 1.8 + 1.8 + + + + + com.inrupt.rdf + inrupt-rdf-wrapping-declarative-processor + ${project.version} + provided + true + + + + org.junit.jupiter + junit-jupiter-api + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.jacoco + jacoco-maven-plugin + + + + diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java new file mode 100644 index 000000000..cec990e5e --- /dev/null +++ b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java @@ -0,0 +1,35 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.test; + +import com.inrupt.rdf.wrapping.declarative.annotations.Dataset; +import com.inrupt.rdf.wrapping.declarative.annotations.Graph; +import com.inrupt.rdf.wrapping.declarative.annotations.Resource; + +@Dataset +public interface X { + @Graph + interface Y { + @Resource + interface Z { + } + } +} diff --git a/pom.xml b/pom.xml index f208c50c2..f6d06805f 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,7 @@ jena rdf4j reports + declarative From 3dba2d44acac2a39200512212c28cb13772e3f6a Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 6 Aug 2023 11:28:25 +0200 Subject: [PATCH 002/141] Generating a source file --- .../declarative/annotations/Property.java | 34 ++++++++++++ .../declarative/processor/Processor.java | 53 ++++++++++++++++--- 2 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Property.java diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Property.java b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Property.java new file mode 100644 index 000000000..f2ee1fb02 --- /dev/null +++ b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Property.java @@ -0,0 +1,34 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target(METHOD) +@Retention(CLASS) +@Documented +public @interface Property { +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index 6ae1bd13f..410b9a7cc 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -20,6 +20,8 @@ */ package com.inrupt.rdf.wrapping.declarative.processor; +import java.io.IOException; +import java.io.PrintWriter; import java.util.Set; import javax.annotation.processing.AbstractProcessor; @@ -29,21 +31,58 @@ import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; -import org.jboss.logging.Logger; - -@SupportedAnnotationTypes("com.inrupt.rdf.wrapping.declarative.annotations.*") +@SupportedAnnotationTypes({ + "com.inrupt.rdf.wrapping.declarative.annotations.Dataset", + "com.inrupt.rdf.wrapping.declarative.annotations.Graph", + "com.inrupt.rdf.wrapping.declarative.annotations.Resource" +}) @SupportedSourceVersion(SourceVersion.RELEASE_8) public class Processor extends AbstractProcessor { - private static final Logger LOG = Logger.getLogger(Processor.class); - @Override public boolean process(final Set annotations, final RoundEnvironment roundEnv) { - LOG.infov("annotations {0}", annotations); + if (roundEnv.processingOver()) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "processing over"); + return true; + } + + if (annotations.isEmpty()) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "annotations empty"); + return true; + } for (TypeElement annotation : annotations) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("annotation [%s]", annotation), annotation); + + // TODO: Just to get started + if (!"com.inrupt.rdf.wrapping.declarative.annotations.Resource".equals(annotation.getQualifiedName().toString())) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("skipping [%s]", annotation), annotation); + continue; + } + final Set annotatedElements = roundEnv.getElementsAnnotatedWith(annotation); - LOG.infov("annotatedElements {0}", annotatedElements); + for (Element annotatedElement : annotatedElements) { + processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("annotatedElement [%s]", annotatedElement), annotatedElement); + + final TypeElement annotatedType = (TypeElement) annotatedElement; + final String qualifiedName = annotatedType.getQualifiedName().toString() + "_$impl"; + + final JavaFileObject builderFile; + try { + builderFile = processingEnv.getFiler().createSourceFile(qualifiedName, annotatedElement); + } catch (IOException e) { + throw new RuntimeException("could not create class file", e); + } + + try (PrintWriter out = new PrintWriter(builderFile.openWriter())) { + // This should surely be a framework like JDeparser + out.println("generated"); + } catch (IOException e) { + throw new RuntimeException("could not open writer", e); + } + } } return true; From 1edc6182ce67f8b6bb6549d55e7aa7c2248223d8 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 6 Aug 2023 16:38:04 +0200 Subject: [PATCH 003/141] Java 8 --- .../template/ExampleGraphTest.java | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java b/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java index 5578d7613..22e6a4255 100644 --- a/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java +++ b/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java @@ -32,28 +32,27 @@ class ExampleGraphTest { @Test void test() { - final Dataset dataset = datasetFrom(""" - PREFIX : + final Dataset dataset = datasetFrom("" + + "PREFIX : \n" + + "\n" + + "[\n" + + " a :C ;\n" + + " :p1 [\n" + + " :p2 \"XXX\" ;\n" + + " ] ;\n" + + "] .\n"); - [ - a :C ; - :p1 [ - :p2 "XXX" ; - ] ; - ] . - """); - - final var wrap = ExampleDataset.wrap(dataset); - final var graph = wrap.getGraph(); - final var resource = graph.getResource(); - final var p1 = resource.getP1(); - final var p2 = p1.getP2(); + final ExampleDataset wrap = ExampleDataset.wrap(dataset); + final ExampleGraph graph = wrap.getGraph(); + final ExampleNode1 resource = graph.getResource(); + final ExampleNode2 p1 = resource.getP1(); + final String p2 = p1.getP2(); System.out.println(p2); } private static Dataset datasetFrom(final String rdf) { - final var dataset = DatasetFactory.create(); + final Dataset dataset = DatasetFactory.create(); RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); return dataset; } From 9e16a120d81bf93b60778464a1547bbc4ffebffc Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 6 Aug 2023 16:38:36 +0200 Subject: [PATCH 004/141] Add example of nested wrapper interface --- .../template/ExampleI1$ExampleI2_$impl.java | 47 +++++++++++++++++++ .../declarative/template/ExampleI1.java | 12 +++++ .../template/ExampleGraphTest.java | 5 ++ 3 files changed, 64 insertions(+) create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java create mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java new file mode 100644 index 000000000..3323960d3 --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java @@ -0,0 +1,47 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.template; + +import javax.annotation.processing.Generated; + +import org.apache.jena.query.Dataset; +import org.apache.jena.sparql.core.DatasetGraph; +import org.apache.jena.sparql.core.DatasetGraphFactory; +import org.apache.jena.sparql.core.DatasetImpl; + +/** + * Warning this class consists of generated code. + */ +@Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") +public class ExampleI1$ExampleI2_$impl extends DatasetImpl implements ExampleI1.ExampleI2 { + + protected ExampleI1$ExampleI2_$impl(final DatasetGraph original) { + super(original); + } + + public static ExampleI1.ExampleI2 wrap(final Dataset original) { + return new ExampleI1$ExampleI2_$impl(original.asDatasetGraph()); + } + + public static ExampleI1.ExampleI2 create() { + return new ExampleI1$ExampleI2_$impl(DatasetGraphFactory.create()); + } +} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java new file mode 100644 index 000000000..a8ccb7562 --- /dev/null +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java @@ -0,0 +1,12 @@ +package com.inrupt.rdf.wrapping.declarative.template; + +import org.apache.jena.query.Dataset; + +public interface ExampleI1 { + interface ExampleI2 { + static ExampleI2 wrap(final Dataset original) { + return Manager.wrap(ExampleI2.class, original); + } + + } +} diff --git a/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java b/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java index 22e6a4255..18780ef83 100644 --- a/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java +++ b/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java @@ -51,6 +51,11 @@ void test() { System.out.println(p2); } + @Test + void test2() { + final ExampleI1.ExampleI2 wrap = ExampleI1.ExampleI2.wrap(DatasetFactory.create()); + } + private static Dataset datasetFrom(final String rdf) { final Dataset dataset = DatasetFactory.create(); RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); From 1be858c4004823c23afb40c5c1b8ed7c841955ff Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 6 Aug 2023 16:40:10 +0200 Subject: [PATCH 005/141] Tidy --- declarative/processor/pom.xml | 8 -------- .../wrapping/declarative/processor/Processor.java | 13 +------------ .../declarative/template/ExampleNode1_$impl.java | 3 +-- .../declarative/template/ExampleNode2_$impl.java | 3 +-- 4 files changed, 3 insertions(+), 24 deletions(-) diff --git a/declarative/processor/pom.xml b/declarative/processor/pom.xml index 442c3b455..e69167d20 100644 --- a/declarative/processor/pom.xml +++ b/declarative/processor/pom.xml @@ -16,8 +16,6 @@ 1.8 1.8 - - 3.0.1.Final @@ -27,12 +25,6 @@ ${project.version} - - org.jboss.logmanager - jboss-logmanager - ${jboss.logmanager.version} - - org.junit.jupiter junit-jupiter-api diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index 410b9a7cc..15a259b3e 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -45,23 +45,12 @@ public class Processor extends AbstractProcessor { public boolean process(final Set annotations, final RoundEnvironment roundEnv) { if (roundEnv.processingOver()) { processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "processing over"); - return true; - } - - if (annotations.isEmpty()) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "annotations empty"); - return true; + return false; } for (TypeElement annotation : annotations) { processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("annotation [%s]", annotation), annotation); - // TODO: Just to get started - if (!"com.inrupt.rdf.wrapping.declarative.annotations.Resource".equals(annotation.getQualifiedName().toString())) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("skipping [%s]", annotation), annotation); - continue; - } - final Set annotatedElements = roundEnv.getElementsAnnotatedWith(annotation); for (Element annotatedElement : annotatedElements) { processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("annotatedElement [%s]", annotatedElement), annotatedElement); diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java index 9564cb17e..d6f7017d7 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -import static org.apache.jena.rdf.model.ResourceFactory.*; +import static org.apache.jena.rdf.model.ResourceFactory.createProperty; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; import com.inrupt.rdf.wrapping.jena.ValueMappings; @@ -31,7 +31,6 @@ import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.enhanced.Implementation; import org.apache.jena.graph.Node; -import org.apache.jena.rdf.model.ResourceFactory; /** * Warning this class consists of generated code. diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java index 10b045ab8..8e05db159 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -import static org.apache.jena.rdf.model.ResourceFactory.*; +import static org.apache.jena.rdf.model.ResourceFactory.createProperty; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; import com.inrupt.rdf.wrapping.jena.ValueMappings; @@ -31,7 +31,6 @@ import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.enhanced.Implementation; import org.apache.jena.graph.Node; -import org.apache.jena.rdf.model.ResourceFactory; /** * Warning this class consists of generated code. From 2b9872a14b50f48a06da00de001540367714e209 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 6 Aug 2023 16:40:39 +0200 Subject: [PATCH 006/141] Generate some more --- .../declarative/processor/Processor.java | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index 15a259b3e..b8eb6c8e5 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.PrintWriter; +import java.time.Instant; import java.util.Set; import javax.annotation.processing.AbstractProcessor; @@ -56,7 +57,15 @@ public boolean process(final Set annotations, final Round processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("annotatedElement [%s]", annotatedElement), annotatedElement); final TypeElement annotatedType = (TypeElement) annotatedElement; - final String qualifiedName = annotatedType.getQualifiedName().toString() + "_$impl"; + final String originalInterfaceName = annotatedType.getQualifiedName().toString(); + final String originalBinaryName = processingEnv.getElementUtils().getBinaryName(annotatedType).toString(); + final String qualifiedName = originalBinaryName + "_$impl"; + final int lastDot = originalBinaryName.lastIndexOf('.'); + final String implementationClassName = qualifiedName.substring(lastDot + 1); + String packageName = null; + if (lastDot > 0) { + packageName = originalBinaryName.substring(0, lastDot); + } final JavaFileObject builderFile; try { @@ -67,7 +76,31 @@ public boolean process(final Set annotations, final Round try (PrintWriter out = new PrintWriter(builderFile.openWriter())) { // This should surely be a framework like JDeparser - out.println("generated"); + if (packageName != null) { + out.print("package "); + out.print(packageName); + out.println(";"); + out.println(); + } + + out.println("import javax.annotation.processing.Generated;"); + out.println(); + + out.println("/**"); + out.println(" * Warning this class consists of generated code."); + out.println(" */"); + + out.print("@Generated(value = \""); + out.print(this.getClass().getName()); + out.print("\", date = \""); + out.print(Instant.now()); + out.println("\")"); + + out.print("public class "); + out.print(implementationClassName); + out.print(" implements "); + out.print(originalInterfaceName); + out.println(" {}"); } catch (IOException e) { throw new RuntimeException("could not open writer", e); } From 03df5641e460a74456b0cb4da617d32a4b4e11a4 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 6 Aug 2023 17:44:28 +0200 Subject: [PATCH 007/141] Generate files that compile for three annotations --- declarative/processor/pom.xml | 5 + .../declarative/processor/Processor.java | 130 +++++++++++++++--- 2 files changed, 117 insertions(+), 18 deletions(-) diff --git a/declarative/processor/pom.xml b/declarative/processor/pom.xml index e69167d20..9ac62fb2b 100644 --- a/declarative/processor/pom.xml +++ b/declarative/processor/pom.xml @@ -24,6 +24,11 @@ inrupt-rdf-wrapping-declarative-annotations ${project.version} + + com.inrupt.rdf + inrupt-rdf-wrapping-jena + ${project.version} + org.junit.jupiter diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index b8eb6c8e5..bc7ee40a8 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -83,24 +83,20 @@ public boolean process(final Set annotations, final Round out.println(); } - out.println("import javax.annotation.processing.Generated;"); - out.println(); - - out.println("/**"); - out.println(" * Warning this class consists of generated code."); - out.println(" */"); - - out.print("@Generated(value = \""); - out.print(this.getClass().getName()); - out.print("\", date = \""); - out.print(Instant.now()); - out.println("\")"); - - out.print("public class "); - out.print(implementationClassName); - out.print(" implements "); - out.print(originalInterfaceName); - out.println(" {}"); + switch (annotation.getQualifiedName().toString()) { + case "com.inrupt.rdf.wrapping.declarative.annotations.Dataset": + printDataset(originalInterfaceName, implementationClassName, out); + break; + case "com.inrupt.rdf.wrapping.declarative.annotations.Graph": + printGraph(originalInterfaceName, implementationClassName, out); + break; + case "com.inrupt.rdf.wrapping.declarative.annotations.Resource": + printResource(originalInterfaceName, implementationClassName, out); + break; + + } + + } catch (IOException e) { throw new RuntimeException("could not open writer", e); } @@ -109,4 +105,102 @@ public boolean process(final Set annotations, final Round return true; } + + private void printDataset(final String originalInterfaceName, final String implementationClassName, final PrintWriter out) { + out.println("import javax.annotation.processing.Generated;"); + out.println(); + out.println("import org.apache.jena.sparql.core.DatasetGraph;"); + out.println("import org.apache.jena.sparql.core.DatasetImpl;"); + out.println(); + + printJavadoc(out); + printGenerated(out); + + out.print("public class "); + out.print(implementationClassName); + out.print(" extends DatasetImpl implements "); + out.print(originalInterfaceName); + out.println(" {"); + + out.print(" protected "); + out.print(implementationClassName); + out.println("(final DatasetGraph original) {"); + out.println(" super(original);"); + out.println(" }"); + + out.println("}"); + } + + private void printGraph(final String originalInterfaceName, final String implementationClassName, final PrintWriter out) { + out.println("import javax.annotation.processing.Generated;"); + out.println(); + out.println("import org.apache.jena.graph.Graph;"); + out.println("import org.apache.jena.rdf.model.impl.ModelCom;"); + out.println(); + + printJavadoc(out); + printGenerated(out); + + out.print("public class "); + out.print(implementationClassName); + out.print(" extends ModelCom implements "); + out.print(originalInterfaceName); + out.println(" {"); + + out.print(" protected "); + out.print(implementationClassName); + out.println("(final Graph original) {"); + out.println(" super(original);"); + out.println(" }"); + + out.println("}"); + } + + private void printResource(final String originalInterfaceName, final String implementationClassName, final PrintWriter out) { + out.println("import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory;"); + out.println("import com.inrupt.rdf.wrapping.jena.WrapperResource;"); + out.println(); + out.println("import javax.annotation.processing.Generated;"); + out.println(); + out.println("import org.apache.jena.enhanced.EnhGraph;"); + out.println("import org.apache.jena.enhanced.Implementation;"); + out.println("import org.apache.jena.graph.Node;"); + out.println(); + + printJavadoc(out); + printGenerated(out); + + out.print("public class "); + out.print(implementationClassName); + out.print(" extends WrapperResource implements "); + out.print(originalInterfaceName); + out.println(" {"); + + out.print(" static final Implementation factory = new UriOrBlankFactory("); + out.print(implementationClassName); + out.println("::new);"); + out.println(); + + out.print(" protected "); + out.print(implementationClassName); + out.println("(final Node node, final EnhGraph graph) {"); + out.println(" super(node, graph);"); + out.println(" }"); + + out.println("}"); + } + + private void printGenerated(final PrintWriter out) { + out.print("@Generated(value = \""); + out.print(this.getClass().getName()); + out.print("\", date = \""); + out.print(Instant.now()); + out.println("\")"); + } + + private static void printJavadoc(final PrintWriter out) { + out.println("/**"); + out.println(" * Warning this class consists of generated code."); + out.println(" */"); + } } From f15dd4d15fcc2ebb9a5c34037471a191719ddabe Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 6 Aug 2023 17:52:40 +0200 Subject: [PATCH 008/141] Tidy --- .../declarative/processor/Processor.java | 34 ++++++++++++++----- declarative/template/pom.xml | 16 +++++++-- .../declarative/template/ExampleI1.java | 20 +++++++++++ .../declarative/template/ExampleNode1.java | 20 +++++++++++ .../template/ExampleNode1_$impl.java | 2 +- .../declarative/template/ExampleNode2.java | 5 ++- .../template/ExampleNode2_$impl.java | 2 +- .../declarative/template/Manager.java | 6 ++-- .../declarative/template/package-info.java | 2 +- declarative/test/pom.xml | 7 ++++ 10 files changed, 96 insertions(+), 18 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index bc7ee40a8..cb878ace3 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -36,9 +36,9 @@ import javax.tools.JavaFileObject; @SupportedAnnotationTypes({ - "com.inrupt.rdf.wrapping.declarative.annotations.Dataset", - "com.inrupt.rdf.wrapping.declarative.annotations.Graph", - "com.inrupt.rdf.wrapping.declarative.annotations.Resource" + "com.inrupt.rdf.wrapping.declarative.annotations.Dataset", + "com.inrupt.rdf.wrapping.declarative.annotations.Graph", + "com.inrupt.rdf.wrapping.declarative.annotations.Resource" }) @SupportedSourceVersion(SourceVersion.RELEASE_8) public class Processor extends AbstractProcessor { @@ -50,15 +50,22 @@ public boolean process(final Set annotations, final Round } for (TypeElement annotation : annotations) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("annotation [%s]", annotation), annotation); + processingEnv.getMessager().printMessage( + Diagnostic.Kind.NOTE, + String.format("annotation [%s]", annotation), annotation); final Set annotatedElements = roundEnv.getElementsAnnotatedWith(annotation); for (Element annotatedElement : annotatedElements) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format("annotatedElement [%s]", annotatedElement), annotatedElement); + processingEnv.getMessager().printMessage( + Diagnostic.Kind.NOTE, + String.format("annotatedElement [%s]", annotatedElement), annotatedElement); final TypeElement annotatedType = (TypeElement) annotatedElement; final String originalInterfaceName = annotatedType.getQualifiedName().toString(); - final String originalBinaryName = processingEnv.getElementUtils().getBinaryName(annotatedType).toString(); + final String originalBinaryName = processingEnv + .getElementUtils() + .getBinaryName(annotatedType) + .toString(); final String qualifiedName = originalBinaryName + "_$impl"; final int lastDot = originalBinaryName.lastIndexOf('.'); final String implementationClassName = qualifiedName.substring(lastDot + 1); @@ -106,7 +113,10 @@ public boolean process(final Set annotations, final Round return true; } - private void printDataset(final String originalInterfaceName, final String implementationClassName, final PrintWriter out) { + private void printDataset( + final String originalInterfaceName, + final String implementationClassName, + final PrintWriter out) { out.println("import javax.annotation.processing.Generated;"); out.println(); out.println("import org.apache.jena.sparql.core.DatasetGraph;"); @@ -131,7 +141,10 @@ private void printDataset(final String originalInterfaceName, final String imple out.println("}"); } - private void printGraph(final String originalInterfaceName, final String implementationClassName, final PrintWriter out) { + private void printGraph( + final String originalInterfaceName, + final String implementationClassName, + final PrintWriter out) { out.println("import javax.annotation.processing.Generated;"); out.println(); out.println("import org.apache.jena.graph.Graph;"); @@ -156,7 +169,10 @@ private void printGraph(final String originalInterfaceName, final String impleme out.println("}"); } - private void printResource(final String originalInterfaceName, final String implementationClassName, final PrintWriter out) { + private void printResource( + final String originalInterfaceName, + final String implementationClassName, + final PrintWriter out) { out.println("import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory;"); out.println("import com.inrupt.rdf.wrapping.jena.WrapperResource;"); out.println(); diff --git a/declarative/template/pom.xml b/declarative/template/pom.xml index ce9de407d..21277eb85 100644 --- a/declarative/template/pom.xml +++ b/declarative/template/pom.xml @@ -15,8 +15,8 @@ - 17 - 17 + 1.8 + 1.8 @@ -32,4 +32,16 @@ test + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java index a8ccb7562..7c4c60c9c 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java @@ -1,3 +1,23 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ package com.inrupt.rdf.wrapping.declarative.template; import org.apache.jena.query.Dataset; diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java index b84325c35..fd3a934b0 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java @@ -1,3 +1,23 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ package com.inrupt.rdf.wrapping.declarative.template; // @Resource diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java index d6f7017d7..ebb82bb94 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java @@ -39,7 +39,7 @@ public class ExampleNode1_$impl extends WrapperResource implements ExampleNode1 { static final Implementation factory = new UriOrBlankFactory(ExampleNode1_$impl::new); - protected ExampleNode1_$impl(Node node, EnhGraph model) { + protected ExampleNode1_$impl(final Node node, final EnhGraph model) { super(node, model); } diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java index c8af94dff..46b31aa57 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java @@ -22,6 +22,9 @@ // @Resource public interface ExampleNode2 { - // @Property(predicate = "urn:example:p2", type = PropertyMappingTypes.anyOrNull, mapping = ValueMappingTypes.literalAsString) + // @Property( + // predicate = "urn:example:p2", + // type = PropertyMappingTypes.anyOrNull, + // mapping = ValueMappingTypes.literalAsString) String getP2(); } diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java index 8e05db159..0a2b4eef8 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java @@ -39,7 +39,7 @@ public class ExampleNode2_$impl extends WrapperResource implements ExampleNode2 { static final Implementation factory = new UriOrBlankFactory(ExampleNode2_$impl::new); - protected ExampleNode2_$impl(Node node, EnhGraph model) { + protected ExampleNode2_$impl(final Node node, final EnhGraph model) { super(node, model); } diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java index d225d2d3a..885516512 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java @@ -27,7 +27,7 @@ import org.apache.jena.rdf.model.Model; /** - * A utility class that aids wrapper interfaces to find generated implementations + * A utility class that aids wrapper interfaces to find generated implementations. */ // TODO: Move to processor module // TODO: Should this be SPI? @@ -43,11 +43,11 @@ public static T wrap(final Class type, final Dataset original) { return wrap(type, original, Dataset.class); } - private static T wrap(final Class type, final Object original, Class xtype) { + private static T wrap(final Class type, final Object original, final Class xtype) { final ClassLoader classLoader = type.getClassLoader(); final String implTypeName = type.getName() + "_$impl"; - Class implClass; + final Class implClass; try { implClass = Class.forName(implTypeName, true, classLoader).asSubclass(type); } catch (ClassNotFoundException e) { diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java index cb90dd82b..b70d996e4 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java @@ -20,6 +20,6 @@ */ /** - * Examples of wrapper interfaces and the implementations the Processor should generate from them + * Examples of wrapper interfaces and the implementations the Processor should generate from them. */ package com.inrupt.rdf.wrapping.declarative.template; diff --git a/declarative/test/pom.xml b/declarative/test/pom.xml index 5939a9bbb..753379c94 100644 --- a/declarative/test/pom.xml +++ b/declarative/test/pom.xml @@ -44,6 +44,13 @@ org.jacoco jacoco-maven-plugin + + org.apache.maven.plugins + maven-deploy-plugin + + true + + From a7f2d4337459a6cfde81cb019f42fd4479ca932a Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 12 Aug 2023 10:41:01 +0200 Subject: [PATCH 009/141] Style --- declarative/processor/pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/declarative/processor/pom.xml b/declarative/processor/pom.xml index 9ac62fb2b..ea7e83dd4 100644 --- a/declarative/processor/pom.xml +++ b/declarative/processor/pom.xml @@ -43,7 +43,8 @@ org.apache.maven.plugins maven-compiler-plugin - + + default-compile compile From 716cee202e728c6ad1ec7a755a202c9ab1f4b698 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 12 Aug 2023 10:43:54 +0200 Subject: [PATCH 010/141] Java 8 compatible Generated annotation --- declarative/processor/pom.xml | 4 ++++ .../rdf/wrapping/declarative/processor/Processor.java | 6 +++--- declarative/template/pom.xml | 4 ++++ .../declarative/template/ExampleDataset_$impl.java | 2 +- .../wrapping/declarative/template/ExampleGraph_$impl.java | 2 +- .../declarative/template/ExampleI1$ExampleI2_$impl.java | 2 +- .../wrapping/declarative/template/ExampleNode1_$impl.java | 2 +- .../wrapping/declarative/template/ExampleNode2_$impl.java | 2 +- pom.xml | 8 ++++++++ 9 files changed, 24 insertions(+), 8 deletions(-) diff --git a/declarative/processor/pom.xml b/declarative/processor/pom.xml index ea7e83dd4..f0af45347 100644 --- a/declarative/processor/pom.xml +++ b/declarative/processor/pom.xml @@ -29,6 +29,10 @@ inrupt-rdf-wrapping-jena ${project.version} + + javax.annotation + javax.annotation-api + org.junit.jupiter diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index cb878ace3..3aae4a621 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -117,7 +117,7 @@ private void printDataset( final String originalInterfaceName, final String implementationClassName, final PrintWriter out) { - out.println("import javax.annotation.processing.Generated;"); + out.println("import javax.annotation.Generated;"); out.println(); out.println("import org.apache.jena.sparql.core.DatasetGraph;"); out.println("import org.apache.jena.sparql.core.DatasetImpl;"); @@ -145,7 +145,7 @@ private void printGraph( final String originalInterfaceName, final String implementationClassName, final PrintWriter out) { - out.println("import javax.annotation.processing.Generated;"); + out.println("import javax.annotation.Generated;"); out.println(); out.println("import org.apache.jena.graph.Graph;"); out.println("import org.apache.jena.rdf.model.impl.ModelCom;"); @@ -176,7 +176,7 @@ private void printResource( out.println("import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory;"); out.println("import com.inrupt.rdf.wrapping.jena.WrapperResource;"); out.println(); - out.println("import javax.annotation.processing.Generated;"); + out.println("import javax.annotation.Generated;"); out.println(); out.println("import org.apache.jena.enhanced.EnhGraph;"); out.println("import org.apache.jena.enhanced.Implementation;"); diff --git a/declarative/template/pom.xml b/declarative/template/pom.xml index 21277eb85..c71ea900a 100644 --- a/declarative/template/pom.xml +++ b/declarative/template/pom.xml @@ -25,6 +25,10 @@ inrupt-rdf-wrapping-jena ${project.version} + + javax.annotation + javax.annotation-api + org.junit.jupiter diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java index 586b6640c..d380b7d17 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -import javax.annotation.processing.Generated; +import javax.annotation.Generated; import org.apache.jena.query.Dataset; import org.apache.jena.sparql.core.DatasetGraph; diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java index 3bff32501..7b4789857 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -import javax.annotation.processing.Generated; +import javax.annotation.Generated; import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java index 3323960d3..4794e6a9a 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -import javax.annotation.processing.Generated; +import javax.annotation.Generated; import org.apache.jena.query.Dataset; import org.apache.jena.sparql.core.DatasetGraph; diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java index ebb82bb94..d7e7badd3 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java @@ -26,7 +26,7 @@ import com.inrupt.rdf.wrapping.jena.ValueMappings; import com.inrupt.rdf.wrapping.jena.WrapperResource; -import javax.annotation.processing.Generated; +import javax.annotation.Generated; import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.enhanced.Implementation; diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java index 0a2b4eef8..e10e2c82e 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java @@ -26,7 +26,7 @@ import com.inrupt.rdf.wrapping.jena.ValueMappings; import com.inrupt.rdf.wrapping.jena.WrapperResource; -import javax.annotation.processing.Generated; +import javax.annotation.Generated; import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.enhanced.Implementation; diff --git a/pom.xml b/pom.xml index f6d06805f..e7784dedf 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ 4.3.4 4.9.0 0.6.0 + 1.3.2 3.3.0 @@ -117,6 +118,13 @@ jena-commonsrdf ${jena.version} + + javax.annotation + javax.annotation-api + ${javax.annotation.version} + + + com.google.guava From c79ac9a5d36e47627c0b90f2cafad76b07a65cb2 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 12 Aug 2023 10:50:24 +0200 Subject: [PATCH 011/141] Move manager to processing module --- .../declarative/processor}/Manager.java | 23 +++++++++---------- declarative/template/pom.xml | 22 ++++++++++++++++-- .../declarative/template/ExampleDataset.java | 9 ++++---- .../declarative/template/ExampleGraph.java | 7 ++++-- .../declarative/template/ExampleI1.java | 4 +++- .../declarative/template/ExampleNode1.java | 4 +++- .../declarative/template/ExampleNode2.java | 4 +++- 7 files changed, 50 insertions(+), 23 deletions(-) rename declarative/{template/src/main/java/com/inrupt/rdf/wrapping/declarative/template => processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor}/Manager.java (76%) diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Manager.java similarity index 76% rename from declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java rename to declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Manager.java index 885516512..dd7795a34 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/Manager.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Manager.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.template; +package com.inrupt.rdf.wrapping.declarative.processor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -29,27 +29,26 @@ /** * A utility class that aids wrapper interfaces to find generated implementations. */ -// TODO: Move to processor module // TODO: Should this be SPI? public final class Manager { private Manager() { } - public static T wrap(final Class type, final Model original) { - return wrap(type, original, Model.class); + public static T wrap(final Model original, final Class interfaceType) { + return wrap(original, interfaceType, Model.class); } - public static T wrap(final Class type, final Dataset original) { - return wrap(type, original, Dataset.class); + public static T wrap(final Dataset original, final Class interfaceType) { + return wrap(original, interfaceType, Dataset.class); } - private static T wrap(final Class type, final Object original, final Class xtype) { - final ClassLoader classLoader = type.getClassLoader(); - final String implTypeName = type.getName() + "_$impl"; + private static T wrap(final Object original, final Class interfaceType, final Class parameterType) { + final ClassLoader classLoader = interfaceType.getClassLoader(); + final String implTypeName = interfaceType.getName() + "_$impl"; final Class implClass; try { - implClass = Class.forName(implTypeName, true, classLoader).asSubclass(type); + implClass = Class.forName(implTypeName, true, classLoader).asSubclass(interfaceType); } catch (ClassNotFoundException e) { throw new RuntimeException("implementation not found", e); } catch (ClassCastException e) { @@ -60,13 +59,13 @@ private static T wrap(final Class type, final Object original, final Clas final Method wrapMethod; try { - wrapMethod = implClass.getMethod("wrap", xtype); + wrapMethod = implClass.getMethod("wrap", parameterType); } catch (NoSuchMethodException e) { throw new RuntimeException("wrap method not found", e); } try { - return type.cast(wrapMethod.invoke(null, original)); + return interfaceType.cast(wrapMethod.invoke(null, original)); } catch (IllegalAccessException e) { throw new RuntimeException("wrap method inaccessible", e); } catch (InvocationTargetException e) { diff --git a/declarative/template/pom.xml b/declarative/template/pom.xml index c71ea900a..12a6178de 100644 --- a/declarative/template/pom.xml +++ b/declarative/template/pom.xml @@ -26,8 +26,9 @@ ${project.version} - javax.annotation - javax.annotation-api + com.inrupt.rdf + inrupt-rdf-wrapping-declarative-processor + ${project.version} @@ -46,6 +47,23 @@ true + + org.apache.maven.plugins + maven-compiler-plugin + + + + default-compile + compile + + compile + + + -proc:none + + + + diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java index 82e41a0c5..07504f8cf 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java @@ -20,12 +20,13 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -import org.apache.jena.query.Dataset; +import com.inrupt.rdf.wrapping.declarative.annotations.Dataset; +import com.inrupt.rdf.wrapping.declarative.processor.Manager; -// @Dataset +@Dataset public interface ExampleDataset { - static ExampleDataset wrap(final Dataset original) { - return Manager.wrap(ExampleDataset.class, original); + static ExampleDataset wrap(final org.apache.jena.query.Dataset original) { + return Manager.wrap(original, ExampleDataset.class); } // @DefaultGraph diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java index 534360337..1a31effcc 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java @@ -20,12 +20,15 @@ */ package com.inrupt.rdf.wrapping.declarative.template; +import com.inrupt.rdf.wrapping.declarative.annotations.Graph; +import com.inrupt.rdf.wrapping.declarative.processor.Manager; + import org.apache.jena.rdf.model.Model; -// @Graph +@Graph public interface ExampleGraph { static ExampleGraph wrap(final Model original) { - return Manager.wrap(ExampleGraph.class, original); + return Manager.wrap(original, ExampleGraph.class); } // @FirstSubjectOf(RDF.type, "urn:example:C") diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java index 7c4c60c9c..22317af2b 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java @@ -20,12 +20,14 @@ */ package com.inrupt.rdf.wrapping.declarative.template; +import com.inrupt.rdf.wrapping.declarative.processor.Manager; + import org.apache.jena.query.Dataset; public interface ExampleI1 { interface ExampleI2 { static ExampleI2 wrap(final Dataset original) { - return Manager.wrap(ExampleI2.class, original); + return Manager.wrap(original, ExampleI2.class); } } diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java index fd3a934b0..611722e75 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java @@ -20,7 +20,9 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -// @Resource +import com.inrupt.rdf.wrapping.declarative.annotations.Resource; + +@Resource public interface ExampleNode1 { // @Property(predicate = "urn:example:p1", type = PropertyMappingTypes.anyOrNull, mapping = ValueMappingTypes.as) ExampleNode2 getP1(); diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java index 46b31aa57..c98452655 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java @@ -20,7 +20,9 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -// @Resource +import com.inrupt.rdf.wrapping.declarative.annotations.Resource; + +@Resource public interface ExampleNode2 { // @Property( // predicate = "urn:example:p2", From 7864296a129c4583292c494cb02829c75fecefaa Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 12 Aug 2023 10:51:03 +0200 Subject: [PATCH 012/141] Generate dataset wrap method --- .../declarative/processor/Processor.java | 10 ++++++ declarative/test/pom.xml | 5 +++ .../rdf/wrapping/declarative/test/X.java | 5 +++ .../rdf/wrapping/declarative/test/XTest.java | 35 +++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index 3aae4a621..7e997ea6a 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -119,6 +119,7 @@ private void printDataset( final PrintWriter out) { out.println("import javax.annotation.Generated;"); out.println(); + out.println("import org.apache.jena.query.Dataset;"); out.println("import org.apache.jena.sparql.core.DatasetGraph;"); out.println("import org.apache.jena.sparql.core.DatasetImpl;"); out.println(); @@ -137,6 +138,15 @@ private void printDataset( out.println("(final DatasetGraph original) {"); out.println(" super(original);"); out.println(" }"); + out.println(); + + out.print(" public static "); + out.print(originalInterfaceName); + out.println(" wrap(final Dataset original) {"); + out.print(" return new "); + out.print(implementationClassName); + out.println("(original.asDatasetGraph());"); + out.println(" }"); out.println("}"); } diff --git a/declarative/test/pom.xml b/declarative/test/pom.xml index 753379c94..60eb8573d 100644 --- a/declarative/test/pom.xml +++ b/declarative/test/pom.xml @@ -32,6 +32,11 @@ junit-jupiter-api test + + org.hamcrest + hamcrest + test + diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java index cec990e5e..f534244f3 100644 --- a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java +++ b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java @@ -23,9 +23,14 @@ import com.inrupt.rdf.wrapping.declarative.annotations.Dataset; import com.inrupt.rdf.wrapping.declarative.annotations.Graph; import com.inrupt.rdf.wrapping.declarative.annotations.Resource; +import com.inrupt.rdf.wrapping.declarative.processor.Manager; @Dataset public interface X { + static X wrap(final org.apache.jena.query.Dataset original) { + return Manager.wrap(original, X.class); + } + @Graph interface Y { @Resource diff --git a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java new file mode 100644 index 000000000..b5ee786d9 --- /dev/null +++ b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java @@ -0,0 +1,35 @@ +package com.inrupt.rdf.wrapping.declarative.test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import com.github.jsonldjava.shaded.com.google.common.base.Charsets; + +import org.apache.commons.io.IOUtils; +import org.apache.jena.query.Dataset; +import org.apache.jena.query.DatasetFactory; +import org.apache.jena.riot.Lang; +import org.apache.jena.riot.RDFDataMgr; +import org.junit.jupiter.api.Test; + +class XTest { + @Test + void datasetCanWrap() { + final Dataset dataset = datasetFrom("" + + "PREFIX : \n" + + "\n" + + "[\n" + + " a :C ;\n" + + " :p1 [\n" + + " :p2 \"XXX\" ;\n" + + " ] ;\n" + + "] .\n"); + + assertDoesNotThrow(() -> X.wrap(dataset)); + } + + private static Dataset datasetFrom(final String rdf) { + final Dataset dataset = DatasetFactory.create(); + RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); + return dataset; + } +} From bb1816ddac6cbcae9d823e97ca9ef03d41c2637b Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 12 Aug 2023 10:57:24 +0200 Subject: [PATCH 013/141] Generate graph wrap method --- .../declarative/processor/Processor.java | 10 ++++++++ .../rdf/wrapping/declarative/test/X.java | 6 +++++ .../rdf/wrapping/declarative/test/XTest.java | 23 +++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index 7e997ea6a..65685ecfd 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -158,6 +158,7 @@ private void printGraph( out.println("import javax.annotation.Generated;"); out.println(); out.println("import org.apache.jena.graph.Graph;"); + out.println("import org.apache.jena.rdf.model.Model;"); out.println("import org.apache.jena.rdf.model.impl.ModelCom;"); out.println(); @@ -175,6 +176,15 @@ private void printGraph( out.println("(final Graph original) {"); out.println(" super(original);"); out.println(" }"); + out.println(); + + out.print(" public static "); + out.print(originalInterfaceName); + out.println(" wrap(final Model original) {"); + out.print(" return new "); + out.print(implementationClassName); + out.println("(original.getGraph());"); + out.println(" }"); out.println("}"); } diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java index f534244f3..7351e1e80 100644 --- a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java +++ b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java @@ -25,6 +25,8 @@ import com.inrupt.rdf.wrapping.declarative.annotations.Resource; import com.inrupt.rdf.wrapping.declarative.processor.Manager; +import org.apache.jena.rdf.model.Model; + @Dataset public interface X { static X wrap(final org.apache.jena.query.Dataset original) { @@ -33,6 +35,10 @@ static X wrap(final org.apache.jena.query.Dataset original) { @Graph interface Y { + static Y wrap(final Model original) { + return Manager.wrap(original, Y.class); + } + @Resource interface Z { } diff --git a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java index b5ee786d9..77943ccfe 100644 --- a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java +++ b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java @@ -7,6 +7,8 @@ import org.apache.commons.io.IOUtils; import org.apache.jena.query.Dataset; import org.apache.jena.query.DatasetFactory; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFDataMgr; import org.junit.jupiter.api.Test; @@ -27,9 +29,30 @@ void datasetCanWrap() { assertDoesNotThrow(() -> X.wrap(dataset)); } + @Test + void graphCanWrap() { + final Model model = modelFrom("" + + "PREFIX : \n" + + "\n" + + "[\n" + + " a :C ;\n" + + " :p1 [\n" + + " :p2 \"XXX\" ;\n" + + " ] ;\n" + + "] .\n"); + + assertDoesNotThrow(() -> X.Y.wrap(model)); + } + private static Dataset datasetFrom(final String rdf) { final Dataset dataset = DatasetFactory.create(); RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); return dataset; } + + private static Model modelFrom(final String rdf) { + final Model model = ModelFactory.createDefaultModel(); + RDFDataMgr.read(model, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); + return model; + } } From bc0355432e24fa504fecf812128d2e383d2ebffa Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 12 Aug 2023 12:49:10 +0200 Subject: [PATCH 014/141] Generate with JDeparser --- declarative/processor/pom.xml | 4 + .../declarative/processor/Processor.java | 232 +++++++----------- pom.xml | 7 +- 3 files changed, 100 insertions(+), 143 deletions(-) diff --git a/declarative/processor/pom.xml b/declarative/processor/pom.xml index f0af45347..e2881da8d 100644 --- a/declarative/processor/pom.xml +++ b/declarative/processor/pom.xml @@ -33,6 +33,10 @@ javax.annotation javax.annotation-api + + org.jboss.jdeparser + jdeparser + org.junit.jupiter diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index 65685ecfd..b5774a6fc 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -20,11 +20,17 @@ */ package com.inrupt.rdf.wrapping.declarative.processor; +import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JTypes.$t; + +import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; +import com.inrupt.rdf.wrapping.jena.WrapperResource; + import java.io.IOException; -import java.io.PrintWriter; import java.time.Instant; import java.util.Set; +import javax.annotation.Generated; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; @@ -33,7 +39,17 @@ import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; + +import org.apache.jena.enhanced.EnhGraph; +import org.apache.jena.enhanced.Implementation; +import org.apache.jena.graph.Graph; +import org.apache.jena.graph.Node; +import org.apache.jena.query.Dataset; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.impl.ModelCom; +import org.apache.jena.sparql.core.DatasetGraph; +import org.apache.jena.sparql.core.DatasetImpl; +import org.jboss.jdeparser.*; @SupportedAnnotationTypes({ "com.inrupt.rdf.wrapping.declarative.annotations.Dataset", @@ -74,36 +90,24 @@ public boolean process(final Set annotations, final Round packageName = originalBinaryName.substring(0, lastDot); } - final JavaFileObject builderFile; - try { - builderFile = processingEnv.getFiler().createSourceFile(qualifiedName, annotatedElement); - } catch (IOException e) { - throw new RuntimeException("could not create class file", e); + final JFiler jFiler = JFiler.newInstance(processingEnv.getFiler()); + final JSources sources = JDeparser.createSources(jFiler, new FormatPreferences()); + final JSourceFile sourceFile = sources.createSourceFile(packageName, implementationClassName); + + switch (annotation.getQualifiedName().toString()) { + case "com.inrupt.rdf.wrapping.declarative.annotations.Dataset": + printDataset(originalInterfaceName, implementationClassName, sourceFile); + break; + case "com.inrupt.rdf.wrapping.declarative.annotations.Graph": + printGraph(originalInterfaceName, implementationClassName, sourceFile); + break; + case "com.inrupt.rdf.wrapping.declarative.annotations.Resource": + printResource(originalInterfaceName, implementationClassName, sourceFile); + break; } - try (PrintWriter out = new PrintWriter(builderFile.openWriter())) { - // This should surely be a framework like JDeparser - if (packageName != null) { - out.print("package "); - out.print(packageName); - out.println(";"); - out.println(); - } - - switch (annotation.getQualifiedName().toString()) { - case "com.inrupt.rdf.wrapping.declarative.annotations.Dataset": - printDataset(originalInterfaceName, implementationClassName, out); - break; - case "com.inrupt.rdf.wrapping.declarative.annotations.Graph": - printGraph(originalInterfaceName, implementationClassName, out); - break; - case "com.inrupt.rdf.wrapping.declarative.annotations.Resource": - printResource(originalInterfaceName, implementationClassName, out); - break; - - } - - + try { + sources.writeSources(); } catch (IOException e) { throw new RuntimeException("could not open writer", e); } @@ -116,127 +120,71 @@ public boolean process(final Set annotations, final Round private void printDataset( final String originalInterfaceName, final String implementationClassName, - final PrintWriter out) { - out.println("import javax.annotation.Generated;"); - out.println(); - out.println("import org.apache.jena.query.Dataset;"); - out.println("import org.apache.jena.sparql.core.DatasetGraph;"); - out.println("import org.apache.jena.sparql.core.DatasetImpl;"); - out.println(); - - printJavadoc(out); - printGenerated(out); - - out.print("public class "); - out.print(implementationClassName); - out.print(" extends DatasetImpl implements "); - out.print(originalInterfaceName); - out.println(" {"); - - out.print(" protected "); - out.print(implementationClassName); - out.println("(final DatasetGraph original) {"); - out.println(" super(original);"); - out.println(" }"); - out.println(); - - out.print(" public static "); - out.print(originalInterfaceName); - out.println(" wrap(final Dataset original) {"); - out.print(" return new "); - out.print(implementationClassName); - out.println("(original.asDatasetGraph());"); - out.println(" }"); - - out.println("}"); + final JSourceFile sourceFile) { + sourceFile._import(Generated.class); + sourceFile._import(Dataset.class); + sourceFile._import(DatasetGraph.class); + sourceFile._import(DatasetImpl.class); + + final JClassDef jClassDef = sourceFile._class(JMod.PUBLIC, implementationClassName); + jClassDef.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); + jClassDef.docComment().text("Warning, this class consists of generated code."); + jClassDef._extends(DatasetImpl.class)._implements(originalInterfaceName); + + final JMethodDef constructor = jClassDef.constructor(JMod.PROTECTED); + constructor.param(JMod.FINAL, DatasetGraph.class, "original"); + constructor.body().callSuper().arg($v("original")); + + final JMethodDef wrap = jClassDef.method(JMod.PUBLIC | JMod.STATIC, originalInterfaceName, "wrap"); + wrap.param(JMod.FINAL, Dataset.class, "original"); + wrap.body()._return($t(implementationClassName)._new().arg($v("original").call("asDatasetGraph"))); } private void printGraph( final String originalInterfaceName, final String implementationClassName, - final PrintWriter out) { - out.println("import javax.annotation.Generated;"); - out.println(); - out.println("import org.apache.jena.graph.Graph;"); - out.println("import org.apache.jena.rdf.model.Model;"); - out.println("import org.apache.jena.rdf.model.impl.ModelCom;"); - out.println(); - - printJavadoc(out); - printGenerated(out); - - out.print("public class "); - out.print(implementationClassName); - out.print(" extends ModelCom implements "); - out.print(originalInterfaceName); - out.println(" {"); - - out.print(" protected "); - out.print(implementationClassName); - out.println("(final Graph original) {"); - out.println(" super(original);"); - out.println(" }"); - out.println(); - - out.print(" public static "); - out.print(originalInterfaceName); - out.println(" wrap(final Model original) {"); - out.print(" return new "); - out.print(implementationClassName); - out.println("(original.getGraph());"); - out.println(" }"); - - out.println("}"); + final JSourceFile sourceFile) { + sourceFile._import(Generated.class); + sourceFile._import(Graph.class); + sourceFile._import(Model.class); + sourceFile._import(ModelCom.class); + + final JClassDef jClassDef = sourceFile._class(JMod.PUBLIC, implementationClassName); + jClassDef.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); + jClassDef.docComment().text("Warning, this class consists of generated code."); + jClassDef._extends(ModelCom.class)._implements(originalInterfaceName); + + final JMethodDef constructor = jClassDef.constructor(JMod.PROTECTED); + constructor.param(JMod.FINAL, Graph.class, "original"); + constructor.body().callSuper().arg($v("original")); + + final JMethodDef wrap = jClassDef.method(JMod.PUBLIC | JMod.STATIC, originalInterfaceName, "wrap"); + wrap.param(JMod.FINAL, Model.class, "original"); + wrap.body()._return($t(implementationClassName)._new().arg($v("original").call("getGraph"))); } private void printResource( final String originalInterfaceName, final String implementationClassName, - final PrintWriter out) { - out.println("import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory;"); - out.println("import com.inrupt.rdf.wrapping.jena.WrapperResource;"); - out.println(); - out.println("import javax.annotation.Generated;"); - out.println(); - out.println("import org.apache.jena.enhanced.EnhGraph;"); - out.println("import org.apache.jena.enhanced.Implementation;"); - out.println("import org.apache.jena.graph.Node;"); - out.println(); - - printJavadoc(out); - printGenerated(out); - - out.print("public class "); - out.print(implementationClassName); - out.print(" extends WrapperResource implements "); - out.print(originalInterfaceName); - out.println(" {"); - - out.print(" static final Implementation factory = new UriOrBlankFactory("); - out.print(implementationClassName); - out.println("::new);"); - out.println(); - - out.print(" protected "); - out.print(implementationClassName); - out.println("(final Node node, final EnhGraph graph) {"); - out.println(" super(node, graph);"); - out.println(" }"); - - out.println("}"); - } - - private void printGenerated(final PrintWriter out) { - out.print("@Generated(value = \""); - out.print(this.getClass().getName()); - out.print("\", date = \""); - out.print(Instant.now()); - out.println("\")"); - } - - private static void printJavadoc(final PrintWriter out) { - out.println("/**"); - out.println(" * Warning this class consists of generated code."); - out.println(" */"); + final JSourceFile sourceFile) { + sourceFile._import(UriOrBlankFactory.class); + sourceFile._import(WrapperResource.class); + sourceFile._import(Generated.class); + sourceFile._import(EnhGraph.class); + sourceFile._import(Implementation.class); + sourceFile._import(Node.class); + + final JClassDef jClassDef = sourceFile._class(JMod.PUBLIC, implementationClassName); + jClassDef.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); + jClassDef.docComment().text("Warning, this class consists of generated code."); + jClassDef._extends(WrapperResource.class)._implements(originalInterfaceName); + + jClassDef.field(JMod.STATIC | JMod.FINAL, Implementation.class, "factory", $t(UriOrBlankFactory.class)._new().arg($t(implementationClassName).methodRef("new"))); + final JMethodDef constructor = jClassDef.constructor(JMod.PROTECTED); + constructor.param(JMod.FINAL, Node.class, "node"); + constructor.param(JMod.FINAL, EnhGraph.class, "graph"); + final JCall jCall = constructor.body().callSuper(); + jCall.arg($v("node")); + jCall.arg($v("graph")); } } diff --git a/pom.xml b/pom.xml index e7784dedf..b7a5b60df 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ 4.9.0 0.6.0 1.3.2 + 2.0.3.Final 3.3.0 @@ -123,7 +124,11 @@ javax.annotation-api ${javax.annotation.version} - + + org.jboss.jdeparser + jdeparser + ${jdeparser.version} + From 25bddf8c780e65d4bd40521768148dfd2995f6e8 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 19 Aug 2023 15:14:02 +0200 Subject: [PATCH 015/141] Tidy Processor --- .../declarative/processor/Processor.java | 238 ++++++++++-------- 1 file changed, 133 insertions(+), 105 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index b5774a6fc..51a8f696d 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -21,6 +21,7 @@ package com.inrupt.rdf.wrapping.declarative.processor; import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; @@ -65,126 +66,153 @@ public boolean process(final Set annotations, final Round return false; } - for (TypeElement annotation : annotations) { - processingEnv.getMessager().printMessage( - Diagnostic.Kind.NOTE, - String.format("annotation [%s]", annotation), annotation); - - final Set annotatedElements = roundEnv.getElementsAnnotatedWith(annotation); - for (Element annotatedElement : annotatedElements) { - processingEnv.getMessager().printMessage( - Diagnostic.Kind.NOTE, - String.format("annotatedElement [%s]", annotatedElement), annotatedElement); - - final TypeElement annotatedType = (TypeElement) annotatedElement; - final String originalInterfaceName = annotatedType.getQualifiedName().toString(); - final String originalBinaryName = processingEnv - .getElementUtils() - .getBinaryName(annotatedType) - .toString(); - final String qualifiedName = originalBinaryName + "_$impl"; - final int lastDot = originalBinaryName.lastIndexOf('.'); - final String implementationClassName = qualifiedName.substring(lastDot + 1); - String packageName = null; - if (lastDot > 0) { - packageName = originalBinaryName.substring(0, lastDot); - } - - final JFiler jFiler = JFiler.newInstance(processingEnv.getFiler()); - final JSources sources = JDeparser.createSources(jFiler, new FormatPreferences()); - final JSourceFile sourceFile = sources.createSourceFile(packageName, implementationClassName); - - switch (annotation.getQualifiedName().toString()) { - case "com.inrupt.rdf.wrapping.declarative.annotations.Dataset": - printDataset(originalInterfaceName, implementationClassName, sourceFile); - break; - case "com.inrupt.rdf.wrapping.declarative.annotations.Graph": - printGraph(originalInterfaceName, implementationClassName, sourceFile); - break; - case "com.inrupt.rdf.wrapping.declarative.annotations.Resource": - printResource(originalInterfaceName, implementationClassName, sourceFile); - break; - } - - try { - sources.writeSources(); - } catch (IOException e) { - throw new RuntimeException("could not open writer", e); - } - } + for (final TypeElement annotation : annotations) { + process(roundEnv, annotation); } return true; } - private void printDataset( - final String originalInterfaceName, - final String implementationClassName, + private void process(final RoundEnvironment roundEnv, final TypeElement annotation) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.NOTE, + String.format("annotation [%s]", annotation), annotation); + + for (final Element annotatedElement : roundEnv.getElementsAnnotatedWith(annotation)) { + process(annotation, annotatedElement); + } + } + + private void process(final TypeElement annotation, final Element annotatedElement) { + processingEnv.getMessager().printMessage( + Diagnostic.Kind.NOTE, + String.format("annotatedElement [%s]", annotatedElement), annotatedElement); + + final TypeElement annotatedType = (TypeElement) annotatedElement; + final String originalInterfaceName = annotatedType.getQualifiedName().toString(); + final String originalBinaryName = processingEnv + .getElementUtils() + .getBinaryName(annotatedType) + .toString(); + final String qualifiedName = originalBinaryName + "_$impl"; + final int lastDot = originalBinaryName.lastIndexOf('.'); + final String implementationClassName = qualifiedName.substring(lastDot + 1); + final String packageName = processingEnv.getElementUtils().getPackageOf(annotatedElement).getQualifiedName().toString(); + + final JFiler jFiler = JFiler.newInstance(processingEnv.getFiler()); + final JSources sources = JDeparser.createSources(jFiler, new FormatPreferences()); + final JSourceFile sourceFile = sources.createSourceFile(packageName, implementationClassName); + + switch (annotation.getQualifiedName().toString()) { + case "com.inrupt.rdf.wrapping.declarative.annotations.Dataset": + implementDataset(originalInterfaceName, implementationClassName, sourceFile); + break; + case "com.inrupt.rdf.wrapping.declarative.annotations.Graph": + implementGraph(originalInterfaceName, implementationClassName, sourceFile); + break; + case "com.inrupt.rdf.wrapping.declarative.annotations.Resource": + implementResource(originalInterfaceName, implementationClassName, sourceFile); + break; + default: + throw new RuntimeException("unknown annotation type"); + } + + try { + sources.writeSources(); + } catch (IOException e) { + throw new RuntimeException("could not open writer", e); + } + } + + private void implementDataset( + final String originalInterface, + final String implementationClass, final JSourceFile sourceFile) { - sourceFile._import(Generated.class); - sourceFile._import(Dataset.class); - sourceFile._import(DatasetGraph.class); - sourceFile._import(DatasetImpl.class); - - final JClassDef jClassDef = sourceFile._class(JMod.PUBLIC, implementationClassName); - jClassDef.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); - jClassDef.docComment().text("Warning, this class consists of generated code."); - jClassDef._extends(DatasetImpl.class)._implements(originalInterfaceName); - - final JMethodDef constructor = jClassDef.constructor(JMod.PROTECTED); - constructor.param(JMod.FINAL, DatasetGraph.class, "original"); + + sourceFile + ._import(Generated.class) + ._import(Dataset.class) + ._import(DatasetGraph.class) + ._import(DatasetImpl.class); + + final JClassDef implementation = sourceFile._class(PUBLIC, implementationClass) + ._extends(DatasetImpl.class) + ._implements(originalInterface); + + annotateAndDocumentAsGenerated(implementation); + + final JMethodDef constructor = implementation.constructor(PROTECTED); + constructor.param(FINAL, DatasetGraph.class, "original"); constructor.body().callSuper().arg($v("original")); - final JMethodDef wrap = jClassDef.method(JMod.PUBLIC | JMod.STATIC, originalInterfaceName, "wrap"); - wrap.param(JMod.FINAL, Dataset.class, "original"); - wrap.body()._return($t(implementationClassName)._new().arg($v("original").call("asDatasetGraph"))); + final JMethodDef wrapMethod = implementation.method(PUBLIC | STATIC, originalInterface, "wrap"); + wrapMethod.param(FINAL, Dataset.class, "original"); + wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("asDatasetGraph"))); } - private void printGraph( - final String originalInterfaceName, - final String implementationClassName, + private void implementGraph( + final String originalInterface, + final String implementationClass, final JSourceFile sourceFile) { - sourceFile._import(Generated.class); - sourceFile._import(Graph.class); - sourceFile._import(Model.class); - sourceFile._import(ModelCom.class); - - final JClassDef jClassDef = sourceFile._class(JMod.PUBLIC, implementationClassName); - jClassDef.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); - jClassDef.docComment().text("Warning, this class consists of generated code."); - jClassDef._extends(ModelCom.class)._implements(originalInterfaceName); - - final JMethodDef constructor = jClassDef.constructor(JMod.PROTECTED); - constructor.param(JMod.FINAL, Graph.class, "original"); + + sourceFile + ._import(Generated.class) + ._import(Graph.class) + ._import(Model.class) + ._import(ModelCom.class); + + final JClassDef jClassDef = sourceFile + ._class(PUBLIC, implementationClass) + ._extends(ModelCom.class) + ._implements(originalInterface); + + annotateAndDocumentAsGenerated(jClassDef); + + final JMethodDef constructor = jClassDef.constructor(PROTECTED); + constructor.param(FINAL, Graph.class, "original"); constructor.body().callSuper().arg($v("original")); - final JMethodDef wrap = jClassDef.method(JMod.PUBLIC | JMod.STATIC, originalInterfaceName, "wrap"); - wrap.param(JMod.FINAL, Model.class, "original"); - wrap.body()._return($t(implementationClassName)._new().arg($v("original").call("getGraph"))); + final JMethodDef wrapMethod = jClassDef.method(PUBLIC | STATIC, originalInterface, "wrap"); + wrapMethod.param(FINAL, Model.class, "original"); + wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("getGraph"))); } - private void printResource( - final String originalInterfaceName, - final String implementationClassName, + private void implementResource( + final String originalInterface, + final String implementationClass, final JSourceFile sourceFile) { - sourceFile._import(UriOrBlankFactory.class); - sourceFile._import(WrapperResource.class); - sourceFile._import(Generated.class); - sourceFile._import(EnhGraph.class); - sourceFile._import(Implementation.class); - sourceFile._import(Node.class); - - final JClassDef jClassDef = sourceFile._class(JMod.PUBLIC, implementationClassName); - jClassDef.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); - jClassDef.docComment().text("Warning, this class consists of generated code."); - jClassDef._extends(WrapperResource.class)._implements(originalInterfaceName); - - jClassDef.field(JMod.STATIC | JMod.FINAL, Implementation.class, "factory", $t(UriOrBlankFactory.class)._new().arg($t(implementationClassName).methodRef("new"))); - final JMethodDef constructor = jClassDef.constructor(JMod.PROTECTED); - constructor.param(JMod.FINAL, Node.class, "node"); - constructor.param(JMod.FINAL, EnhGraph.class, "graph"); - final JCall jCall = constructor.body().callSuper(); - jCall.arg($v("node")); - jCall.arg($v("graph")); + + sourceFile + ._import(UriOrBlankFactory.class) + ._import(WrapperResource.class) + ._import(Generated.class) + ._import(EnhGraph.class) + ._import(Implementation.class) + ._import(Node.class); + + final JClassDef implementation = sourceFile._class(PUBLIC, implementationClass) + ._extends(WrapperResource.class) + ._implements(originalInterface); + + annotateAndDocumentAsGenerated(implementation); + + implementation.field( + STATIC | FINAL, + Implementation.class, + "factory", + $t(UriOrBlankFactory.class)._new().arg($t(implementationClass).methodRef("new"))); + + final JMethodDef constructor = implementation.constructor(PROTECTED); + constructor.param(FINAL, Node.class, "node"); + constructor.param(FINAL, EnhGraph.class, "graph"); + constructor.body().callSuper().arg($v("node")).arg($v("graph")); + } + + private void annotateAndDocumentAsGenerated(final JClassDef implementation) { + implementation.docComment().text("Warning, this class consists of generated code."); + + implementation + .annotate(Generated.class) + .value(this.getClass().getName()).value("date", Instant.now().toString()); } } From 9da7b6b26dffaa1c00a29b20fae532da14dbdd31 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 19 Aug 2023 16:23:44 +0200 Subject: [PATCH 016/141] Implement `@DefaultGraph` --- .../declarative/annotations/DefaultGraph.java | 34 +++++++++++++++++++ .../declarative/processor/Processor.java | 28 +++++++++++++-- .../rdf/wrapping/declarative/test/X.java | 4 +++ .../rdf/wrapping/declarative/test/XTest.java | 7 ++++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/DefaultGraph.java diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/DefaultGraph.java b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/DefaultGraph.java new file mode 100644 index 000000000..1e022cdd2 --- /dev/null +++ b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/DefaultGraph.java @@ -0,0 +1,34 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target(METHOD) +@Retention(CLASS) +@Documented +public @interface DefaultGraph { +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index 51a8f696d..66c5d703b 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -24,6 +24,7 @@ import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; +import com.inrupt.rdf.wrapping.declarative.annotations.DefaultGraph; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; import com.inrupt.rdf.wrapping.jena.WrapperResource; @@ -38,7 +39,9 @@ import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; +import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; +import javax.lang.model.util.ElementFilter; import javax.tools.Diagnostic; import org.apache.jena.enhanced.EnhGraph; @@ -105,7 +108,7 @@ private void process(final TypeElement annotation, final Element annotatedElemen switch (annotation.getQualifiedName().toString()) { case "com.inrupt.rdf.wrapping.declarative.annotations.Dataset": - implementDataset(originalInterfaceName, implementationClassName, sourceFile); + implementDataset(originalInterfaceName, implementationClassName, sourceFile, annotatedType); break; case "com.inrupt.rdf.wrapping.declarative.annotations.Graph": implementGraph(originalInterfaceName, implementationClassName, sourceFile); @@ -127,7 +130,8 @@ private void process(final TypeElement annotation, final Element annotatedElemen private void implementDataset( final String originalInterface, final String implementationClass, - final JSourceFile sourceFile) { + final JSourceFile sourceFile, + final TypeElement annotatedType) { sourceFile ._import(Generated.class) @@ -148,6 +152,26 @@ private void implementDataset( final JMethodDef wrapMethod = implementation.method(PUBLIC | STATIC, originalInterface, "wrap"); wrapMethod.param(FINAL, Dataset.class, "original"); wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("asDatasetGraph"))); + + ElementFilter.methodsIn(annotatedType.getEnclosedElements()).stream() + .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC)) + .filter(method -> method.getAnnotation(DefaultGraph.class) != null) + .forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + sourceFile._import(returnType); + final JMethodDef defaultGraphMethod = implementation.method( + PUBLIC, + returnType, + method.getSimpleName().toString()); + defaultGraphMethod.annotate(Override.class); + defaultGraphMethod + .body() + ._return(returnType + .call("wrap") + .arg($t(implementationClass) + ._this() + .call("getDefaultModel"))); + }); } private void implementGraph( diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java index 7351e1e80..071dfddb8 100644 --- a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java +++ b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java @@ -21,6 +21,7 @@ package com.inrupt.rdf.wrapping.declarative.test; import com.inrupt.rdf.wrapping.declarative.annotations.Dataset; +import com.inrupt.rdf.wrapping.declarative.annotations.DefaultGraph; import com.inrupt.rdf.wrapping.declarative.annotations.Graph; import com.inrupt.rdf.wrapping.declarative.annotations.Resource; import com.inrupt.rdf.wrapping.declarative.processor.Manager; @@ -33,6 +34,9 @@ static X wrap(final org.apache.jena.query.Dataset original) { return Manager.wrap(original, X.class); } + @DefaultGraph + Y getDefaultGraph(); + @Graph interface Y { static Y wrap(final Model original) { diff --git a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java index 77943ccfe..251fd8bb8 100644 --- a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java +++ b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java @@ -29,6 +29,13 @@ void datasetCanWrap() { assertDoesNotThrow(() -> X.wrap(dataset)); } + @Test + void datasetCanGetDefaultGraph() { + final X x = X.wrap(DatasetFactory.create()); + + assertDoesNotThrow(x::getDefaultGraph); + } + @Test void graphCanWrap() { final Model model = modelFrom("" + From 3cffe9e1674162d4bf7fc71f379f4dc8fdaa98d0 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 19 Aug 2023 16:25:15 +0200 Subject: [PATCH 017/141] Tidy processor tests --- .../rdf/wrapping/declarative/test/XTest.java | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java index 251fd8bb8..0fa0481ce 100644 --- a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java +++ b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java @@ -1,3 +1,23 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ package com.inrupt.rdf.wrapping.declarative.test; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -16,15 +36,7 @@ class XTest { @Test void datasetCanWrap() { - final Dataset dataset = datasetFrom("" + - "PREFIX : \n" + - "\n" + - "[\n" + - " a :C ;\n" + - " :p1 [\n" + - " :p2 \"XXX\" ;\n" + - " ] ;\n" + - "] .\n"); + final Dataset dataset = DatasetFactory.create(); assertDoesNotThrow(() -> X.wrap(dataset)); } @@ -38,15 +50,7 @@ void datasetCanGetDefaultGraph() { @Test void graphCanWrap() { - final Model model = modelFrom("" + - "PREFIX : \n" + - "\n" + - "[\n" + - " a :C ;\n" + - " :p1 [\n" + - " :p2 \"XXX\" ;\n" + - " ] ;\n" + - "] .\n"); + final Model model = ModelFactory.createDefaultModel(); assertDoesNotThrow(() -> X.Y.wrap(model)); } From 28b092e6dec7d419a303b0d06acc7542124d905d Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 19 Aug 2023 16:41:53 +0200 Subject: [PATCH 018/141] Implement `@NamedGraph` --- .../declarative/annotations/NamedGraph.java | 35 +++++++++++++++++++ .../declarative/processor/Processor.java | 20 +++++++++++ .../declarative/template/ExampleDataset.java | 3 ++ .../template/ExampleDataset_$impl.java | 5 +++ .../rdf/wrapping/declarative/test/X.java | 8 ++--- .../rdf/wrapping/declarative/test/XTest.java | 7 ++++ 6 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/NamedGraph.java diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/NamedGraph.java b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/NamedGraph.java new file mode 100644 index 000000000..69e49ea9d --- /dev/null +++ b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/NamedGraph.java @@ -0,0 +1,35 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target(METHOD) +@Retention(CLASS) +@Documented +public @interface NamedGraph { + String value(); +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index 66c5d703b..ea8895aa5 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -25,6 +25,7 @@ import static org.jboss.jdeparser.JTypes.$t; import com.inrupt.rdf.wrapping.declarative.annotations.DefaultGraph; +import com.inrupt.rdf.wrapping.declarative.annotations.NamedGraph; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; import com.inrupt.rdf.wrapping.jena.WrapperResource; @@ -172,6 +173,25 @@ private void implementDataset( ._this() .call("getDefaultModel"))); }); + + ElementFilter.methodsIn(annotatedType.getEnclosedElements()).stream() + .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC)) + .filter(method -> method.getAnnotation(NamedGraph.class) != null) + .forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + sourceFile._import(returnType); + final JMethodDef namedGraphMethod = implementation + .method(PUBLIC, returnType, method.getSimpleName().toString()); + namedGraphMethod.annotate(Override.class); + namedGraphMethod + .body() + ._return(returnType + .call("wrap") + .arg($t(implementationClass) + ._this() + .call("getNamedModel") + .arg(JExprs.str(method.getAnnotation(NamedGraph.class).value())))); + }); } private void implementGraph( diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java index 07504f8cf..8122b5e4f 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java @@ -31,4 +31,7 @@ static ExampleDataset wrap(final org.apache.jena.query.Dataset original) { // @DefaultGraph ExampleGraph getGraph(); + + // @NamedGraph("urn:example:g1") + ExampleGraph getNamedGraph(); } diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java index d380b7d17..c5e4a5c72 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java @@ -49,4 +49,9 @@ public static ExampleDataset create() { public ExampleGraph getGraph() { return ExampleGraph.wrap(getDefaultModel()); } + + @Override + public ExampleGraph getNamedGraph() { + return ExampleGraph.wrap(getNamedModel("urn:example:g1")); + } } diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java index 071dfddb8..77f5790ec 100644 --- a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java +++ b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java @@ -20,10 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.test; -import com.inrupt.rdf.wrapping.declarative.annotations.Dataset; -import com.inrupt.rdf.wrapping.declarative.annotations.DefaultGraph; -import com.inrupt.rdf.wrapping.declarative.annotations.Graph; -import com.inrupt.rdf.wrapping.declarative.annotations.Resource; +import com.inrupt.rdf.wrapping.declarative.annotations.*; import com.inrupt.rdf.wrapping.declarative.processor.Manager; import org.apache.jena.rdf.model.Model; @@ -37,6 +34,9 @@ static X wrap(final org.apache.jena.query.Dataset original) { @DefaultGraph Y getDefaultGraph(); + @NamedGraph("urn:example:g1") + Y getNamedGraph(); + @Graph interface Y { static Y wrap(final Model original) { diff --git a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java index 0fa0481ce..d14a721b9 100644 --- a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java +++ b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java @@ -48,6 +48,13 @@ void datasetCanGetDefaultGraph() { assertDoesNotThrow(x::getDefaultGraph); } + @Test + void datasetCanGetNamedGraph() { + final X x = X.wrap(DatasetFactory.create()); + + assertDoesNotThrow(x::getNamedGraph); + } + @Test void graphCanWrap() { final Model model = ModelFactory.createDefaultModel(); From 5539f5cf2da1a7665c20eab9bec03de604201ec5 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 19 Aug 2023 18:20:36 +0200 Subject: [PATCH 019/141] Implement `@FirstInstanceOf` --- .../annotations/FirstInstanceOf.java | 35 +++++++++++++ .../declarative/processor/Processor.java | 49 +++++++++++++++++-- .../declarative/template/ExampleGraph.java | 2 +- .../template/ExampleGraph_$impl.java | 13 ++--- .../rdf/wrapping/declarative/test/X.java | 3 ++ .../rdf/wrapping/declarative/test/XTest.java | 8 +++ .../rdf/wrapping/jena/WrapperModel.java | 39 +++++++++++++++ 7 files changed, 136 insertions(+), 13 deletions(-) create mode 100644 declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/FirstInstanceOf.java create mode 100644 jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/FirstInstanceOf.java b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/FirstInstanceOf.java new file mode 100644 index 000000000..ddf2c116b --- /dev/null +++ b/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/FirstInstanceOf.java @@ -0,0 +1,35 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.CLASS; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target(METHOD) +@Retention(CLASS) +@Documented +public @interface FirstInstanceOf { + String value(); +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index ea8895aa5..6b0ae7df5 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -25,8 +25,10 @@ import static org.jboss.jdeparser.JTypes.$t; import com.inrupt.rdf.wrapping.declarative.annotations.DefaultGraph; +import com.inrupt.rdf.wrapping.declarative.annotations.FirstInstanceOf; import com.inrupt.rdf.wrapping.declarative.annotations.NamedGraph; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; +import com.inrupt.rdf.wrapping.jena.WrapperModel; import com.inrupt.rdf.wrapping.jena.WrapperResource; import java.io.IOException; @@ -112,7 +114,7 @@ private void process(final TypeElement annotation, final Element annotatedElemen implementDataset(originalInterfaceName, implementationClassName, sourceFile, annotatedType); break; case "com.inrupt.rdf.wrapping.declarative.annotations.Graph": - implementGraph(originalInterfaceName, implementationClassName, sourceFile); + implementGraph(originalInterfaceName, implementationClassName, sourceFile, annotatedType); break; case "com.inrupt.rdf.wrapping.declarative.annotations.Resource": implementResource(originalInterfaceName, implementationClassName, sourceFile); @@ -197,9 +199,11 @@ private void implementDataset( private void implementGraph( final String originalInterface, final String implementationClass, - final JSourceFile sourceFile) { + final JSourceFile sourceFile, + final TypeElement annotatedType) { sourceFile + ._import(WrapperModel.class) ._import(Generated.class) ._import(Graph.class) ._import(Model.class) @@ -207,7 +211,7 @@ private void implementGraph( final JClassDef jClassDef = sourceFile ._class(PUBLIC, implementationClass) - ._extends(ModelCom.class) + ._extends(WrapperModel.class) ._implements(originalInterface); annotateAndDocumentAsGenerated(jClassDef); @@ -216,9 +220,48 @@ private void implementGraph( constructor.param(FINAL, Graph.class, "original"); constructor.body().callSuper().arg($v("original")); + ElementFilter.methodsIn(annotatedType.getEnclosedElements()).stream() + .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC) && !method.getReturnType().equals($t(Void.class))) + .filter(method -> method.getAnnotation(FirstInstanceOf.class) != null) + .forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + final String originalBinaryName = processingEnv + .getElementUtils() + .getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(method.getReturnType())) + .toString(); + final String qualifiedName = originalBinaryName + "_$impl"; + + sourceFile._import(returnType); + constructor.body().call($t(implementationClass)._this().call("getPersonality"), "add").arg($t(qualifiedName)._class()).arg($t(qualifiedName).field("factory")); + }); + final JMethodDef wrapMethod = jClassDef.method(PUBLIC | STATIC, originalInterface, "wrap"); wrapMethod.param(FINAL, Model.class, "original"); wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("getGraph"))); + + ElementFilter.methodsIn(annotatedType.getEnclosedElements()).stream() + .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC) && !method.getReturnType().equals($t(Void.class))) + .filter(method -> method.getAnnotation(FirstInstanceOf.class) != null) + .forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + final String originalBinaryName = processingEnv + .getElementUtils() + .getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(method.getReturnType())) + .toString(); + final String qualifiedName = originalBinaryName + "_$impl"; + + sourceFile._import(returnType); + final JMethodDef namedGraphMethod = jClassDef + .method(PUBLIC, returnType, method.getSimpleName().toString()); + namedGraphMethod.annotate(Override.class); + namedGraphMethod + .body() + ._return($t(implementationClass) + ._this() + .call("firstInstanceOf") + .arg(JExprs.str(method.getAnnotation(FirstInstanceOf.class).value())) + .arg($t(qualifiedName)._class())); + }); } private void implementResource( diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java index 1a31effcc..8ba76fce4 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java @@ -31,6 +31,6 @@ static ExampleGraph wrap(final Model original) { return Manager.wrap(original, ExampleGraph.class); } - // @FirstSubjectOf(RDF.type, "urn:example:C") + // @FirstInstanceOf("urn:example:C") ExampleNode1 getResource(); } diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java index 7b4789857..e8dc76cbe 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java @@ -20,20 +20,19 @@ */ package com.inrupt.rdf.wrapping.declarative.template; +import com.inrupt.rdf.wrapping.jena.WrapperModel; + import javax.annotation.Generated; import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.ResourceFactory; -import org.apache.jena.rdf.model.impl.ModelCom; import org.apache.jena.sparql.graph.GraphFactory; -import org.apache.jena.vocabulary.RDF; /** * Warning this class consists of generated code. */ @Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") -public class ExampleGraph_$impl extends ModelCom implements ExampleGraph { +public class ExampleGraph_$impl extends WrapperModel implements ExampleGraph { protected ExampleGraph_$impl(final Graph base) { super(base); @@ -52,10 +51,6 @@ public static ExampleGraph create() { @Override public ExampleNode1 getResource() { - return listResourcesWithProperty( - RDF.type, - ResourceFactory.createResource("urn:example:C")) - .nextResource() - .as(ExampleNode1_$impl.class); + return firstInstanceOf("urn:example:C", ExampleNode1_$impl.class); } } diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java index 77f5790ec..fcacdc834 100644 --- a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java +++ b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java @@ -43,6 +43,9 @@ static Y wrap(final Model original) { return Manager.wrap(original, Y.class); } + @FirstInstanceOf("urn:example:C") + Z getResource(); + @Resource interface Z { } diff --git a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java index d14a721b9..9f25e5d78 100644 --- a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java +++ b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java @@ -62,6 +62,14 @@ void graphCanWrap() { assertDoesNotThrow(() -> X.Y.wrap(model)); } + @Test + void graphCanGetFirstInstanceOf() { + final Model model = ModelFactory.createDefaultModel(); + final X.Y y = X.Y.wrap(model); + + assertDoesNotThrow(y::getResource); + } + private static Dataset datasetFrom(final String rdf) { final Dataset dataset = DatasetFactory.create(); RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); diff --git a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java new file mode 100644 index 000000000..079e82c35 --- /dev/null +++ b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java @@ -0,0 +1,39 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.jena; + +import org.apache.jena.graph.Graph; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.impl.ModelCom; +import org.apache.jena.vocabulary.RDF; + +public abstract class WrapperModel extends ModelCom { + protected WrapperModel(final Graph base) { + super(base); + } + + protected T firstInstanceOf(final String clazz, final Class view) { + return listSubjectsWithProperty(RDF.type, createResource(clazz)) + .mapWith(subject -> subject.as(view)) + .nextOptional() + .orElse(null); + } +} From d41e081d09020a7191dc300e19bda8b48b10f577 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 19 Aug 2023 18:28:47 +0200 Subject: [PATCH 020/141] Tidy Processor --- .../rdf/wrapping/declarative/processor/Processor.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index 6b0ae7df5..d653812bf 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -209,14 +209,14 @@ private void implementGraph( ._import(Model.class) ._import(ModelCom.class); - final JClassDef jClassDef = sourceFile + final JClassDef implementation = sourceFile ._class(PUBLIC, implementationClass) ._extends(WrapperModel.class) ._implements(originalInterface); - annotateAndDocumentAsGenerated(jClassDef); + annotateAndDocumentAsGenerated(implementation); - final JMethodDef constructor = jClassDef.constructor(PROTECTED); + final JMethodDef constructor = implementation.constructor(PROTECTED); constructor.param(FINAL, Graph.class, "original"); constructor.body().callSuper().arg($v("original")); @@ -235,7 +235,7 @@ private void implementGraph( constructor.body().call($t(implementationClass)._this().call("getPersonality"), "add").arg($t(qualifiedName)._class()).arg($t(qualifiedName).field("factory")); }); - final JMethodDef wrapMethod = jClassDef.method(PUBLIC | STATIC, originalInterface, "wrap"); + final JMethodDef wrapMethod = implementation.method(PUBLIC | STATIC, originalInterface, "wrap"); wrapMethod.param(FINAL, Model.class, "original"); wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("getGraph"))); @@ -251,7 +251,7 @@ private void implementGraph( final String qualifiedName = originalBinaryName + "_$impl"; sourceFile._import(returnType); - final JMethodDef namedGraphMethod = jClassDef + final JMethodDef namedGraphMethod = implementation .method(PUBLIC, returnType, method.getSimpleName().toString()); namedGraphMethod.annotate(Override.class); namedGraphMethod From 2df57f5a1d41f535c2fe987dfd6aafe3bdd183cb Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 19 Aug 2023 18:20:50 +0200 Subject: [PATCH 021/141] Add simple E2E unit test --- .../rdf/wrapping/declarative/test/XTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java index 9f25e5d78..c0762e94d 100644 --- a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java +++ b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java @@ -70,6 +70,24 @@ void graphCanGetFirstInstanceOf() { assertDoesNotThrow(y::getResource); } + @Test + void e2e() { + final Dataset dataset = datasetFrom("" + + "PREFIX : \n" + + "\n" + + "GRAPH {\n" + + " [\n" + + " a :C ;\n" + + " ] .\n" + + "}\n"); + + final X x = X.wrap(dataset); + final X.Y y = x.getNamedGraph(); + final X.Y.Z z = y.getResource(); + + System.out.println(z); + } + private static Dataset datasetFrom(final String rdf) { final Dataset dataset = DatasetFactory.create(); RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); From dde62bb54d95c6448230bd1b5adc69a64c3fc0b2 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 19 Aug 2023 18:31:43 +0200 Subject: [PATCH 022/141] Separate implementors from processor --- .../processor/DatasetImplementor.java | 114 ++++++++ .../processor/GraphImplementor.java | 129 +++++++++ .../declarative/processor/Implementor.java | 102 +++++++ .../declarative/processor/Processor.java | 255 +----------------- .../processor/ResourceImplementor.java | 77 ++++++ 5 files changed, 425 insertions(+), 252 deletions(-) create mode 100644 declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java create mode 100644 declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java create mode 100644 declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java create mode 100644 declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java new file mode 100644 index 000000000..a6a280c26 --- /dev/null +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java @@ -0,0 +1,114 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JTypes.$t; + +import com.inrupt.rdf.wrapping.declarative.annotations.DefaultGraph; +import com.inrupt.rdf.wrapping.declarative.annotations.NamedGraph; + +import javax.annotation.Generated; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.ElementFilter; + +import org.apache.jena.query.Dataset; +import org.apache.jena.sparql.core.DatasetGraph; +import org.apache.jena.sparql.core.DatasetImpl; +import org.jboss.jdeparser.*; + +class DatasetImplementor extends Implementor { + DatasetImplementor(final ProcessingEnvironment processingEnvironment, final TypeElement annotatedElement) { + super(processingEnvironment, annotatedElement); + } + + @Override + protected void implementInternal() { + // Imports + sourceFile + ._import(Generated.class) + ._import(Dataset.class) + ._import(DatasetGraph.class) + ._import(DatasetImpl.class); + + // Class + final JClassDef implementation = sourceFile._class(PUBLIC, implementationClass) + ._extends(DatasetImpl.class) + ._implements(originalInterface); + + // @Generated & Javadocs + annotateAndDocumentAsGenerated(implementation); + + // Constructor + final JMethodDef constructor = implementation.constructor(PROTECTED); + constructor.param(FINAL, DatasetGraph.class, "original"); + constructor.body().callSuper().arg($v("original")); + + // Wrap method + final JMethodDef wrapMethod = implementation.method(PUBLIC | STATIC, originalInterface, "wrap"); + wrapMethod.param(FINAL, Dataset.class, "original"); + wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("asDatasetGraph"))); + + // @DefaultGraph + ElementFilter.methodsIn(annotatedElement.getEnclosedElements()).stream() + .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC)) + .filter(method -> method.getAnnotation(DefaultGraph.class) != null) + .forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + sourceFile._import(returnType); + final JMethodDef defaultGraphMethod = implementation.method( + PUBLIC, + returnType, + method.getSimpleName().toString()); + defaultGraphMethod.annotate(Override.class); + defaultGraphMethod + .body() + ._return(returnType + .call("wrap") + .arg($t(implementationClass) + ._this() + .call("getDefaultModel"))); + }); + + // @NamedGraph + ElementFilter.methodsIn(annotatedElement.getEnclosedElements()).stream() + .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC)) + .filter(method -> method.getAnnotation(NamedGraph.class) != null) + .forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + sourceFile._import(returnType); + final JMethodDef namedGraphMethod = implementation + .method(PUBLIC, returnType, method.getSimpleName().toString()); + namedGraphMethod.annotate(Override.class); + namedGraphMethod + .body() + ._return(returnType + .call("wrap") + .arg($t(implementationClass) + ._this() + .call("getNamedModel") + .arg(JExprs.str(method.getAnnotation(NamedGraph.class).value())))); + }); + } +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java new file mode 100644 index 000000000..4686b25ce --- /dev/null +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -0,0 +1,129 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JTypes.$t; + +import com.inrupt.rdf.wrapping.declarative.annotations.FirstInstanceOf; +import com.inrupt.rdf.wrapping.jena.WrapperModel; + +import javax.annotation.Generated; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.util.ElementFilter; + +import org.apache.jena.graph.Graph; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.impl.ModelCom; +import org.jboss.jdeparser.*; + +class GraphImplementor extends Implementor { + GraphImplementor(final ProcessingEnvironment processingEnvironment, final TypeElement annotatedElement) { + super(processingEnvironment, annotatedElement); + } + + @Override + protected void implementInternal() { + // Imports + sourceFile + ._import(WrapperModel.class) + ._import(Generated.class) + ._import(Graph.class) + ._import(Model.class) + ._import(ModelCom.class); + + // Class + final JClassDef implementation = sourceFile + ._class(PUBLIC, implementationClass) + ._extends(WrapperModel.class) + ._implements(originalInterface); + + // @Generated & Javadocs + annotateAndDocumentAsGenerated(implementation); + + // Constructor + final JMethodDef constructor = implementation.constructor(PROTECTED); + constructor.param(FINAL, Graph.class, "original"); + constructor.body().callSuper().arg($v("original")); + + // Personality + ElementFilter.methodsIn(annotatedElement.getEnclosedElements()).stream() + .filter(method -> !method.isDefault() + && !method.getModifiers().contains(Modifier.STATIC) + && !method.getReturnType().equals($t(Void.class))) + .filter(method -> method.getAnnotation(FirstInstanceOf.class) != null) + .forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + final Element returnTypeElement = processingEnvironment.getTypeUtils() + .asElement(method.getReturnType()); + final String originalBinaryName = processingEnvironment + .getElementUtils() + .getBinaryName((TypeElement) returnTypeElement) + .toString(); + final String qualifiedName = originalBinaryName + "_$impl"; + + sourceFile._import(returnType); + constructor + .body() + .call($t(implementationClass)._this().call("getPersonality"), "add") + .arg($t(qualifiedName)._class()) + .arg($t(qualifiedName).field("factory")); + }); + + // Wrap method + final JMethodDef wrapMethod = implementation.method(PUBLIC | STATIC, originalInterface, "wrap"); + wrapMethod.param(FINAL, Model.class, "original"); + wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("getGraph"))); + + // @FirstInstanceOf + ElementFilter.methodsIn(annotatedElement.getEnclosedElements()).stream() + .filter(method -> !method.isDefault() + && !method.getModifiers().contains(Modifier.STATIC) + && !method.getReturnType().equals($t(Void.class))) + .filter(method -> method.getAnnotation(FirstInstanceOf.class) != null) + .forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + final Element returnTypeElement = processingEnvironment.getTypeUtils() + .asElement(method.getReturnType()); + final String originalBinaryName = processingEnvironment + .getElementUtils() + .getBinaryName((TypeElement) returnTypeElement) + .toString(); + final String qualifiedName = originalBinaryName + "_$impl"; + + sourceFile._import(returnType); + final JMethodDef namedGraphMethod = implementation + .method(PUBLIC, returnType, method.getSimpleName().toString()); + namedGraphMethod.annotate(Override.class); + namedGraphMethod + .body() + ._return($t(implementationClass) + ._this() + .call("firstInstanceOf") + .arg(JExprs.str(method.getAnnotation(FirstInstanceOf.class).value())) + .arg($t(qualifiedName)._class())); + }); + } +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java new file mode 100644 index 000000000..12bfaf459 --- /dev/null +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java @@ -0,0 +1,102 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import java.io.IOException; +import java.time.Instant; + +import javax.annotation.Generated; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +import org.jboss.jdeparser.*; + +abstract class Implementor { + protected final ProcessingEnvironment processingEnvironment; + protected final TypeElement annotatedElement; + protected final JSources sources; + protected final String implementationClass; + protected final String originalInterface; + protected JSourceFile sourceFile; + + protected Implementor(final ProcessingEnvironment processingEnvironment, final TypeElement annotatedElement) { + this.processingEnvironment = processingEnvironment; + this.annotatedElement = annotatedElement; + + originalInterface = annotatedElement.getQualifiedName().toString(); + final String originalBinaryName = processingEnvironment + .getElementUtils() + .getBinaryName(annotatedElement) + .toString(); + final String qualifiedName = originalBinaryName + "_$impl"; + final int lastDot = originalBinaryName.lastIndexOf('.'); + implementationClass = qualifiedName.substring(lastDot + 1); + final String packageName = processingEnvironment.getElementUtils() + .getPackageOf(annotatedElement) + .getQualifiedName().toString(); + + final JFiler jFiler = JFiler.newInstance(processingEnvironment.getFiler()); + sources = JDeparser.createSources(jFiler, new FormatPreferences()); + + sourceFile = sources.createSourceFile(packageName, implementationClass); + } + + void implement() { + implementInternal(); + + try { + sources.writeSources(); + } catch (IOException e) { + throw new RuntimeException("could not open writer", e); + } + + } + + protected abstract void implementInternal(); + + static Implementor get( + final TypeElement annotation, + final ProcessingEnvironment processingEnvironment, + final Element annotatedElement) { + + final TypeElement annotatedType = (TypeElement) annotatedElement; + + switch (annotation.getQualifiedName().toString()) { + case "com.inrupt.rdf.wrapping.declarative.annotations.Dataset": + return new DatasetImplementor(processingEnvironment, annotatedType); + case "com.inrupt.rdf.wrapping.declarative.annotations.Graph": + return new GraphImplementor(processingEnvironment, annotatedType); + case "com.inrupt.rdf.wrapping.declarative.annotations.Resource": + return new ResourceImplementor(processingEnvironment, annotatedType); + default: + throw new RuntimeException("unknown annotation type"); + } + } + + protected void annotateAndDocumentAsGenerated(final JClassDef implementation) { + implementation.docComment().text("Warning, this class consists of generated code."); + + implementation + .annotate(Generated.class) + .value(this.getClass().getName()).value("date", Instant.now().toString()); + } +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index d653812bf..2e5fbad6f 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -20,44 +20,17 @@ */ package com.inrupt.rdf.wrapping.declarative.processor; -import static org.jboss.jdeparser.JExprs.$v; -import static org.jboss.jdeparser.JMod.*; -import static org.jboss.jdeparser.JTypes.$t; - -import com.inrupt.rdf.wrapping.declarative.annotations.DefaultGraph; -import com.inrupt.rdf.wrapping.declarative.annotations.FirstInstanceOf; -import com.inrupt.rdf.wrapping.declarative.annotations.NamedGraph; -import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; -import com.inrupt.rdf.wrapping.jena.WrapperModel; -import com.inrupt.rdf.wrapping.jena.WrapperResource; - -import java.io.IOException; -import java.time.Instant; import java.util.Set; -import javax.annotation.Generated; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; -import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; -import javax.lang.model.util.ElementFilter; import javax.tools.Diagnostic; -import org.apache.jena.enhanced.EnhGraph; -import org.apache.jena.enhanced.Implementation; -import org.apache.jena.graph.Graph; -import org.apache.jena.graph.Node; -import org.apache.jena.query.Dataset; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.impl.ModelCom; -import org.apache.jena.sparql.core.DatasetGraph; -import org.apache.jena.sparql.core.DatasetImpl; -import org.jboss.jdeparser.*; - @SupportedAnnotationTypes({ "com.inrupt.rdf.wrapping.declarative.annotations.Dataset", "com.inrupt.rdf.wrapping.declarative.annotations.Graph", @@ -73,233 +46,11 @@ public boolean process(final Set annotations, final Round } for (final TypeElement annotation : annotations) { - process(roundEnv, annotation); + for (final Element annotatedElement : roundEnv.getElementsAnnotatedWith(annotation)) { + Implementor.get(annotation, processingEnv, annotatedElement).implement(); + } } return true; } - - private void process(final RoundEnvironment roundEnv, final TypeElement annotation) { - processingEnv.getMessager().printMessage( - Diagnostic.Kind.NOTE, - String.format("annotation [%s]", annotation), annotation); - - for (final Element annotatedElement : roundEnv.getElementsAnnotatedWith(annotation)) { - process(annotation, annotatedElement); - } - } - - private void process(final TypeElement annotation, final Element annotatedElement) { - processingEnv.getMessager().printMessage( - Diagnostic.Kind.NOTE, - String.format("annotatedElement [%s]", annotatedElement), annotatedElement); - - final TypeElement annotatedType = (TypeElement) annotatedElement; - final String originalInterfaceName = annotatedType.getQualifiedName().toString(); - final String originalBinaryName = processingEnv - .getElementUtils() - .getBinaryName(annotatedType) - .toString(); - final String qualifiedName = originalBinaryName + "_$impl"; - final int lastDot = originalBinaryName.lastIndexOf('.'); - final String implementationClassName = qualifiedName.substring(lastDot + 1); - final String packageName = processingEnv.getElementUtils().getPackageOf(annotatedElement).getQualifiedName().toString(); - - final JFiler jFiler = JFiler.newInstance(processingEnv.getFiler()); - final JSources sources = JDeparser.createSources(jFiler, new FormatPreferences()); - final JSourceFile sourceFile = sources.createSourceFile(packageName, implementationClassName); - - switch (annotation.getQualifiedName().toString()) { - case "com.inrupt.rdf.wrapping.declarative.annotations.Dataset": - implementDataset(originalInterfaceName, implementationClassName, sourceFile, annotatedType); - break; - case "com.inrupt.rdf.wrapping.declarative.annotations.Graph": - implementGraph(originalInterfaceName, implementationClassName, sourceFile, annotatedType); - break; - case "com.inrupt.rdf.wrapping.declarative.annotations.Resource": - implementResource(originalInterfaceName, implementationClassName, sourceFile); - break; - default: - throw new RuntimeException("unknown annotation type"); - } - - try { - sources.writeSources(); - } catch (IOException e) { - throw new RuntimeException("could not open writer", e); - } - } - - private void implementDataset( - final String originalInterface, - final String implementationClass, - final JSourceFile sourceFile, - final TypeElement annotatedType) { - - sourceFile - ._import(Generated.class) - ._import(Dataset.class) - ._import(DatasetGraph.class) - ._import(DatasetImpl.class); - - final JClassDef implementation = sourceFile._class(PUBLIC, implementationClass) - ._extends(DatasetImpl.class) - ._implements(originalInterface); - - annotateAndDocumentAsGenerated(implementation); - - final JMethodDef constructor = implementation.constructor(PROTECTED); - constructor.param(FINAL, DatasetGraph.class, "original"); - constructor.body().callSuper().arg($v("original")); - - final JMethodDef wrapMethod = implementation.method(PUBLIC | STATIC, originalInterface, "wrap"); - wrapMethod.param(FINAL, Dataset.class, "original"); - wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("asDatasetGraph"))); - - ElementFilter.methodsIn(annotatedType.getEnclosedElements()).stream() - .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC)) - .filter(method -> method.getAnnotation(DefaultGraph.class) != null) - .forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - sourceFile._import(returnType); - final JMethodDef defaultGraphMethod = implementation.method( - PUBLIC, - returnType, - method.getSimpleName().toString()); - defaultGraphMethod.annotate(Override.class); - defaultGraphMethod - .body() - ._return(returnType - .call("wrap") - .arg($t(implementationClass) - ._this() - .call("getDefaultModel"))); - }); - - ElementFilter.methodsIn(annotatedType.getEnclosedElements()).stream() - .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC)) - .filter(method -> method.getAnnotation(NamedGraph.class) != null) - .forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - sourceFile._import(returnType); - final JMethodDef namedGraphMethod = implementation - .method(PUBLIC, returnType, method.getSimpleName().toString()); - namedGraphMethod.annotate(Override.class); - namedGraphMethod - .body() - ._return(returnType - .call("wrap") - .arg($t(implementationClass) - ._this() - .call("getNamedModel") - .arg(JExprs.str(method.getAnnotation(NamedGraph.class).value())))); - }); - } - - private void implementGraph( - final String originalInterface, - final String implementationClass, - final JSourceFile sourceFile, - final TypeElement annotatedType) { - - sourceFile - ._import(WrapperModel.class) - ._import(Generated.class) - ._import(Graph.class) - ._import(Model.class) - ._import(ModelCom.class); - - final JClassDef implementation = sourceFile - ._class(PUBLIC, implementationClass) - ._extends(WrapperModel.class) - ._implements(originalInterface); - - annotateAndDocumentAsGenerated(implementation); - - final JMethodDef constructor = implementation.constructor(PROTECTED); - constructor.param(FINAL, Graph.class, "original"); - constructor.body().callSuper().arg($v("original")); - - ElementFilter.methodsIn(annotatedType.getEnclosedElements()).stream() - .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC) && !method.getReturnType().equals($t(Void.class))) - .filter(method -> method.getAnnotation(FirstInstanceOf.class) != null) - .forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final String originalBinaryName = processingEnv - .getElementUtils() - .getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(method.getReturnType())) - .toString(); - final String qualifiedName = originalBinaryName + "_$impl"; - - sourceFile._import(returnType); - constructor.body().call($t(implementationClass)._this().call("getPersonality"), "add").arg($t(qualifiedName)._class()).arg($t(qualifiedName).field("factory")); - }); - - final JMethodDef wrapMethod = implementation.method(PUBLIC | STATIC, originalInterface, "wrap"); - wrapMethod.param(FINAL, Model.class, "original"); - wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("getGraph"))); - - ElementFilter.methodsIn(annotatedType.getEnclosedElements()).stream() - .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC) && !method.getReturnType().equals($t(Void.class))) - .filter(method -> method.getAnnotation(FirstInstanceOf.class) != null) - .forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final String originalBinaryName = processingEnv - .getElementUtils() - .getBinaryName((TypeElement) processingEnv.getTypeUtils().asElement(method.getReturnType())) - .toString(); - final String qualifiedName = originalBinaryName + "_$impl"; - - sourceFile._import(returnType); - final JMethodDef namedGraphMethod = implementation - .method(PUBLIC, returnType, method.getSimpleName().toString()); - namedGraphMethod.annotate(Override.class); - namedGraphMethod - .body() - ._return($t(implementationClass) - ._this() - .call("firstInstanceOf") - .arg(JExprs.str(method.getAnnotation(FirstInstanceOf.class).value())) - .arg($t(qualifiedName)._class())); - }); - } - - private void implementResource( - final String originalInterface, - final String implementationClass, - final JSourceFile sourceFile) { - - sourceFile - ._import(UriOrBlankFactory.class) - ._import(WrapperResource.class) - ._import(Generated.class) - ._import(EnhGraph.class) - ._import(Implementation.class) - ._import(Node.class); - - final JClassDef implementation = sourceFile._class(PUBLIC, implementationClass) - ._extends(WrapperResource.class) - ._implements(originalInterface); - - annotateAndDocumentAsGenerated(implementation); - - implementation.field( - STATIC | FINAL, - Implementation.class, - "factory", - $t(UriOrBlankFactory.class)._new().arg($t(implementationClass).methodRef("new"))); - - final JMethodDef constructor = implementation.constructor(PROTECTED); - constructor.param(FINAL, Node.class, "node"); - constructor.param(FINAL, EnhGraph.class, "graph"); - constructor.body().callSuper().arg($v("node")).arg($v("graph")); - } - - private void annotateAndDocumentAsGenerated(final JClassDef implementation) { - implementation.docComment().text("Warning, this class consists of generated code."); - - implementation - .annotate(Generated.class) - .value(this.getClass().getName()).value("date", Instant.now().toString()); - } } diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java new file mode 100644 index 000000000..ff8af8c05 --- /dev/null +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java @@ -0,0 +1,77 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JTypes.$t; + +import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; +import com.inrupt.rdf.wrapping.jena.WrapperResource; + +import javax.annotation.Generated; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.TypeElement; + +import org.apache.jena.enhanced.EnhGraph; +import org.apache.jena.enhanced.Implementation; +import org.apache.jena.graph.Node; +import org.jboss.jdeparser.JClassDef; +import org.jboss.jdeparser.JMethodDef; + +class ResourceImplementor extends Implementor { + ResourceImplementor(final ProcessingEnvironment processingEnvironment, final TypeElement annotatedElement) { + super(processingEnvironment, annotatedElement); + } + + @Override + protected void implementInternal() { + // Imports + sourceFile + ._import(UriOrBlankFactory.class) + ._import(WrapperResource.class) + ._import(Generated.class) + ._import(EnhGraph.class) + ._import(Implementation.class) + ._import(Node.class); + + // Class + final JClassDef implementation = sourceFile._class(PUBLIC, implementationClass) + ._extends(WrapperResource.class) + ._implements(originalInterface); + + // @Generated & Javadocs + annotateAndDocumentAsGenerated(implementation); + + // Factory + implementation.field( + STATIC | FINAL, + Implementation.class, + "factory", + $t(UriOrBlankFactory.class)._new().arg($t(implementationClass).methodRef("new"))); + + // Constructor + final JMethodDef constructor = implementation.constructor(PROTECTED); + constructor.param(FINAL, Node.class, "node"); + constructor.param(FINAL, EnhGraph.class, "graph"); + constructor.body().callSuper().arg($v("node")).arg($v("graph")); + } +} From 79f3c2462cf4fc68f4b17eb6dbfbb31aae49e2b8 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 19 Aug 2023 20:05:11 +0200 Subject: [PATCH 023/141] Style --- declarative/{annotations => annotation}/pom.xml | 4 ++-- .../rdf/wrapping/declarative/annotation}/Dataset.java | 2 +- .../rdf/wrapping/declarative/annotation}/DefaultGraph.java | 2 +- .../wrapping/declarative/annotation}/FirstInstanceOf.java | 2 +- .../inrupt/rdf/wrapping/declarative/annotation}/Graph.java | 2 +- .../rdf/wrapping/declarative/annotation}/NamedGraph.java | 2 +- .../rdf/wrapping/declarative/annotation}/Property.java | 2 +- .../rdf/wrapping/declarative/annotation}/Resource.java | 2 +- declarative/pom.xml | 2 +- declarative/processor/pom.xml | 2 +- .../wrapping/declarative/processor/DatasetImplementor.java | 4 ++-- .../wrapping/declarative/processor/GraphImplementor.java | 2 +- .../rdf/wrapping/declarative/processor/Implementor.java | 7 +++---- .../rdf/wrapping/declarative/processor/Processor.java | 6 +++--- .../rdf/wrapping/declarative/template/ExampleDataset.java | 2 +- .../rdf/wrapping/declarative/template/ExampleGraph.java | 2 +- .../rdf/wrapping/declarative/template/ExampleNode1.java | 2 +- .../rdf/wrapping/declarative/template/ExampleNode2.java | 2 +- .../java/com/inrupt/rdf/wrapping/declarative/test/X.java | 2 +- 19 files changed, 25 insertions(+), 26 deletions(-) rename declarative/{annotations => annotation}/pom.xml (88%) rename declarative/{annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations => annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation}/Dataset.java (96%) rename declarative/{annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations => annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation}/DefaultGraph.java (96%) rename declarative/{annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations => annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation}/FirstInstanceOf.java (96%) rename declarative/{annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations => annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation}/Graph.java (96%) rename declarative/{annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations => annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation}/NamedGraph.java (96%) rename declarative/{annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations => annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation}/Property.java (96%) rename declarative/{annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations => annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation}/Resource.java (96%) diff --git a/declarative/annotations/pom.xml b/declarative/annotation/pom.xml similarity index 88% rename from declarative/annotations/pom.xml rename to declarative/annotation/pom.xml index 0a405c7c7..9019e2fe4 100644 --- a/declarative/annotations/pom.xml +++ b/declarative/annotation/pom.xml @@ -7,8 +7,8 @@ 1.0.1-SNAPSHOT - inrupt-rdf-wrapping-declarative-annotations - Inrupt RDF Wrapping Declarative - Annotations + inrupt-rdf-wrapping-declarative-annotation + Inrupt RDF Wrapping Declarative - Annotation 1.8 diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Dataset.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Dataset.java similarity index 96% rename from declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Dataset.java rename to declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Dataset.java index 9003b1491..fe1a53052 100644 --- a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Dataset.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Dataset.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotations; +package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.CLASS; diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/DefaultGraph.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/DefaultGraph.java similarity index 96% rename from declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/DefaultGraph.java rename to declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/DefaultGraph.java index 1e022cdd2..c769e3a50 100644 --- a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/DefaultGraph.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/DefaultGraph.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotations; +package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.CLASS; diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/FirstInstanceOf.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/FirstInstanceOf.java similarity index 96% rename from declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/FirstInstanceOf.java rename to declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/FirstInstanceOf.java index ddf2c116b..27328e14d 100644 --- a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/FirstInstanceOf.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/FirstInstanceOf.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotations; +package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.CLASS; diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Graph.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Graph.java similarity index 96% rename from declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Graph.java rename to declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Graph.java index 62a893e49..4b6b94768 100644 --- a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Graph.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Graph.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotations; +package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.CLASS; diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/NamedGraph.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/NamedGraph.java similarity index 96% rename from declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/NamedGraph.java rename to declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/NamedGraph.java index 69e49ea9d..d7be70915 100644 --- a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/NamedGraph.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/NamedGraph.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotations; +package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.CLASS; diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Property.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Property.java similarity index 96% rename from declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Property.java rename to declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Property.java index f2ee1fb02..60742d180 100644 --- a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Property.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Property.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotations; +package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.CLASS; diff --git a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Resource.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Resource.java similarity index 96% rename from declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Resource.java rename to declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Resource.java index c7b2ca60e..2718d9dcc 100644 --- a/declarative/annotations/src/main/java/com/inrupt/rdf/wrapping/declarative/annotations/Resource.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Resource.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotations; +package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.CLASS; diff --git a/declarative/pom.xml b/declarative/pom.xml index 0f46267e3..dfe1fe523 100644 --- a/declarative/pom.xml +++ b/declarative/pom.xml @@ -12,7 +12,7 @@ pom - annotations + annotation processor test template diff --git a/declarative/processor/pom.xml b/declarative/processor/pom.xml index e2881da8d..42e17699d 100644 --- a/declarative/processor/pom.xml +++ b/declarative/processor/pom.xml @@ -21,7 +21,7 @@ com.inrupt.rdf - inrupt-rdf-wrapping-declarative-annotations + inrupt-rdf-wrapping-declarative-annotation ${project.version} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java index a6a280c26..a316332b0 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java @@ -24,8 +24,8 @@ import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; -import com.inrupt.rdf.wrapping.declarative.annotations.DefaultGraph; -import com.inrupt.rdf.wrapping.declarative.annotations.NamedGraph; +import com.inrupt.rdf.wrapping.declarative.annotation.DefaultGraph; +import com.inrupt.rdf.wrapping.declarative.annotation.NamedGraph; import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java index 4686b25ce..92dc8517f 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -24,7 +24,7 @@ import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; -import com.inrupt.rdf.wrapping.declarative.annotations.FirstInstanceOf; +import com.inrupt.rdf.wrapping.declarative.annotation.FirstInstanceOf; import com.inrupt.rdf.wrapping.jena.WrapperModel; import javax.annotation.Generated; diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java index 12bfaf459..22a284d81 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java @@ -68,7 +68,6 @@ void implement() { } catch (IOException e) { throw new RuntimeException("could not open writer", e); } - } protected abstract void implementInternal(); @@ -81,11 +80,11 @@ static Implementor get( final TypeElement annotatedType = (TypeElement) annotatedElement; switch (annotation.getQualifiedName().toString()) { - case "com.inrupt.rdf.wrapping.declarative.annotations.Dataset": + case "com.inrupt.rdf.wrapping.declarative.annotation.Dataset": return new DatasetImplementor(processingEnvironment, annotatedType); - case "com.inrupt.rdf.wrapping.declarative.annotations.Graph": + case "com.inrupt.rdf.wrapping.declarative.annotation.Graph": return new GraphImplementor(processingEnvironment, annotatedType); - case "com.inrupt.rdf.wrapping.declarative.annotations.Resource": + case "com.inrupt.rdf.wrapping.declarative.annotation.Resource": return new ResourceImplementor(processingEnvironment, annotatedType); default: throw new RuntimeException("unknown annotation type"); diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index 2e5fbad6f..ae3d26334 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -32,9 +32,9 @@ import javax.tools.Diagnostic; @SupportedAnnotationTypes({ - "com.inrupt.rdf.wrapping.declarative.annotations.Dataset", - "com.inrupt.rdf.wrapping.declarative.annotations.Graph", - "com.inrupt.rdf.wrapping.declarative.annotations.Resource" + "com.inrupt.rdf.wrapping.declarative.annotation.Dataset", + "com.inrupt.rdf.wrapping.declarative.annotation.Graph", + "com.inrupt.rdf.wrapping.declarative.annotation.Resource" }) @SupportedSourceVersion(SourceVersion.RELEASE_8) public class Processor extends AbstractProcessor { diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java index 8122b5e4f..a074f05cf 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -import com.inrupt.rdf.wrapping.declarative.annotations.Dataset; +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; import com.inrupt.rdf.wrapping.declarative.processor.Manager; @Dataset diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java index 8ba76fce4..224489fc8 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -import com.inrupt.rdf.wrapping.declarative.annotations.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; import com.inrupt.rdf.wrapping.declarative.processor.Manager; import org.apache.jena.rdf.model.Model; diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java index 611722e75..d4b949235 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -import com.inrupt.rdf.wrapping.declarative.annotations.Resource; +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; @Resource public interface ExampleNode1 { diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java index c98452655..397582f17 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.template; -import com.inrupt.rdf.wrapping.declarative.annotations.Resource; +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; @Resource public interface ExampleNode2 { diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java index fcacdc834..9361da5ca 100644 --- a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java +++ b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.test; -import com.inrupt.rdf.wrapping.declarative.annotations.*; +import com.inrupt.rdf.wrapping.declarative.annotation.*; import com.inrupt.rdf.wrapping.declarative.processor.Manager; import org.apache.jena.rdf.model.Model; From a3c27da849e538e1c589e546c009c75a193b93ba Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 10:39:50 +0200 Subject: [PATCH 024/141] Extract `Implementor#membersAnnotatedWith` --- .../processor/DatasetImplementor.java | 70 +++++++-------- .../processor/GraphImplementor.java | 86 ++++++++----------- .../declarative/processor/Implementor.java | 16 ++++ 3 files changed, 84 insertions(+), 88 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java index a316332b0..3de512bfe 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java @@ -29,9 +29,7 @@ import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; -import javax.lang.model.util.ElementFilter; import org.apache.jena.query.Dataset; import org.apache.jena.sparql.core.DatasetGraph; @@ -71,44 +69,38 @@ protected void implementInternal() { wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("asDatasetGraph"))); // @DefaultGraph - ElementFilter.methodsIn(annotatedElement.getEnclosedElements()).stream() - .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC)) - .filter(method -> method.getAnnotation(DefaultGraph.class) != null) - .forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - sourceFile._import(returnType); - final JMethodDef defaultGraphMethod = implementation.method( - PUBLIC, - returnType, - method.getSimpleName().toString()); - defaultGraphMethod.annotate(Override.class); - defaultGraphMethod - .body() - ._return(returnType - .call("wrap") - .arg($t(implementationClass) - ._this() - .call("getDefaultModel"))); - }); + membersAnnotatedWith(DefaultGraph.class).forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + sourceFile._import(returnType); + final JMethodDef defaultGraphMethod = implementation.method( + PUBLIC, + returnType, + method.getSimpleName().toString()); + defaultGraphMethod.annotate(Override.class); + defaultGraphMethod + .body() + ._return(returnType + .call("wrap") + .arg($t(implementationClass) + ._this() + .call("getDefaultModel"))); + }); // @NamedGraph - ElementFilter.methodsIn(annotatedElement.getEnclosedElements()).stream() - .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC)) - .filter(method -> method.getAnnotation(NamedGraph.class) != null) - .forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - sourceFile._import(returnType); - final JMethodDef namedGraphMethod = implementation - .method(PUBLIC, returnType, method.getSimpleName().toString()); - namedGraphMethod.annotate(Override.class); - namedGraphMethod - .body() - ._return(returnType - .call("wrap") - .arg($t(implementationClass) - ._this() - .call("getNamedModel") - .arg(JExprs.str(method.getAnnotation(NamedGraph.class).value())))); - }); + membersAnnotatedWith(NamedGraph.class).forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + sourceFile._import(returnType); + final JMethodDef namedGraphMethod = implementation + .method(PUBLIC, returnType, method.getSimpleName().toString()); + namedGraphMethod.annotate(Override.class); + namedGraphMethod + .body() + ._return(returnType + .call("wrap") + .arg($t(implementationClass) + ._this() + .call("getNamedModel") + .arg(JExprs.str(method.getAnnotation(NamedGraph.class).value())))); + }); } } diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java index 92dc8517f..16325bf8c 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -30,9 +30,7 @@ import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; -import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; -import javax.lang.model.util.ElementFilter; import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; @@ -69,28 +67,23 @@ protected void implementInternal() { constructor.body().callSuper().arg($v("original")); // Personality - ElementFilter.methodsIn(annotatedElement.getEnclosedElements()).stream() - .filter(method -> !method.isDefault() - && !method.getModifiers().contains(Modifier.STATIC) - && !method.getReturnType().equals($t(Void.class))) - .filter(method -> method.getAnnotation(FirstInstanceOf.class) != null) - .forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final Element returnTypeElement = processingEnvironment.getTypeUtils() - .asElement(method.getReturnType()); - final String originalBinaryName = processingEnvironment - .getElementUtils() - .getBinaryName((TypeElement) returnTypeElement) - .toString(); - final String qualifiedName = originalBinaryName + "_$impl"; + membersAnnotatedWith(FirstInstanceOf.class).forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + final Element returnTypeElement = processingEnvironment.getTypeUtils() + .asElement(method.getReturnType()); + final String originalBinaryName = processingEnvironment + .getElementUtils() + .getBinaryName((TypeElement) returnTypeElement) + .toString(); + final String qualifiedName = originalBinaryName + "_$impl"; - sourceFile._import(returnType); - constructor - .body() - .call($t(implementationClass)._this().call("getPersonality"), "add") - .arg($t(qualifiedName)._class()) - .arg($t(qualifiedName).field("factory")); - }); + sourceFile._import(returnType); + constructor + .body() + .call($t(implementationClass)._this().call("getPersonality"), "add") + .arg($t(qualifiedName)._class()) + .arg($t(qualifiedName).field("factory")); + }); // Wrap method final JMethodDef wrapMethod = implementation.method(PUBLIC | STATIC, originalInterface, "wrap"); @@ -98,32 +91,27 @@ protected void implementInternal() { wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("getGraph"))); // @FirstInstanceOf - ElementFilter.methodsIn(annotatedElement.getEnclosedElements()).stream() - .filter(method -> !method.isDefault() - && !method.getModifiers().contains(Modifier.STATIC) - && !method.getReturnType().equals($t(Void.class))) - .filter(method -> method.getAnnotation(FirstInstanceOf.class) != null) - .forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final Element returnTypeElement = processingEnvironment.getTypeUtils() - .asElement(method.getReturnType()); - final String originalBinaryName = processingEnvironment - .getElementUtils() - .getBinaryName((TypeElement) returnTypeElement) - .toString(); - final String qualifiedName = originalBinaryName + "_$impl"; + membersAnnotatedWith(FirstInstanceOf.class).forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + final Element returnTypeElement = processingEnvironment.getTypeUtils() + .asElement(method.getReturnType()); + final String originalBinaryName = processingEnvironment + .getElementUtils() + .getBinaryName((TypeElement) returnTypeElement) + .toString(); + final String qualifiedName = originalBinaryName + "_$impl"; - sourceFile._import(returnType); - final JMethodDef namedGraphMethod = implementation - .method(PUBLIC, returnType, method.getSimpleName().toString()); - namedGraphMethod.annotate(Override.class); - namedGraphMethod - .body() - ._return($t(implementationClass) - ._this() - .call("firstInstanceOf") - .arg(JExprs.str(method.getAnnotation(FirstInstanceOf.class).value())) - .arg($t(qualifiedName)._class())); - }); + sourceFile._import(returnType); + final JMethodDef namedGraphMethod = implementation + .method(PUBLIC, returnType, method.getSimpleName().toString()); + namedGraphMethod.annotate(Override.class); + namedGraphMethod + .body() + ._return($t(implementationClass) + ._this() + .call("firstInstanceOf") + .arg(JExprs.str(method.getAnnotation(FirstInstanceOf.class).value())) + .arg($t(qualifiedName)._class())); + }); } } diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java index 22a284d81..ff938283f 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java @@ -20,13 +20,20 @@ */ package com.inrupt.rdf.wrapping.declarative.processor; +import static org.jboss.jdeparser.JTypes.$t; + import java.io.IOException; +import java.lang.annotation.Annotation; import java.time.Instant; +import java.util.stream.Stream; import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; +import javax.lang.model.util.ElementFilter; import org.jboss.jdeparser.*; @@ -98,4 +105,13 @@ protected void annotateAndDocumentAsGenerated(final JClassDef implementation) { .annotate(Generated.class) .value(this.getClass().getName()).value("date", Instant.now().toString()); } + + protected Stream membersAnnotatedWith(final Class annotation) { + return ElementFilter.methodsIn(annotatedElement.getEnclosedElements()).stream() + .filter(method -> !method.isDefault() + && !method.getModifiers().contains(Modifier.STATIC) + && !method.getReturnType().equals($t(Void.class))) + .filter(method -> method.getAnnotation(annotation) != null); + } + } From 9fcf2ffdccced4c866f2365018cc80f0d987abcd Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 12:48:21 +0200 Subject: [PATCH 025/141] Tidy Implementors --- .../processor/DatasetImplementor.java | 72 ++++++++-------- .../processor/GraphImplementor.java | 86 +++++++++---------- .../declarative/processor/Implementor.java | 83 +++++++++++------- .../declarative/processor/Manager.java | 7 +- .../processor/ResourceImplementor.java | 47 +++++----- 5 files changed, 163 insertions(+), 132 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java index 3de512bfe..e477d10f9 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java @@ -37,68 +37,72 @@ import org.jboss.jdeparser.*; class DatasetImplementor extends Implementor { - DatasetImplementor(final ProcessingEnvironment processingEnvironment, final TypeElement annotatedElement) { - super(processingEnvironment, annotatedElement); + DatasetImplementor(final ProcessingEnvironment environment, final TypeElement element) { + super(environment, element); } @Override protected void implementInternal() { - // Imports + addImports(); + + final JClassDef myClass = createClass(DatasetImpl.class); + final JType myType = $t(myClass); + final JExpr myInstance = myType._this(); + + createConstructor(myClass); + + createWrapMethod(myClass, myType); + + createDefaultGraphMethods(myClass, myInstance); + + createNamedGraphMethods(myClass, myInstance); + } + + private void addImports() { sourceFile ._import(Generated.class) ._import(Dataset.class) ._import(DatasetGraph.class) ._import(DatasetImpl.class); + } - // Class - final JClassDef implementation = sourceFile._class(PUBLIC, implementationClass) - ._extends(DatasetImpl.class) - ._implements(originalInterface); - - // @Generated & Javadocs - annotateAndDocumentAsGenerated(implementation); - - // Constructor - final JMethodDef constructor = implementation.constructor(PROTECTED); - constructor.param(FINAL, DatasetGraph.class, "original"); - constructor.body().callSuper().arg($v("original")); + private static void createConstructor(final JClassDef myClass) { + final JMethodDef myConstructor = myClass.constructor(PROTECTED); + myConstructor.param(FINAL, DatasetGraph.class, ORIGINAL); + myConstructor.body().callSuper().arg($v(ORIGINAL)); + } - // Wrap method - final JMethodDef wrapMethod = implementation.method(PUBLIC | STATIC, originalInterface, "wrap"); - wrapMethod.param(FINAL, Dataset.class, "original"); - wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("asDatasetGraph"))); + private void createWrapMethod(final JClassDef myClass, final JType myType) { + final JMethodDef myWrap = myClass.method(PUBLIC | STATIC, originalInterface, WRAP); + myWrap.param(FINAL, Dataset.class, ORIGINAL); + myWrap.body()._return(myType._new().arg($v(ORIGINAL).call("asDatasetGraph"))); + } - // @DefaultGraph + private void createDefaultGraphMethods(final JClassDef myClass, final JExpr myInstance) { membersAnnotatedWith(DefaultGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); sourceFile._import(returnType); - final JMethodDef defaultGraphMethod = implementation.method( - PUBLIC, - returnType, - method.getSimpleName().toString()); + final JMethodDef defaultGraphMethod = myClass + .method(PUBLIC, returnType, method.getSimpleName().toString()); defaultGraphMethod.annotate(Override.class); defaultGraphMethod .body() - ._return(returnType - .call("wrap") - .arg($t(implementationClass) - ._this() - .call("getDefaultModel"))); + ._return(returnType.call(WRAP).arg(myInstance.call("getDefaultModel"))); }); + } - // @NamedGraph + private void createNamedGraphMethods(final JClassDef myClass, final JExpr myInstance) { membersAnnotatedWith(NamedGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); sourceFile._import(returnType); - final JMethodDef namedGraphMethod = implementation + final JMethodDef namedGraphMethod = myClass .method(PUBLIC, returnType, method.getSimpleName().toString()); namedGraphMethod.annotate(Override.class); namedGraphMethod .body() ._return(returnType - .call("wrap") - .arg($t(implementationClass) - ._this() + .call(WRAP) + .arg(myInstance .call("getNamedModel") .arg(JExprs.str(method.getAnnotation(NamedGraph.class).value())))); }); diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java index 16325bf8c..ee855c3a4 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -29,7 +29,6 @@ import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import org.apache.jena.graph.Graph; @@ -38,80 +37,79 @@ import org.jboss.jdeparser.*; class GraphImplementor extends Implementor { - GraphImplementor(final ProcessingEnvironment processingEnvironment, final TypeElement annotatedElement) { - super(processingEnvironment, annotatedElement); + GraphImplementor(final ProcessingEnvironment environment, final TypeElement element) { + super(environment, element); } @Override protected void implementInternal() { - // Imports + addImports(); + + final JClassDef myClass = createClass(WrapperModel.class); + final JType myType = $t(myClass); + final JExpr myInstance = myType._this(); + + final JMethodDef myConstructor = createConstructor(myClass); + + addImplementationsToPersonality(myConstructor, myInstance); + + createWrapMethod(myClass, myType); + + createFirstInstanceOfMethods(myClass, myInstance); + } + + private void addImports() { sourceFile ._import(WrapperModel.class) ._import(Generated.class) ._import(Graph.class) ._import(Model.class) ._import(ModelCom.class); + } - // Class - final JClassDef implementation = sourceFile - ._class(PUBLIC, implementationClass) - ._extends(WrapperModel.class) - ._implements(originalInterface); - - // @Generated & Javadocs - annotateAndDocumentAsGenerated(implementation); + private static JMethodDef createConstructor(final JClassDef myClass) { + final JMethodDef myConstructor = myClass.constructor(PROTECTED); + myConstructor.param(FINAL, Graph.class, ORIGINAL); + myConstructor.body().callSuper().arg($v(ORIGINAL)); - // Constructor - final JMethodDef constructor = implementation.constructor(PROTECTED); - constructor.param(FINAL, Graph.class, "original"); - constructor.body().callSuper().arg($v("original")); + return myConstructor; + } - // Personality + private void addImplementationsToPersonality(final JMethodDef myConstructor, final JExpr myInstance) { membersAnnotatedWith(FirstInstanceOf.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); - final Element returnTypeElement = processingEnvironment.getTypeUtils() - .asElement(method.getReturnType()); - final String originalBinaryName = processingEnvironment - .getElementUtils() - .getBinaryName((TypeElement) returnTypeElement) - .toString(); - final String qualifiedName = originalBinaryName + "_$impl"; + final JType implementationType = returnTypeAsImplementation(method); sourceFile._import(returnType); - constructor + myConstructor .body() - .call($t(implementationClass)._this().call("getPersonality"), "add") - .arg($t(qualifiedName)._class()) - .arg($t(qualifiedName).field("factory")); + .call(myInstance.call("getPersonality"), "add") + .arg(implementationType._class()) + .arg(implementationType.field(ResourceImplementor.FACTORY)); }); + } - // Wrap method - final JMethodDef wrapMethod = implementation.method(PUBLIC | STATIC, originalInterface, "wrap"); - wrapMethod.param(FINAL, Model.class, "original"); - wrapMethod.body()._return($t(implementationClass)._new().arg($v("original").call("getGraph"))); + private void createWrapMethod(final JClassDef myClass, final JType myType) { + final JMethodDef myWrap = myClass.method(PUBLIC | STATIC, originalInterface, WRAP); + myWrap.param(FINAL, Model.class, ORIGINAL); + myWrap.body()._return(myType._new().arg($v(ORIGINAL).call("getGraph"))); + } - // @FirstInstanceOf + private void createFirstInstanceOfMethods(final JClassDef myClass, final JExpr myInstance) { membersAnnotatedWith(FirstInstanceOf.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); - final Element returnTypeElement = processingEnvironment.getTypeUtils() - .asElement(method.getReturnType()); - final String originalBinaryName = processingEnvironment - .getElementUtils() - .getBinaryName((TypeElement) returnTypeElement) - .toString(); - final String qualifiedName = originalBinaryName + "_$impl"; + final JType implementationType = returnTypeAsImplementation(method); sourceFile._import(returnType); - final JMethodDef namedGraphMethod = implementation + final JMethodDef namedGraphMethod = myClass .method(PUBLIC, returnType, method.getSimpleName().toString()); namedGraphMethod.annotate(Override.class); namedGraphMethod .body() - ._return($t(implementationClass) - ._this() + ._return(myInstance .call("firstInstanceOf") .arg(JExprs.str(method.getAnnotation(FirstInstanceOf.class).value())) - .arg($t(qualifiedName)._class())); + .arg(implementationType._class())); }); } } diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java index ff938283f..84e4a3fba 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.processor; +import static org.jboss.jdeparser.JMod.PUBLIC; import static org.jboss.jdeparser.JTypes.$t; import java.io.IOException; @@ -38,32 +39,30 @@ import org.jboss.jdeparser.*; abstract class Implementor { - protected final ProcessingEnvironment processingEnvironment; - protected final TypeElement annotatedElement; + protected static final String ORIGINAL = "original"; + protected static final String WRAP = "wrap"; + + protected final ProcessingEnvironment environment; + protected final TypeElement element; protected final JSources sources; - protected final String implementationClass; protected final String originalInterface; protected JSourceFile sourceFile; - protected Implementor(final ProcessingEnvironment processingEnvironment, final TypeElement annotatedElement) { - this.processingEnvironment = processingEnvironment; - this.annotatedElement = annotatedElement; + private final String implementationClass; - originalInterface = annotatedElement.getQualifiedName().toString(); - final String originalBinaryName = processingEnvironment - .getElementUtils() - .getBinaryName(annotatedElement) - .toString(); - final String qualifiedName = originalBinaryName + "_$impl"; + protected Implementor(final ProcessingEnvironment environment, final TypeElement element) { + this.environment = environment; + this.element = element; + + originalInterface = element.getQualifiedName().toString(); + final String originalBinaryName = environment.getElementUtils().getBinaryName(element).toString(); + final String qualifiedName = asImplementation(originalBinaryName); final int lastDot = originalBinaryName.lastIndexOf('.'); implementationClass = qualifiedName.substring(lastDot + 1); - final String packageName = processingEnvironment.getElementUtils() - .getPackageOf(annotatedElement) - .getQualifiedName().toString(); - - final JFiler jFiler = JFiler.newInstance(processingEnvironment.getFiler()); - sources = JDeparser.createSources(jFiler, new FormatPreferences()); + final String packageName = environment.getElementUtils().getPackageOf(element).getQualifiedName().toString(); + final JFiler filer = JFiler.newInstance(environment.getFiler()); + sources = JDeparser.createSources(filer, new FormatPreferences()); sourceFile = sources.createSourceFile(packageName, implementationClass); } @@ -79,39 +78,59 @@ void implement() { protected abstract void implementInternal(); - static Implementor get( - final TypeElement annotation, - final ProcessingEnvironment processingEnvironment, - final Element annotatedElement) { + static Implementor get(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { - final TypeElement annotatedType = (TypeElement) annotatedElement; + final TypeElement annotatedType = (TypeElement) element; switch (annotation.getQualifiedName().toString()) { case "com.inrupt.rdf.wrapping.declarative.annotation.Dataset": - return new DatasetImplementor(processingEnvironment, annotatedType); + return new DatasetImplementor(env, annotatedType); case "com.inrupt.rdf.wrapping.declarative.annotation.Graph": - return new GraphImplementor(processingEnvironment, annotatedType); + return new GraphImplementor(env, annotatedType); case "com.inrupt.rdf.wrapping.declarative.annotation.Resource": - return new ResourceImplementor(processingEnvironment, annotatedType); + return new ResourceImplementor(env, annotatedType); default: throw new RuntimeException("unknown annotation type"); } } - protected void annotateAndDocumentAsGenerated(final JClassDef implementation) { - implementation.docComment().text("Warning, this class consists of generated code."); + static String asImplementation(final String original) { + return original + "_$impl"; + } - implementation - .annotate(Generated.class) - .value(this.getClass().getName()).value("date", Instant.now().toString()); + protected JClassDef createClass(final Class base) { + final JClassDef myClass = sourceFile + ._class(PUBLIC, implementationClass) + ._extends(base) + ._implements(originalInterface); + + annotateAndDocumentAsGenerated(myClass); + + return myClass; } protected Stream membersAnnotatedWith(final Class annotation) { - return ElementFilter.methodsIn(annotatedElement.getEnclosedElements()).stream() + return ElementFilter.methodsIn(element.getEnclosedElements()).stream() .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC) && !method.getReturnType().equals($t(Void.class))) .filter(method -> method.getAnnotation(annotation) != null); } + protected JType returnTypeAsImplementation(final ExecutableElement method) { + final Element returnType = environment.getTypeUtils().asElement(method.getReturnType()); + final String originalBinaryName = environment + .getElementUtils() + .getBinaryName((TypeElement) returnType) + .toString(); + return $t(asImplementation(originalBinaryName)); + } + + private void annotateAndDocumentAsGenerated(final JClassDef implementation) { + implementation.docComment().text("Warning, this class consists of generated code."); + + implementation + .annotate(Generated.class) + .value(this.getClass().getName()).value("date", Instant.now().toString()); + } } diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Manager.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Manager.java index dd7795a34..3d65fd5f2 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Manager.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Manager.java @@ -20,6 +20,9 @@ */ package com.inrupt.rdf.wrapping.declarative.processor; +import static com.inrupt.rdf.wrapping.declarative.processor.Implementor.WRAP; +import static com.inrupt.rdf.wrapping.declarative.processor.Implementor.asImplementation; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -44,7 +47,7 @@ public static T wrap(final Dataset original, final Class interfaceType) { private static T wrap(final Object original, final Class interfaceType, final Class parameterType) { final ClassLoader classLoader = interfaceType.getClassLoader(); - final String implTypeName = interfaceType.getName() + "_$impl"; + final String implTypeName = asImplementation(interfaceType.getName()); final Class implClass; try { @@ -59,7 +62,7 @@ private static T wrap(final Object original, final Class interfaceType, f final Method wrapMethod; try { - wrapMethod = implClass.getMethod("wrap", parameterType); + wrapMethod = implClass.getMethod(WRAP, parameterType); } catch (NoSuchMethodException e) { throw new RuntimeException("wrap method not found", e); } diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java index ff8af8c05..fee28d100 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java @@ -36,15 +36,28 @@ import org.apache.jena.graph.Node; import org.jboss.jdeparser.JClassDef; import org.jboss.jdeparser.JMethodDef; +import org.jboss.jdeparser.JType; class ResourceImplementor extends Implementor { - ResourceImplementor(final ProcessingEnvironment processingEnvironment, final TypeElement annotatedElement) { - super(processingEnvironment, annotatedElement); + static final String FACTORY = "factory"; + + ResourceImplementor(final ProcessingEnvironment environment, final TypeElement element) { + super(environment, element); } @Override protected void implementInternal() { - // Imports + addImports(); + + final JClassDef myClass = createClass(WrapperResource.class); + final JType myType = $t(myClass); + + createFactoryField(myClass, myType); + + createConstructor(myClass); + } + + private void addImports() { sourceFile ._import(UriOrBlankFactory.class) ._import(WrapperResource.class) @@ -52,26 +65,20 @@ protected void implementInternal() { ._import(EnhGraph.class) ._import(Implementation.class) ._import(Node.class); + } - // Class - final JClassDef implementation = sourceFile._class(PUBLIC, implementationClass) - ._extends(WrapperResource.class) - ._implements(originalInterface); - - // @Generated & Javadocs - annotateAndDocumentAsGenerated(implementation); - - // Factory - implementation.field( + private static void createFactoryField(final JClassDef myClass, final JType myType) { + myClass.field( STATIC | FINAL, Implementation.class, - "factory", - $t(UriOrBlankFactory.class)._new().arg($t(implementationClass).methodRef("new"))); + FACTORY, + $t(UriOrBlankFactory.class)._new().arg(myType.methodRef("new"))); + } - // Constructor - final JMethodDef constructor = implementation.constructor(PROTECTED); - constructor.param(FINAL, Node.class, "node"); - constructor.param(FINAL, EnhGraph.class, "graph"); - constructor.body().callSuper().arg($v("node")).arg($v("graph")); + private static void createConstructor(final JClassDef myClass) { + final JMethodDef myConstructor = myClass.constructor(PROTECTED); + myConstructor.param(FINAL, Node.class, "node"); + myConstructor.param(FINAL, EnhGraph.class, "graph"); + myConstructor.body().callSuper().arg($v("node")).arg($v("graph")); } } From 1de14bb174e6f3b8a8fca94fbd9028d43f48a26f Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 13:17:02 +0200 Subject: [PATCH 026/141] Extend `@FirstInstance` to multiple classes --- ...ava => OptionalFirstInstanceOfEither.java} | 4 +- .../processor/GraphImplementor.java | 31 +++++++----- .../template/ExampleGraph_$impl.java | 2 +- .../rdf/wrapping/declarative/test/X.java | 2 +- .../rdf/wrapping/jena/WrapperModel.java | 47 +++++++++++++++++-- 5 files changed, 66 insertions(+), 20 deletions(-) rename declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/{FirstInstanceOf.java => OptionalFirstInstanceOfEither.java} (95%) diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/FirstInstanceOf.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstInstanceOfEither.java similarity index 95% rename from declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/FirstInstanceOf.java rename to declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstInstanceOfEither.java index 27328e14d..17188cb0d 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/FirstInstanceOf.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstInstanceOfEither.java @@ -30,6 +30,6 @@ @Target(METHOD) @Retention(CLASS) @Documented -public @interface FirstInstanceOf { - String value(); +public @interface OptionalFirstInstanceOfEither { + String[] value(); } diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java index ee855c3a4..12f2551a4 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -24,7 +24,7 @@ import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; -import com.inrupt.rdf.wrapping.declarative.annotation.FirstInstanceOf; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; import com.inrupt.rdf.wrapping.jena.WrapperModel; import javax.annotation.Generated; @@ -55,7 +55,7 @@ protected void implementInternal() { createWrapMethod(myClass, myType); - createFirstInstanceOfMethods(myClass, myInstance); + createOptionalFirstInstanceOfEitherMethods(myClass, myInstance); } private void addImports() { @@ -76,7 +76,7 @@ private static JMethodDef createConstructor(final JClassDef myClass) { } private void addImplementationsToPersonality(final JMethodDef myConstructor, final JExpr myInstance) { - membersAnnotatedWith(FirstInstanceOf.class).forEach(method -> { + membersAnnotatedWith(OptionalFirstInstanceOfEither.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = returnTypeAsImplementation(method); @@ -95,21 +95,26 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { myWrap.body()._return(myType._new().arg($v(ORIGINAL).call("getGraph"))); } - private void createFirstInstanceOfMethods(final JClassDef myClass, final JExpr myInstance) { - membersAnnotatedWith(FirstInstanceOf.class).forEach(method -> { + private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, final JExpr myInstance) { + membersAnnotatedWith(OptionalFirstInstanceOfEither.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = returnTypeAsImplementation(method); sourceFile._import(returnType); - final JMethodDef namedGraphMethod = myClass - .method(PUBLIC, returnType, method.getSimpleName().toString()); + final JMethodDef namedGraphMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); namedGraphMethod.annotate(Override.class); - namedGraphMethod - .body() - ._return(myInstance - .call("firstInstanceOf") - .arg(JExprs.str(method.getAnnotation(FirstInstanceOf.class).value())) - .arg(implementationType._class())); + + // Call model wrapper convenience method passing projection class argument + final JCall wrapperConvenienceCall = myInstance + .call("optionalFirstInstanceOfEither") + .arg(implementationType._class()); + + // Pass each filter class value from the annotation as additional argument + for (final String s : method.getAnnotation(OptionalFirstInstanceOfEither.class).value()) { + wrapperConvenienceCall.arg(JExprs.str(s)); + } + + namedGraphMethod.body()._return(wrapperConvenienceCall); }); } } diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java index e8dc76cbe..5a76a56d1 100644 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java +++ b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java @@ -51,6 +51,6 @@ public static ExampleGraph create() { @Override public ExampleNode1 getResource() { - return firstInstanceOf("urn:example:C", ExampleNode1_$impl.class); + return optionalFirstInstanceOfEither(ExampleNode1_$impl.class, "urn:example:C"); } } diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java index 9361da5ca..a6b8a0c3b 100644 --- a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java +++ b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java @@ -43,7 +43,7 @@ static Y wrap(final Model original) { return Manager.wrap(original, Y.class); } - @FirstInstanceOf("urn:example:C") + @OptionalFirstInstanceOfEither({"urn:example:C", "urn:example:Other"}) Z getResource(); @Resource diff --git a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java index 079e82c35..56eb22c98 100644 --- a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java +++ b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java @@ -20,8 +20,11 @@ */ package com.inrupt.rdf.wrapping.jena; +import java.util.Arrays; +import java.util.stream.Stream; + import org.apache.jena.graph.Graph; -import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.*; import org.apache.jena.rdf.model.impl.ModelCom; import org.apache.jena.vocabulary.RDF; @@ -30,10 +33,48 @@ protected WrapperModel(final Graph base) { super(base); } - protected T firstInstanceOf(final String clazz, final Class view) { - return listSubjectsWithProperty(RDF.type, createResource(clazz)) + protected T optionalFirstInstanceOfEither(final Class view, final String... classes) { + return listStatements(new InstanceOfEitherSelector(classes)) + .mapWith(Statement::getSubject) .mapWith(subject -> subject.as(view)) .nextOptional() .orElse(null); } + + private static final class InstanceOfEitherSelector implements Selector { + private final Stream classes; + + private InstanceOfEitherSelector(final String[] classes) { + this.classes = Arrays.stream(classes).map(ResourceFactory::createResource); + } + + @Override + public boolean test(final Statement statement) { + if (!getPredicate().equals(statement.getPredicate())) { + return false; + } + + return classes.anyMatch(clazz -> clazz.equals(statement.getObject())); + } + + @Override + public Property getPredicate() { + return RDF.type; + } + + @Override + public boolean isSimple() { + return false; + } + + @Override + public Resource getSubject() { + return null; + } + + @Override + public RDFNode getObject() { + return null; + } + } } From 5cbee866d7903878976215c3c4085648466d6a1d Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 20:45:48 +0200 Subject: [PATCH 027/141] Discard annotations at compile --- .../inrupt/rdf/wrapping/declarative/annotation/Dataset.java | 4 ++-- .../rdf/wrapping/declarative/annotation/DefaultGraph.java | 4 ++-- .../com/inrupt/rdf/wrapping/declarative/annotation/Graph.java | 4 ++-- .../rdf/wrapping/declarative/annotation/NamedGraph.java | 4 ++-- .../declarative/annotation/OptionalFirstInstanceOfEither.java | 4 ++-- .../inrupt/rdf/wrapping/declarative/annotation/Property.java | 4 ++-- .../inrupt/rdf/wrapping/declarative/annotation/Resource.java | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Dataset.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Dataset.java index fe1a53052..7db497266 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Dataset.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Dataset.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; +import static java.lang.annotation.RetentionPolicy.SOURCE; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(TYPE) -@Retention(CLASS) +@Retention(SOURCE) @Documented public @interface Dataset { } diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/DefaultGraph.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/DefaultGraph.java index c769e3a50..2d53f9afe 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/DefaultGraph.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/DefaultGraph.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.CLASS; +import static java.lang.annotation.RetentionPolicy.SOURCE; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(METHOD) -@Retention(CLASS) +@Retention(SOURCE) @Documented public @interface DefaultGraph { } diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Graph.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Graph.java index 4b6b94768..eedd4cbe7 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Graph.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Graph.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; +import static java.lang.annotation.RetentionPolicy.SOURCE; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(TYPE) -@Retention(CLASS) +@Retention(SOURCE) @Documented public @interface Graph { } diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/NamedGraph.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/NamedGraph.java index d7be70915..c8514351f 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/NamedGraph.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/NamedGraph.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.CLASS; +import static java.lang.annotation.RetentionPolicy.SOURCE; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(METHOD) -@Retention(CLASS) +@Retention(SOURCE) @Documented public @interface NamedGraph { String value(); diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstInstanceOfEither.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstInstanceOfEither.java index 17188cb0d..67743eaac 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstInstanceOfEither.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstInstanceOfEither.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.CLASS; +import static java.lang.annotation.RetentionPolicy.SOURCE; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(METHOD) -@Retention(CLASS) +@Retention(SOURCE) @Documented public @interface OptionalFirstInstanceOfEither { String[] value(); diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Property.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Property.java index 60742d180..9cfa09bb4 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Property.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Property.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.CLASS; +import static java.lang.annotation.RetentionPolicy.SOURCE; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(METHOD) -@Retention(CLASS) +@Retention(SOURCE) @Documented public @interface Property { } diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Resource.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Resource.java index 2718d9dcc..e15566f0f 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Resource.java +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Resource.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.declarative.annotation; import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.CLASS; +import static java.lang.annotation.RetentionPolicy.SOURCE; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(TYPE) -@Retention(CLASS) +@Retention(SOURCE) @Documented public @interface Resource { } From d494318c7b1c6425f700e2f3f40874534868993a Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 21:08:20 +0200 Subject: [PATCH 028/141] Ignore literals in instance selector --- .../main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java index 56eb22c98..bd12213fc 100644 --- a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java +++ b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java @@ -50,6 +50,10 @@ private InstanceOfEitherSelector(final String[] classes) { @Override public boolean test(final Statement statement) { + if (!statement.getObject().isResource()) { + return false; + } + if (!getPredicate().equals(statement.getPredicate())) { return false; } From f160565244d354f3a4f4205f107bd59883e04cbb Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 21:12:31 +0200 Subject: [PATCH 029/141] Don't reuse classes in instance selector --- .../com/inrupt/rdf/wrapping/jena/WrapperModel.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java index bd12213fc..3288d2b34 100644 --- a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java +++ b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java @@ -21,7 +21,8 @@ package com.inrupt.rdf.wrapping.jena; import java.util.Arrays; -import java.util.stream.Stream; +import java.util.List; +import java.util.stream.Collectors; import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.*; @@ -42,10 +43,13 @@ protected T optionalFirstInstanceOfEither(final Class vie } private static final class InstanceOfEitherSelector implements Selector { - private final Stream classes; + private final List classes; private InstanceOfEitherSelector(final String[] classes) { - this.classes = Arrays.stream(classes).map(ResourceFactory::createResource); + this.classes = Arrays + .stream(classes) + .map(ResourceFactory::createResource) + .collect(Collectors.toList()); } @Override @@ -58,7 +62,7 @@ public boolean test(final Statement statement) { return false; } - return classes.anyMatch(clazz -> clazz.equals(statement.getObject())); + return classes.contains(statement.getObject().asResource()); } @Override From 8d0973b752876e316dcc20a82f0a04504d19d505 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 21:18:35 +0200 Subject: [PATCH 030/141] Naming --- .../declarative/processor/DatasetImplementor.java | 12 ++++++------ .../declarative/processor/GraphImplementor.java | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java index e477d10f9..81a9c3b61 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java @@ -82,10 +82,10 @@ private void createDefaultGraphMethods(final JClassDef myClass, final JExpr myIn membersAnnotatedWith(DefaultGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); sourceFile._import(returnType); - final JMethodDef defaultGraphMethod = myClass + final JMethodDef myMethod = myClass .method(PUBLIC, returnType, method.getSimpleName().toString()); - defaultGraphMethod.annotate(Override.class); - defaultGraphMethod + myMethod.annotate(Override.class); + myMethod .body() ._return(returnType.call(WRAP).arg(myInstance.call("getDefaultModel"))); }); @@ -95,10 +95,10 @@ private void createNamedGraphMethods(final JClassDef myClass, final JExpr myInst membersAnnotatedWith(NamedGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); sourceFile._import(returnType); - final JMethodDef namedGraphMethod = myClass + final JMethodDef myMethod = myClass .method(PUBLIC, returnType, method.getSimpleName().toString()); - namedGraphMethod.annotate(Override.class); - namedGraphMethod + myMethod.annotate(Override.class); + myMethod .body() ._return(returnType .call(WRAP) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java index 12f2551a4..ce645314f 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -101,8 +101,8 @@ private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, final JType implementationType = returnTypeAsImplementation(method); sourceFile._import(returnType); - final JMethodDef namedGraphMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); - namedGraphMethod.annotate(Override.class); + final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); + myMethod.annotate(Override.class); // Call model wrapper convenience method passing projection class argument final JCall wrapperConvenienceCall = myInstance @@ -114,7 +114,7 @@ private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, wrapperConvenienceCall.arg(JExprs.str(s)); } - namedGraphMethod.body()._return(wrapperConvenienceCall); + myMethod.body()._return(wrapperConvenienceCall); }); } } From 3ae2b1530844f8b7d805ef11e2c4bdc18eb4bf09 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 21:49:01 +0200 Subject: [PATCH 031/141] Implement `@FirstSubjectOf` --- .../OptionalFirstSubjectOfEither.java | 35 +++++++++++++ .../processor/DatasetImplementor.java | 4 +- .../processor/GraphImplementor.java | 51 ++++++++++++++----- .../declarative/processor/Implementor.java | 9 +++- .../rdf/wrapping/declarative/test/X.java | 3 ++ .../rdf/wrapping/declarative/test/XTest.java | 12 +++++ .../rdf/wrapping/jena/WrapperModel.java | 44 ++++++++++++++++ 7 files changed, 142 insertions(+), 16 deletions(-) create mode 100644 declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstSubjectOfEither.java diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstSubjectOfEither.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstSubjectOfEither.java new file mode 100644 index 000000000..6eef65cef --- /dev/null +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstSubjectOfEither.java @@ -0,0 +1,35 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.annotation; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target(METHOD) +@Retention(SOURCE) +@Documented +public @interface OptionalFirstSubjectOfEither { + String[] value(); +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java index 81a9c3b61..b3ffc8f73 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java @@ -79,7 +79,7 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { } private void createDefaultGraphMethods(final JClassDef myClass, final JExpr myInstance) { - membersAnnotatedWith(DefaultGraph.class).forEach(method -> { + membersAnnotatedWithAny(DefaultGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); sourceFile._import(returnType); final JMethodDef myMethod = myClass @@ -92,7 +92,7 @@ private void createDefaultGraphMethods(final JClassDef myClass, final JExpr myIn } private void createNamedGraphMethods(final JClassDef myClass, final JExpr myInstance) { - membersAnnotatedWith(NamedGraph.class).forEach(method -> { + membersAnnotatedWithAny(NamedGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); sourceFile._import(returnType); final JMethodDef myMethod = myClass diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java index ce645314f..e580da257 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -25,6 +25,7 @@ import static org.jboss.jdeparser.JTypes.$t; import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; import com.inrupt.rdf.wrapping.jena.WrapperModel; import javax.annotation.Generated; @@ -56,6 +57,8 @@ protected void implementInternal() { createWrapMethod(myClass, myType); createOptionalFirstInstanceOfEitherMethods(myClass, myInstance); + + createOptionalFirstSubjectOfEitherMethods(myClass, myInstance); } private void addImports() { @@ -76,17 +79,18 @@ private static JMethodDef createConstructor(final JClassDef myClass) { } private void addImplementationsToPersonality(final JMethodDef myConstructor, final JExpr myInstance) { - membersAnnotatedWith(OptionalFirstInstanceOfEither.class).forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final JType implementationType = returnTypeAsImplementation(method); - - sourceFile._import(returnType); - myConstructor - .body() - .call(myInstance.call("getPersonality"), "add") - .arg(implementationType._class()) - .arg(implementationType.field(ResourceImplementor.FACTORY)); - }); + membersAnnotatedWithAny(OptionalFirstInstanceOfEither.class, OptionalFirstSubjectOfEither.class) + .forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + final JType implementationType = returnTypeAsImplementation(method); + + sourceFile._import(returnType); + myConstructor + .body() + .call(myInstance.call("getPersonality"), "add") + .arg(implementationType._class()) + .arg(implementationType.field(ResourceImplementor.FACTORY)); + }); } private void createWrapMethod(final JClassDef myClass, final JType myType) { @@ -96,7 +100,7 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { } private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, final JExpr myInstance) { - membersAnnotatedWith(OptionalFirstInstanceOfEither.class).forEach(method -> { + membersAnnotatedWithAny(OptionalFirstInstanceOfEither.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = returnTypeAsImplementation(method); @@ -117,4 +121,27 @@ private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, myMethod.body()._return(wrapperConvenienceCall); }); } + + private void createOptionalFirstSubjectOfEitherMethods(final JClassDef myClass, final JExpr myInstance) { + membersAnnotatedWithAny(OptionalFirstSubjectOfEither.class).forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + final JType implementationType = returnTypeAsImplementation(method); + + sourceFile._import(returnType); + final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); + myMethod.annotate(Override.class); + + // Call model wrapper convenience method passing projection class argument + final JCall wrapperConvenienceCall = myInstance + .call("optionalFirstSubjectOfEither") + .arg(implementationType._class()); + + // Pass each filter predicate value from the annotation as additional argument + for (final String s : method.getAnnotation(OptionalFirstSubjectOfEither.class).value()) { + wrapperConvenienceCall.arg(JExprs.str(s)); + } + + myMethod.body()._return(wrapperConvenienceCall); + }); + } } diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java index 84e4a3fba..509267280 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.lang.annotation.Annotation; import java.time.Instant; +import java.util.Arrays; import java.util.stream.Stream; import javax.annotation.Generated; @@ -109,12 +110,16 @@ protected JClassDef createClass(final Class base) { return myClass; } - protected Stream membersAnnotatedWith(final Class annotation) { + @SafeVarargs + protected final Stream membersAnnotatedWithAny( + final Class... annotations) { + return ElementFilter.methodsIn(element.getEnclosedElements()).stream() .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC) && !method.getReturnType().equals($t(Void.class))) - .filter(method -> method.getAnnotation(annotation) != null); + .filter(method -> Arrays.stream(annotations) + .anyMatch(annotation -> method.getAnnotation(annotation) != null)); } protected JType returnTypeAsImplementation(final ExecutableElement method) { diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java index a6b8a0c3b..49d9b439e 100644 --- a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java +++ b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java @@ -46,6 +46,9 @@ static Y wrap(final Model original) { @OptionalFirstInstanceOfEither({"urn:example:C", "urn:example:Other"}) Z getResource(); + @OptionalFirstSubjectOfEither({"urn:example:p", "urn:example:Other"}) + Z getResource2(); + @Resource interface Z { } diff --git a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java index c0762e94d..3f12f6855 100644 --- a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java +++ b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java @@ -70,6 +70,14 @@ void graphCanGetFirstInstanceOf() { assertDoesNotThrow(y::getResource); } + @Test + void graphCanGetFirstSubjectOf() { + final Model model = ModelFactory.createDefaultModel(); + final X.Y y = X.Y.wrap(model); + + assertDoesNotThrow(y::getResource2); + } + @Test void e2e() { final Dataset dataset = datasetFrom("" + @@ -79,13 +87,17 @@ void e2e() { " [\n" + " a :C ;\n" + " ] .\n" + + "\n" + + " [ :p 0 ] .\n" + "}\n"); final X x = X.wrap(dataset); final X.Y y = x.getNamedGraph(); final X.Y.Z z = y.getResource(); + final X.Y.Z z2 = y.getResource2(); System.out.println(z); + System.out.println(z2); } private static Dataset datasetFrom(final String rdf) { diff --git a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java index 3288d2b34..9cbf4c56a 100644 --- a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java +++ b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java @@ -42,6 +42,14 @@ protected T optionalFirstInstanceOfEither(final Class vie .orElse(null); } + protected T optionalFirstSubjectOfEither(final Class view, final String... predicates) { + return listStatements(new EitherPredicateSelector(predicates)) + .mapWith(Statement::getSubject) + .mapWith(subject -> subject.as(view)) + .nextOptional() + .orElse(null); + } + private static final class InstanceOfEitherSelector implements Selector { private final List classes; @@ -85,4 +93,40 @@ public RDFNode getObject() { return null; } } + + private static final class EitherPredicateSelector implements Selector { + private final List predicates; + + private EitherPredicateSelector(final String[] predicates) { + this.predicates = Arrays + .stream(predicates) + .map(ResourceFactory::createProperty) + .collect(Collectors.toList()); + } + + @Override + public boolean test(final Statement statement) { + return predicates.contains(statement.getPredicate()); + } + + @Override + public boolean isSimple() { + return false; + } + + @Override + public Resource getSubject() { + return null; + } + + @Override + public Property getPredicate() { + return null; + } + + @Override + public RDFNode getObject() { + return null; + } + } } From a52b047e09d08054564d1f01b1dd38e8e57cbe96 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 21:55:54 +0200 Subject: [PATCH 032/141] Implement `@FirstObjectOf` --- .../OptionalFirstObjectOfEither.java | 35 +++++++++++++++++++ .../processor/GraphImplementor.java | 31 +++++++++++++++- .../rdf/wrapping/declarative/test/X.java | 3 ++ .../rdf/wrapping/declarative/test/XTest.java | 12 ++++++- .../rdf/wrapping/jena/WrapperModel.java | 8 +++++ 5 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstObjectOfEither.java diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstObjectOfEither.java b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstObjectOfEither.java new file mode 100644 index 000000000..f6cfd2b75 --- /dev/null +++ b/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstObjectOfEither.java @@ -0,0 +1,35 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.annotation; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target(METHOD) +@Retention(SOURCE) +@Documented +public @interface OptionalFirstObjectOfEither { + String[] value(); +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java index e580da257..2d3f91901 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -25,6 +25,7 @@ import static org.jboss.jdeparser.JTypes.$t; import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstObjectOfEither; import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; import com.inrupt.rdf.wrapping.jena.WrapperModel; @@ -59,6 +60,8 @@ protected void implementInternal() { createOptionalFirstInstanceOfEitherMethods(myClass, myInstance); createOptionalFirstSubjectOfEitherMethods(myClass, myInstance); + + createOptionalFirstObjectOfEitherMethods(myClass, myInstance); } private void addImports() { @@ -79,7 +82,10 @@ private static JMethodDef createConstructor(final JClassDef myClass) { } private void addImplementationsToPersonality(final JMethodDef myConstructor, final JExpr myInstance) { - membersAnnotatedWithAny(OptionalFirstInstanceOfEither.class, OptionalFirstSubjectOfEither.class) + membersAnnotatedWithAny( + OptionalFirstInstanceOfEither.class, + OptionalFirstSubjectOfEither.class, + OptionalFirstObjectOfEither.class) .forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = returnTypeAsImplementation(method); @@ -144,4 +150,27 @@ private void createOptionalFirstSubjectOfEitherMethods(final JClassDef myClass, myMethod.body()._return(wrapperConvenienceCall); }); } + + private void createOptionalFirstObjectOfEitherMethods(final JClassDef myClass, final JExpr myInstance) { + membersAnnotatedWithAny(OptionalFirstObjectOfEither.class).forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + final JType implementationType = returnTypeAsImplementation(method); + + sourceFile._import(returnType); + final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); + myMethod.annotate(Override.class); + + // Call model wrapper convenience method passing projection class argument + final JCall wrapperConvenienceCall = myInstance + .call("optionalFirstObjectOfEither") + .arg(implementationType._class()); + + // Pass each filter predicate value from the annotation as additional argument + for (final String s : method.getAnnotation(OptionalFirstObjectOfEither.class).value()) { + wrapperConvenienceCall.arg(JExprs.str(s)); + } + + myMethod.body()._return(wrapperConvenienceCall); + }); + } } diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java index 49d9b439e..2e39cc04b 100644 --- a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java +++ b/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java @@ -49,6 +49,9 @@ static Y wrap(final Model original) { @OptionalFirstSubjectOfEither({"urn:example:p", "urn:example:Other"}) Z getResource2(); + @OptionalFirstObjectOfEither({"urn:example:p", "urn:example:Other"}) + Z getResource3(); + @Resource interface Z { } diff --git a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java index 3f12f6855..429bc29d0 100644 --- a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java +++ b/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java @@ -78,6 +78,14 @@ void graphCanGetFirstSubjectOf() { assertDoesNotThrow(y::getResource2); } + @Test + void graphCanGetFirstObjectOf() { + final Model model = ModelFactory.createDefaultModel(); + final X.Y y = X.Y.wrap(model); + + assertDoesNotThrow(y::getResource3); + } + @Test void e2e() { final Dataset dataset = datasetFrom("" + @@ -88,16 +96,18 @@ void e2e() { " a :C ;\n" + " ] .\n" + "\n" + - " [ :p 0 ] .\n" + + " [ :p [] ] .\n" + "}\n"); final X x = X.wrap(dataset); final X.Y y = x.getNamedGraph(); final X.Y.Z z = y.getResource(); final X.Y.Z z2 = y.getResource2(); + final X.Y.Z z3 = y.getResource3(); System.out.println(z); System.out.println(z2); + System.out.println(z3); } private static Dataset datasetFrom(final String rdf) { diff --git a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java index 9cbf4c56a..7ccfdd2e4 100644 --- a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java +++ b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java @@ -50,6 +50,14 @@ protected T optionalFirstSubjectOfEither(final Class view .orElse(null); } + protected T optionalFirstObjectOfEither(final Class view, final String... predicates) { + return listStatements(new EitherPredicateSelector(predicates)) + .mapWith(Statement::getObject) + .mapWith(object -> object.as(view)) + .nextOptional() + .orElse(null); + } + private static final class InstanceOfEitherSelector implements Selector { private final List classes; From c6ccf0d24f56d7d30db6829a682b0cd758463f89 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 22:47:43 +0200 Subject: [PATCH 033/141] Easy on the generated imports --- .../wrapping/declarative/processor/DatasetImplementor.java | 4 ++-- .../rdf/wrapping/declarative/processor/GraphImplementor.java | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java index b3ffc8f73..9440c2d5b 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java @@ -81,7 +81,7 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { private void createDefaultGraphMethods(final JClassDef myClass, final JExpr myInstance) { membersAnnotatedWithAny(DefaultGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); - sourceFile._import(returnType); + final JMethodDef myMethod = myClass .method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); @@ -94,7 +94,7 @@ private void createDefaultGraphMethods(final JClassDef myClass, final JExpr myIn private void createNamedGraphMethods(final JClassDef myClass, final JExpr myInstance) { membersAnnotatedWithAny(NamedGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); - sourceFile._import(returnType); + final JMethodDef myMethod = myClass .method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java index 2d3f91901..250c84270 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -90,7 +90,6 @@ private void addImplementationsToPersonality(final JMethodDef myConstructor, fin final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = returnTypeAsImplementation(method); - sourceFile._import(returnType); myConstructor .body() .call(myInstance.call("getPersonality"), "add") @@ -110,7 +109,6 @@ private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = returnTypeAsImplementation(method); - sourceFile._import(returnType); final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); @@ -133,7 +131,6 @@ private void createOptionalFirstSubjectOfEitherMethods(final JClassDef myClass, final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = returnTypeAsImplementation(method); - sourceFile._import(returnType); final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); @@ -156,7 +153,6 @@ private void createOptionalFirstObjectOfEitherMethods(final JClassDef myClass, f final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = returnTypeAsImplementation(method); - sourceFile._import(returnType); final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); From aa7a899f865a9e18390570bfe21e22278b2a1223 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 22:50:49 +0200 Subject: [PATCH 034/141] Only add to personality once --- .../processor/GraphImplementor.java | 14 +++++++------ .../declarative/processor/Implementor.java | 20 ++++++++++--------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java index 250c84270..d84e969fb 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -31,6 +31,7 @@ import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import org.apache.jena.graph.Graph; @@ -86,9 +87,10 @@ private void addImplementationsToPersonality(final JMethodDef myConstructor, fin OptionalFirstInstanceOfEither.class, OptionalFirstSubjectOfEither.class, OptionalFirstObjectOfEither.class) - .forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final JType implementationType = returnTypeAsImplementation(method); + .map(ExecutableElement::getReturnType) + .distinct() + .forEach(returnType -> { + final JType implementationType = asImplementation(returnType); myConstructor .body() @@ -107,7 +109,7 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, final JExpr myInstance) { membersAnnotatedWithAny(OptionalFirstInstanceOfEither.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); - final JType implementationType = returnTypeAsImplementation(method); + final JType implementationType = asImplementation(method.getReturnType()); final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); @@ -129,7 +131,7 @@ private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, private void createOptionalFirstSubjectOfEitherMethods(final JClassDef myClass, final JExpr myInstance) { membersAnnotatedWithAny(OptionalFirstSubjectOfEither.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); - final JType implementationType = returnTypeAsImplementation(method); + final JType implementationType = asImplementation(method.getReturnType()); final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); @@ -151,7 +153,7 @@ private void createOptionalFirstSubjectOfEitherMethods(final JClassDef myClass, private void createOptionalFirstObjectOfEitherMethods(final JClassDef myClass, final JExpr myInstance) { membersAnnotatedWithAny(OptionalFirstObjectOfEither.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); - final JType implementationType = returnTypeAsImplementation(method); + final JType implementationType = asImplementation(method.getReturnType()); final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java index 509267280..4c1396cc0 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java @@ -35,6 +35,7 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import org.jboss.jdeparser.*; @@ -99,6 +100,16 @@ static String asImplementation(final String original) { return original + "_$impl"; } + protected JType asImplementation(final TypeMirror original) { + final Element returnType = environment.getTypeUtils().asElement(original); + final String originalBinaryName = environment + .getElementUtils() + .getBinaryName((TypeElement) returnType) + .toString(); + + return $t(asImplementation(originalBinaryName)); + } + protected JClassDef createClass(final Class base) { final JClassDef myClass = sourceFile ._class(PUBLIC, implementationClass) @@ -122,15 +133,6 @@ protected final Stream membersAnnotatedWithAny( .anyMatch(annotation -> method.getAnnotation(annotation) != null)); } - protected JType returnTypeAsImplementation(final ExecutableElement method) { - final Element returnType = environment.getTypeUtils().asElement(method.getReturnType()); - final String originalBinaryName = environment - .getElementUtils() - .getBinaryName((TypeElement) returnType) - .toString(); - return $t(asImplementation(originalBinaryName)); - } - private void annotateAndDocumentAsGenerated(final JClassDef implementation) { implementation.docComment().text("Warning, this class consists of generated code."); From 25a8fb07afdc9a6cff37d0e3e428ff33bed8bc2a Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 20 Aug 2023 23:07:18 +0200 Subject: [PATCH 035/141] Found how to generate `this` properly --- .../processor/DatasetImplementor.java | 14 +++++----- .../processor/GraphImplementor.java | 26 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java index 9440c2d5b..a39ffb759 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.processor; +import static org.jboss.jdeparser.JExpr.THIS; import static org.jboss.jdeparser.JExprs.$v; import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; @@ -47,15 +48,14 @@ protected void implementInternal() { final JClassDef myClass = createClass(DatasetImpl.class); final JType myType = $t(myClass); - final JExpr myInstance = myType._this(); createConstructor(myClass); createWrapMethod(myClass, myType); - createDefaultGraphMethods(myClass, myInstance); + createDefaultGraphMethods(myClass); - createNamedGraphMethods(myClass, myInstance); + createNamedGraphMethods(myClass); } private void addImports() { @@ -78,7 +78,7 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { myWrap.body()._return(myType._new().arg($v(ORIGINAL).call("asDatasetGraph"))); } - private void createDefaultGraphMethods(final JClassDef myClass, final JExpr myInstance) { + private void createDefaultGraphMethods(final JClassDef myClass) { membersAnnotatedWithAny(DefaultGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); @@ -87,11 +87,11 @@ private void createDefaultGraphMethods(final JClassDef myClass, final JExpr myIn myMethod.annotate(Override.class); myMethod .body() - ._return(returnType.call(WRAP).arg(myInstance.call("getDefaultModel"))); + ._return(returnType.call(WRAP).arg(THIS.call("getDefaultModel"))); }); } - private void createNamedGraphMethods(final JClassDef myClass, final JExpr myInstance) { + private void createNamedGraphMethods(final JClassDef myClass) { membersAnnotatedWithAny(NamedGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); @@ -102,7 +102,7 @@ private void createNamedGraphMethods(final JClassDef myClass, final JExpr myInst .body() ._return(returnType .call(WRAP) - .arg(myInstance + .arg(THIS .call("getNamedModel") .arg(JExprs.str(method.getAnnotation(NamedGraph.class).value())))); }); diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java index d84e969fb..8395b4ff5 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.processor; +import static org.jboss.jdeparser.JExpr.THIS; import static org.jboss.jdeparser.JExprs.$v; import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; @@ -50,19 +51,18 @@ protected void implementInternal() { final JClassDef myClass = createClass(WrapperModel.class); final JType myType = $t(myClass); - final JExpr myInstance = myType._this(); final JMethodDef myConstructor = createConstructor(myClass); - addImplementationsToPersonality(myConstructor, myInstance); + addImplementationsToPersonality(myConstructor); createWrapMethod(myClass, myType); - createOptionalFirstInstanceOfEitherMethods(myClass, myInstance); + createOptionalFirstInstanceOfEitherMethods(myClass); - createOptionalFirstSubjectOfEitherMethods(myClass, myInstance); + createOptionalFirstSubjectOfEitherMethods(myClass); - createOptionalFirstObjectOfEitherMethods(myClass, myInstance); + createOptionalFirstObjectOfEitherMethods(myClass); } private void addImports() { @@ -82,7 +82,7 @@ private static JMethodDef createConstructor(final JClassDef myClass) { return myConstructor; } - private void addImplementationsToPersonality(final JMethodDef myConstructor, final JExpr myInstance) { + private void addImplementationsToPersonality(final JMethodDef myConstructor) { membersAnnotatedWithAny( OptionalFirstInstanceOfEither.class, OptionalFirstSubjectOfEither.class, @@ -94,7 +94,7 @@ private void addImplementationsToPersonality(final JMethodDef myConstructor, fin myConstructor .body() - .call(myInstance.call("getPersonality"), "add") + .call(THIS.call("getPersonality"), "add") .arg(implementationType._class()) .arg(implementationType.field(ResourceImplementor.FACTORY)); }); @@ -106,7 +106,7 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { myWrap.body()._return(myType._new().arg($v(ORIGINAL).call("getGraph"))); } - private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, final JExpr myInstance) { + private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass) { membersAnnotatedWithAny(OptionalFirstInstanceOfEither.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = asImplementation(method.getReturnType()); @@ -115,7 +115,7 @@ private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, myMethod.annotate(Override.class); // Call model wrapper convenience method passing projection class argument - final JCall wrapperConvenienceCall = myInstance + final JCall wrapperConvenienceCall = THIS .call("optionalFirstInstanceOfEither") .arg(implementationType._class()); @@ -128,7 +128,7 @@ private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass, }); } - private void createOptionalFirstSubjectOfEitherMethods(final JClassDef myClass, final JExpr myInstance) { + private void createOptionalFirstSubjectOfEitherMethods(final JClassDef myClass) { membersAnnotatedWithAny(OptionalFirstSubjectOfEither.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = asImplementation(method.getReturnType()); @@ -137,7 +137,7 @@ private void createOptionalFirstSubjectOfEitherMethods(final JClassDef myClass, myMethod.annotate(Override.class); // Call model wrapper convenience method passing projection class argument - final JCall wrapperConvenienceCall = myInstance + final JCall wrapperConvenienceCall = THIS .call("optionalFirstSubjectOfEither") .arg(implementationType._class()); @@ -150,7 +150,7 @@ private void createOptionalFirstSubjectOfEitherMethods(final JClassDef myClass, }); } - private void createOptionalFirstObjectOfEitherMethods(final JClassDef myClass, final JExpr myInstance) { + private void createOptionalFirstObjectOfEitherMethods(final JClassDef myClass) { membersAnnotatedWithAny(OptionalFirstObjectOfEither.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = asImplementation(method.getReturnType()); @@ -159,7 +159,7 @@ private void createOptionalFirstObjectOfEitherMethods(final JClassDef myClass, f myMethod.annotate(Override.class); // Call model wrapper convenience method passing projection class argument - final JCall wrapperConvenienceCall = myInstance + final JCall wrapperConvenienceCall = THIS .call("optionalFirstObjectOfEither") .arg(implementationType._class()); From 16b0629b33a5509b418f158d17e104fad27330d5 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 27 Aug 2023 21:34:57 +0200 Subject: [PATCH 036/141] Validation in processor --- .../processor/DatasetValidator.java | 50 +++++++ .../declarative/processor/GraphValidator.java | 55 +++++++ .../declarative/processor/Processor.java | 12 +- .../processor/ResourceValidator.java | 46 ++++++ .../processor/ValidationError.java | 56 +++++++ .../declarative/processor/Validator.java | 139 ++++++++++++++++++ 6 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetValidator.java create mode 100644 declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphValidator.java create mode 100644 declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceValidator.java create mode 100644 declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ValidationError.java create mode 100644 declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Validator.java diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetValidator.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetValidator.java new file mode 100644 index 000000000..b2d5f3276 --- /dev/null +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetValidator.java @@ -0,0 +1,50 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import com.inrupt.rdf.wrapping.declarative.annotation.DefaultGraph; +import com.inrupt.rdf.wrapping.declarative.annotation.NamedGraph; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +import org.apache.jena.query.Dataset; + +class DatasetValidator extends Validator { + DatasetValidator(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { + super(annotation, env, element); + } + + @Override + protected void validateInternal() { + requireInterface(); + + limitBaseInterfaces(Dataset.class); + + requireMemberMethods(DefaultGraph.class); + requireMemberMethods(NamedGraph.class); + + requireNonMemberMethods(DefaultGraph.class, NamedGraph.class); + + // TODO: Validate that member return type is annotated with @Graph + } +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphValidator.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphValidator.java new file mode 100644 index 000000000..b7dafb6d2 --- /dev/null +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphValidator.java @@ -0,0 +1,55 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +import org.apache.jena.rdf.model.Model; + +class GraphValidator extends Validator { + GraphValidator(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { + super(annotation, env, element); + } + + @Override + protected void validateInternal() { + requireInterface(); + + limitBaseInterfaces(Model.class); + + requireMemberMethods(OptionalFirstInstanceOfEither.class); + requireMemberMethods(OptionalFirstObjectOfEither.class); + requireMemberMethods(OptionalFirstSubjectOfEither.class); + + requireNonMemberMethods( + OptionalFirstInstanceOfEither.class, + OptionalFirstObjectOfEither.class, + OptionalFirstSubjectOfEither.class); + + // TODO: Validate that member return type is annotated with @Resource + } +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java index ae3d26334..94ef02a67 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.declarative.processor; +import java.util.ArrayList; import java.util.Set; import javax.annotation.processing.AbstractProcessor; @@ -45,12 +46,21 @@ public boolean process(final Set annotations, final Round return false; } + final ArrayList implementors = new ArrayList<>(); + final ArrayList validationErrors = new ArrayList<>(); for (final TypeElement annotation : annotations) { for (final Element annotatedElement : roundEnv.getElementsAnnotatedWith(annotation)) { - Implementor.get(annotation, processingEnv, annotatedElement).implement(); + implementors.add(Implementor.get(annotation, processingEnv, annotatedElement)); + validationErrors.addAll(Validator.get(annotation, processingEnv, annotatedElement).validate()); } } + if (validationErrors.isEmpty()) { + implementors.forEach(Implementor::implement); + } else { + validationErrors.forEach(error -> error.printMessage(processingEnv.getMessager())); + } + return true; } } diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceValidator.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceValidator.java new file mode 100644 index 000000000..18b36911f --- /dev/null +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceValidator.java @@ -0,0 +1,46 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import com.inrupt.rdf.wrapping.declarative.annotation.Property; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +import org.apache.jena.rdf.model.Resource; + +class ResourceValidator extends Validator { + ResourceValidator(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { + super(annotation, env, element); + } + + @Override + protected void validateInternal() { + requireInterface(); + + limitBaseInterfaces(Resource.class); + + requireMemberMethods(Property.class); + + requireNonMemberMethods(Property.class); + } +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ValidationError.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ValidationError.java new file mode 100644 index 000000000..1a712fa40 --- /dev/null +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ValidationError.java @@ -0,0 +1,56 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import javax.annotation.processing.Messager; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.tools.Diagnostic; + +class ValidationError { + private final Element element; + private final AnnotationMirror annotation; + private final String msg; + + ValidationError(final Element element, final AnnotationMirror annotation, final String msg, final Object... args) { + this.element = element; + this.annotation = annotation; + this.msg = String.format(msg, args); + } + + ValidationError(final Element element, final String msg, final Object... args) { + this(element, null, msg, args); + } + + void printMessage(final Messager messager) { + if (element == null) { + messager.printMessage(Diagnostic.Kind.ERROR, msg); + return; + } + + if (annotation == null) { + messager.printMessage(Diagnostic.Kind.ERROR, msg, element); + return; + } + + messager.printMessage(Diagnostic.Kind.ERROR, msg, element, annotation); + } +} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Validator.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Validator.java new file mode 100644 index 000000000..9def55fdf --- /dev/null +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Validator.java @@ -0,0 +1,139 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.function.Predicate; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; + +abstract class Validator { + protected final TypeElement annotation; + protected final ProcessingEnvironment env; + protected final Element element; + protected final Collection errors = new ArrayList<>(); + + protected Validator(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { + this.annotation = annotation; + this.env = env; + this.element = element; + } + + static Validator get(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { + switch (annotation.getQualifiedName().toString()) { + case "com.inrupt.rdf.wrapping.declarative.annotation.Dataset": + return new DatasetValidator(annotation, env, element); + case "com.inrupt.rdf.wrapping.declarative.annotation.Graph": + return new GraphValidator(annotation, env, element); + case "com.inrupt.rdf.wrapping.declarative.annotation.Resource": + return new ResourceValidator(annotation, env, element); + default: + throw new RuntimeException("unknown annotation type"); + } + } + + Collection validate() { + validateInternal(); + + return errors; + } + + protected abstract void validateInternal(); + + protected void requireMemberMethods(final Class annotation) { + final Predicate isNotMember = method -> + method.isDefault() || method.getModifiers().contains(Modifier.STATIC); + + final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; + + ElementFilter.methodsIn(element.getEnclosedElements()).stream() + .filter(isNotMember) + .filter(isAnnotated) + .forEach(method -> errors.add(new ValidationError( + method, + "Method %s on interface %s annotated with @%s cannot be static or default", + method.getSimpleName(), + element.getSimpleName(), + annotation.getSimpleName()))); + } + + @SafeVarargs + protected final void requireNonMemberMethods(final Class... annotations) { + final Predicate isMember = method -> + !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC); + + final Predicate isUnannotated = method -> + Arrays.stream(annotations).noneMatch(a -> method.getAnnotation(a) != null); + + ElementFilter.methodsIn(element.getEnclosedElements()).stream() + .filter(isMember) + .filter(isUnannotated) + .forEach(method -> errors.add(new ValidationError( + method, + "Unannotated method %s on interface %s must be static or default", + method.getSimpleName(), + element.getSimpleName()))); + } + + protected void limitBaseInterfaces(final Class clazz) { + if (!element.getKind().isInterface()) { + return; + } + + final TypeElement type = (TypeElement) element; + final TypeMirror allowed = env.getElementUtils().getTypeElement(clazz.getName()).asType(); + + for (final TypeMirror implemented : type.getInterfaces()) { + if (env.getTypeUtils().isSameType(implemented, allowed)) { + continue; + } + + errors.add(new ValidationError( + element, + "Interface %s annotated with @%s can only extend %s or nothing", + element.getSimpleName(), + annotation.getSimpleName(), + clazz.getName())); + } + } + + protected void requireInterface() { + if (element.getKind().isInterface()) { + return; + } + + errors.add(new ValidationError( + element, + "Element %s annotated with @%s must be an interface but was a %s", + element.getSimpleName(), + annotation.getSimpleName(), + element.getKind())); + } +} From 76f6c2e4dc3e8a1e77ec80f9035e7c79f4740f83 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Mon, 28 Aug 2023 14:12:49 +0200 Subject: [PATCH 037/141] Use implementation not interface to generate dataset methods --- .../wrapping/declarative/processor/DatasetImplementor.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java index a39ffb759..838c0713b 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java +++ b/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java @@ -81,26 +81,28 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { private void createDefaultGraphMethods(final JClassDef myClass) { membersAnnotatedWithAny(DefaultGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); + final JType implementationType = asImplementation(method.getReturnType()); final JMethodDef myMethod = myClass .method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); myMethod .body() - ._return(returnType.call(WRAP).arg(THIS.call("getDefaultModel"))); + ._return(implementationType.call(WRAP).arg(THIS.call("getDefaultModel"))); }); } private void createNamedGraphMethods(final JClassDef myClass) { membersAnnotatedWithAny(NamedGraph.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); + final JType implementationType = asImplementation(method.getReturnType()); final JMethodDef myMethod = myClass .method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); myMethod .body() - ._return(returnType + ._return(implementationType .call(WRAP) .arg(THIS .call("getNamedModel") From 974c7191ba6967a1e814188f7035d70f0761e8f6 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Mon, 28 Aug 2023 14:19:43 +0200 Subject: [PATCH 038/141] Test compile-time validation of declarative wrapping --- declarative/processor/pom.xml | 10 ++ .../declarative/processor/ValidatorTest.java | 126 ++++++++++++++++++ ...taset default graph method is default.java | 12 ++ ...ataset default graph method is static.java | 12 ++ .../bad/dataset extends unacceptable.java | 7 + ...aset instance method is not annotated.java | 8 ++ .../bad/dataset is not an interface.java | 7 + ...dataset named graph method is default.java | 12 ++ .../dataset named graph method is static.java | 12 ++ .../bad/graph extends unacceptable.java | 7 + ...raph instance method is not annotated.java | 8 ++ .../graph instance of method is default.java | 12 ++ .../graph instance of method is static.java | 12 ++ .../bad/graph is not an interface.java | 7 + .../graph object of method is default.java | 12 ++ .../bad/graph object of method is static.java | 12 ++ .../graph subject of method is default.java | 12 ++ .../graph subject of method is static.java | 12 ++ .../bad/resource extends unacceptable.java | 7 + ...urce instance method is not annotated.java | 8 ++ .../bad/resource is not an interface.java | 7 + .../resource property method is default.java | 12 ++ .../resource property method is static.java | 12 ++ ...aset default graph method is instance.java | 15 +++ .../good/dataset extends Dataset.java | 7 + .../good/dataset extends nothing.java | 7 + ...ataset named graph method is instance.java | 15 +++ ...dataset unannotated method is default.java | 10 ++ .../dataset unannotated method is static.java | 10 ++ .../resources/good/graph extends Model.java | 7 + .../resources/good/graph extends nothing.java | 7 + .../graph instance of method is instance.java | 15 +++ .../graph object of method is instance.java | 15 +++ .../graph subject of method is instance.java | 15 +++ .../graph unannotated method is default.java | 10 ++ .../graph unannotated method is static.java | 10 ++ .../good/resource extends Resource.java | 7 + .../good/resource extends nothing.java | 7 + ...esource unannotated method is default.java | 10 ++ ...resource unannotated method is static.java | 10 ++ pom.xml | 6 + 41 files changed, 529 insertions(+) create mode 100644 declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/ValidatorTest.java create mode 100644 declarative/processor/src/test/resources/bad/dataset default graph method is default.java create mode 100644 declarative/processor/src/test/resources/bad/dataset default graph method is static.java create mode 100644 declarative/processor/src/test/resources/bad/dataset extends unacceptable.java create mode 100644 declarative/processor/src/test/resources/bad/dataset instance method is not annotated.java create mode 100644 declarative/processor/src/test/resources/bad/dataset is not an interface.java create mode 100644 declarative/processor/src/test/resources/bad/dataset named graph method is default.java create mode 100644 declarative/processor/src/test/resources/bad/dataset named graph method is static.java create mode 100644 declarative/processor/src/test/resources/bad/graph extends unacceptable.java create mode 100644 declarative/processor/src/test/resources/bad/graph instance method is not annotated.java create mode 100644 declarative/processor/src/test/resources/bad/graph instance of method is default.java create mode 100644 declarative/processor/src/test/resources/bad/graph instance of method is static.java create mode 100644 declarative/processor/src/test/resources/bad/graph is not an interface.java create mode 100644 declarative/processor/src/test/resources/bad/graph object of method is default.java create mode 100644 declarative/processor/src/test/resources/bad/graph object of method is static.java create mode 100644 declarative/processor/src/test/resources/bad/graph subject of method is default.java create mode 100644 declarative/processor/src/test/resources/bad/graph subject of method is static.java create mode 100644 declarative/processor/src/test/resources/bad/resource extends unacceptable.java create mode 100644 declarative/processor/src/test/resources/bad/resource instance method is not annotated.java create mode 100644 declarative/processor/src/test/resources/bad/resource is not an interface.java create mode 100644 declarative/processor/src/test/resources/bad/resource property method is default.java create mode 100644 declarative/processor/src/test/resources/bad/resource property method is static.java create mode 100644 declarative/processor/src/test/resources/good/dataset default graph method is instance.java create mode 100644 declarative/processor/src/test/resources/good/dataset extends Dataset.java create mode 100644 declarative/processor/src/test/resources/good/dataset extends nothing.java create mode 100644 declarative/processor/src/test/resources/good/dataset named graph method is instance.java create mode 100644 declarative/processor/src/test/resources/good/dataset unannotated method is default.java create mode 100644 declarative/processor/src/test/resources/good/dataset unannotated method is static.java create mode 100644 declarative/processor/src/test/resources/good/graph extends Model.java create mode 100644 declarative/processor/src/test/resources/good/graph extends nothing.java create mode 100644 declarative/processor/src/test/resources/good/graph instance of method is instance.java create mode 100644 declarative/processor/src/test/resources/good/graph object of method is instance.java create mode 100644 declarative/processor/src/test/resources/good/graph subject of method is instance.java create mode 100644 declarative/processor/src/test/resources/good/graph unannotated method is default.java create mode 100644 declarative/processor/src/test/resources/good/graph unannotated method is static.java create mode 100644 declarative/processor/src/test/resources/good/resource extends Resource.java create mode 100644 declarative/processor/src/test/resources/good/resource extends nothing.java create mode 100644 declarative/processor/src/test/resources/good/resource unannotated method is default.java create mode 100644 declarative/processor/src/test/resources/good/resource unannotated method is static.java diff --git a/declarative/processor/pom.xml b/declarative/processor/pom.xml index 42e17699d..1de296607 100644 --- a/declarative/processor/pom.xml +++ b/declarative/processor/pom.xml @@ -43,6 +43,16 @@ junit-jupiter-api test + + org.junit.jupiter + junit-jupiter-params + test + + + com.google.testing.compile + compile-testing + test + diff --git a/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/ValidatorTest.java b/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/ValidatorTest.java new file mode 100644 index 000000000..fd1231663 --- /dev/null +++ b/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/ValidatorTest.java @@ -0,0 +1,126 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.declarative.processor; + +import static com.google.testing.compile.CompilationSubject.assertThat; +import static com.google.testing.compile.JavaFileObjects.forResource; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import com.google.testing.compile.Compilation; +import com.google.testing.compile.Compiler; + +import java.util.stream.Stream; + +import javax.tools.JavaFileObject; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +@DisplayName("Compile-time validation") +class ValidatorTest { + private static final String MUST_BE_AN_INTERFACE = "must be an interface"; + private static final String CANNOT_BE_STATIC_OR_DEFAULT = "cannot be static or default"; + private static final String MUST_BE_STATIC_OR_DEFAULT = "must be static or default"; + + private Compiler compiler; + + @BeforeEach + void init() { + compiler = Compiler.javac().withProcessors(new Processor()); + } + + @DisplayName("produces error containing") + @ParameterizedTest(name = "[{1}] when {0}") + @MethodSource + void compilationErrorOnInvalid(final String name, final String error) { + final JavaFileObject file = forResource("bad/" + name + ".java"); + final Compilation compilation = compiler.compile(file); + + assertThat(compilation).hadErrorContaining(error).inFile(file); + } + + private static Stream compilationErrorOnInvalid() { + return Stream.of( + arguments("dataset is not an interface", MUST_BE_AN_INTERFACE), + arguments("dataset extends unacceptable", "can only extend org.apache.jena.query.Dataset"), + arguments("dataset default graph method is static", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("dataset default graph method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("dataset named graph method is static", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("dataset named graph method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("dataset instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), + + arguments("graph is not an interface", MUST_BE_AN_INTERFACE), + arguments("graph extends unacceptable", "can only extend org.apache.jena.rdf.model.Model"), + arguments("graph instance of method is static", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph instance of method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph object of method is static", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph object of method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph subject of method is static", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph subject of method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), + + arguments("resource is not an interface", MUST_BE_AN_INTERFACE), + arguments("resource extends unacceptable", "can only extend org.apache.jena.rdf.model.Resource"), + arguments("resource property method is static", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("resource property method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("resource instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT) + ); + } + + @DisplayName("succeeds when") + @ParameterizedTest(name = "{0}") + @MethodSource + void compilationSucceeds(final String name) { + final JavaFileObject file = forResource("good/" + name + ".java"); + final Compilation compilation = compiler.compile(file); + + assertThat(compilation).succeeded(); + } + + private static Stream compilationSucceeds() { + return Stream.of( + arguments("dataset extends nothing"), + arguments("dataset extends Dataset"), + arguments("dataset default graph method is instance"), + arguments("dataset named graph method is instance"), + arguments("dataset unannotated method is static"), + arguments("dataset unannotated method is default"), + + arguments("graph extends nothing"), + arguments("graph extends Model"), + arguments("graph instance of method is instance"), + arguments("graph subject of method is instance"), + arguments("graph object of method is instance"), + arguments("graph unannotated method is static"), + arguments("graph unannotated method is default"), + + arguments("resource extends nothing"), + arguments("resource extends Resource"), + // arguments("resource property method is instance"), + arguments("resource unannotated method is static"), + arguments("resource unannotated method is default") + + ); + } +} diff --git a/declarative/processor/src/test/resources/bad/dataset default graph method is default.java b/declarative/processor/src/test/resources/bad/dataset default graph method is default.java new file mode 100644 index 000000000..ba49653c6 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/dataset default graph method is default.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; +import com.inrupt.rdf.wrapping.declarative.annotation.DefaultGraph; + +@Dataset +interface X { + @DefaultGraph + default Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/dataset default graph method is static.java b/declarative/processor/src/test/resources/bad/dataset default graph method is static.java new file mode 100644 index 000000000..994179ee0 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/dataset default graph method is static.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; +import com.inrupt.rdf.wrapping.declarative.annotation.DefaultGraph; + +@Dataset +interface X { + @DefaultGraph + static Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/dataset extends unacceptable.java b/declarative/processor/src/test/resources/bad/dataset extends unacceptable.java new file mode 100644 index 000000000..8ec63b2ef --- /dev/null +++ b/declarative/processor/src/test/resources/bad/dataset extends unacceptable.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; + +@Dataset +interface X extends Comparable { +} diff --git a/declarative/processor/src/test/resources/bad/dataset instance method is not annotated.java b/declarative/processor/src/test/resources/bad/dataset instance method is not annotated.java new file mode 100644 index 000000000..1e1f2ff2f --- /dev/null +++ b/declarative/processor/src/test/resources/bad/dataset instance method is not annotated.java @@ -0,0 +1,8 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; + +@Dataset +interface X { + Object x(); +} diff --git a/declarative/processor/src/test/resources/bad/dataset is not an interface.java b/declarative/processor/src/test/resources/bad/dataset is not an interface.java new file mode 100644 index 000000000..7db3930b6 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/dataset is not an interface.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; + +@Dataset +class X { +} diff --git a/declarative/processor/src/test/resources/bad/dataset named graph method is default.java b/declarative/processor/src/test/resources/bad/dataset named graph method is default.java new file mode 100644 index 000000000..248f81204 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/dataset named graph method is default.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; +import com.inrupt.rdf.wrapping.declarative.annotation.NamedGraph; + +@Dataset +interface X { + @NamedGraph("x") + default Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/dataset named graph method is static.java b/declarative/processor/src/test/resources/bad/dataset named graph method is static.java new file mode 100644 index 000000000..d6ac902a7 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/dataset named graph method is static.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; +import com.inrupt.rdf.wrapping.declarative.annotation.NamedGraph; + +@Dataset +interface X { + @NamedGraph("x") + static Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/graph extends unacceptable.java b/declarative/processor/src/test/resources/bad/graph extends unacceptable.java new file mode 100644 index 000000000..46af15af5 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/graph extends unacceptable.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; + +@Graph +interface X extends Comparable { +} diff --git a/declarative/processor/src/test/resources/bad/graph instance method is not annotated.java b/declarative/processor/src/test/resources/bad/graph instance method is not annotated.java new file mode 100644 index 000000000..cee38a511 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/graph instance method is not annotated.java @@ -0,0 +1,8 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; + +@Graph +interface X { + Object x(); +} diff --git a/declarative/processor/src/test/resources/bad/graph instance of method is default.java b/declarative/processor/src/test/resources/bad/graph instance of method is default.java new file mode 100644 index 000000000..3c1a8e833 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/graph instance of method is default.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; + +@Graph +interface X { + @OptionalFirstInstanceOfEither("x") + default Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/graph instance of method is static.java b/declarative/processor/src/test/resources/bad/graph instance of method is static.java new file mode 100644 index 000000000..a7a7ac42b --- /dev/null +++ b/declarative/processor/src/test/resources/bad/graph instance of method is static.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; + +@Graph +interface X { + @OptionalFirstInstanceOfEither("x") + static Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/graph is not an interface.java b/declarative/processor/src/test/resources/bad/graph is not an interface.java new file mode 100644 index 000000000..937f396db --- /dev/null +++ b/declarative/processor/src/test/resources/bad/graph is not an interface.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; + +@Graph +class X { +} diff --git a/declarative/processor/src/test/resources/bad/graph object of method is default.java b/declarative/processor/src/test/resources/bad/graph object of method is default.java new file mode 100644 index 000000000..f10cc8417 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/graph object of method is default.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstObjectOfEither; + +@Graph +interface X { + @OptionalFirstObjectOfEither("x") + default Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/graph object of method is static.java b/declarative/processor/src/test/resources/bad/graph object of method is static.java new file mode 100644 index 000000000..febf6e39f --- /dev/null +++ b/declarative/processor/src/test/resources/bad/graph object of method is static.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstObjectOfEither; + +@Graph +interface X { + @OptionalFirstObjectOfEither("x") + static Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/graph subject of method is default.java b/declarative/processor/src/test/resources/bad/graph subject of method is default.java new file mode 100644 index 000000000..77da7d339 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/graph subject of method is default.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; + +@Graph +interface X { + @OptionalFirstSubjectOfEither("x") + default Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/graph subject of method is static.java b/declarative/processor/src/test/resources/bad/graph subject of method is static.java new file mode 100644 index 000000000..1dda00476 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/graph subject of method is static.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; + +@Graph +interface X { + @OptionalFirstSubjectOfEither("x") + static Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/resource extends unacceptable.java b/declarative/processor/src/test/resources/bad/resource extends unacceptable.java new file mode 100644 index 000000000..dcc95023e --- /dev/null +++ b/declarative/processor/src/test/resources/bad/resource extends unacceptable.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Resource +interface X extends Comparable { +} diff --git a/declarative/processor/src/test/resources/bad/resource instance method is not annotated.java b/declarative/processor/src/test/resources/bad/resource instance method is not annotated.java new file mode 100644 index 000000000..3a7f4ff88 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/resource instance method is not annotated.java @@ -0,0 +1,8 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Resource +interface X { + Object x(); +} diff --git a/declarative/processor/src/test/resources/bad/resource is not an interface.java b/declarative/processor/src/test/resources/bad/resource is not an interface.java new file mode 100644 index 000000000..d20a92715 --- /dev/null +++ b/declarative/processor/src/test/resources/bad/resource is not an interface.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Resource +class X { +} diff --git a/declarative/processor/src/test/resources/bad/resource property method is default.java b/declarative/processor/src/test/resources/bad/resource property method is default.java new file mode 100644 index 000000000..5fd82296d --- /dev/null +++ b/declarative/processor/src/test/resources/bad/resource property method is default.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Property; +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Resource +interface X { + @Property + default Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/bad/resource property method is static.java b/declarative/processor/src/test/resources/bad/resource property method is static.java new file mode 100644 index 000000000..5fd82296d --- /dev/null +++ b/declarative/processor/src/test/resources/bad/resource property method is static.java @@ -0,0 +1,12 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Property; +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Resource +interface X { + @Property + default Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/good/dataset default graph method is instance.java b/declarative/processor/src/test/resources/good/dataset default graph method is instance.java new file mode 100644 index 000000000..2914666b6 --- /dev/null +++ b/declarative/processor/src/test/resources/good/dataset default graph method is instance.java @@ -0,0 +1,15 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; +import com.inrupt.rdf.wrapping.declarative.annotation.DefaultGraph; +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; + +@Dataset +interface X { + @DefaultGraph + Y x(); + + @Graph + interface Y { + } +} diff --git a/declarative/processor/src/test/resources/good/dataset extends Dataset.java b/declarative/processor/src/test/resources/good/dataset extends Dataset.java new file mode 100644 index 000000000..8dce4683c --- /dev/null +++ b/declarative/processor/src/test/resources/good/dataset extends Dataset.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; + +@Dataset +interface X extends org.apache.jena.query.Dataset { +} diff --git a/declarative/processor/src/test/resources/good/dataset extends nothing.java b/declarative/processor/src/test/resources/good/dataset extends nothing.java new file mode 100644 index 000000000..7126e04c9 --- /dev/null +++ b/declarative/processor/src/test/resources/good/dataset extends nothing.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; + +@Dataset +interface X { +} diff --git a/declarative/processor/src/test/resources/good/dataset named graph method is instance.java b/declarative/processor/src/test/resources/good/dataset named graph method is instance.java new file mode 100644 index 000000000..6b94fc98f --- /dev/null +++ b/declarative/processor/src/test/resources/good/dataset named graph method is instance.java @@ -0,0 +1,15 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.NamedGraph; + +@Dataset +interface X { + @NamedGraph("x") + Y x(); + + @Graph + interface Y { + } +} diff --git a/declarative/processor/src/test/resources/good/dataset unannotated method is default.java b/declarative/processor/src/test/resources/good/dataset unannotated method is default.java new file mode 100644 index 000000000..3ad3e68ae --- /dev/null +++ b/declarative/processor/src/test/resources/good/dataset unannotated method is default.java @@ -0,0 +1,10 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; + +@Dataset +interface X { + default Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/good/dataset unannotated method is static.java b/declarative/processor/src/test/resources/good/dataset unannotated method is static.java new file mode 100644 index 000000000..c89fe7ce5 --- /dev/null +++ b/declarative/processor/src/test/resources/good/dataset unannotated method is static.java @@ -0,0 +1,10 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; + +@Dataset +interface X { + static Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/good/graph extends Model.java b/declarative/processor/src/test/resources/good/graph extends Model.java new file mode 100644 index 000000000..6be7f94cb --- /dev/null +++ b/declarative/processor/src/test/resources/good/graph extends Model.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; + +@Graph +interface X extends org.apache.jena.rdf.model.Model { +} diff --git a/declarative/processor/src/test/resources/good/graph extends nothing.java b/declarative/processor/src/test/resources/good/graph extends nothing.java new file mode 100644 index 000000000..018fa6760 --- /dev/null +++ b/declarative/processor/src/test/resources/good/graph extends nothing.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; + +@Graph +interface X { +} diff --git a/declarative/processor/src/test/resources/good/graph instance of method is instance.java b/declarative/processor/src/test/resources/good/graph instance of method is instance.java new file mode 100644 index 000000000..0653cffe0 --- /dev/null +++ b/declarative/processor/src/test/resources/good/graph instance of method is instance.java @@ -0,0 +1,15 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Graph +interface X { + @OptionalFirstInstanceOfEither("x") + Y x(); + + @Resource + interface Y { + } +} diff --git a/declarative/processor/src/test/resources/good/graph object of method is instance.java b/declarative/processor/src/test/resources/good/graph object of method is instance.java new file mode 100644 index 000000000..b9d2323b4 --- /dev/null +++ b/declarative/processor/src/test/resources/good/graph object of method is instance.java @@ -0,0 +1,15 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Graph +interface X { + @OptionalFirstObjectOfEither("x") + Y x(); + + @Resource + interface Y { + } +} diff --git a/declarative/processor/src/test/resources/good/graph subject of method is instance.java b/declarative/processor/src/test/resources/good/graph subject of method is instance.java new file mode 100644 index 000000000..672f98b72 --- /dev/null +++ b/declarative/processor/src/test/resources/good/graph subject of method is instance.java @@ -0,0 +1,15 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Graph +interface X { + @OptionalFirstSubjectOfEither("x") + Y x(); + + @Resource + interface Y { + } +} diff --git a/declarative/processor/src/test/resources/good/graph unannotated method is default.java b/declarative/processor/src/test/resources/good/graph unannotated method is default.java new file mode 100644 index 000000000..707e05b06 --- /dev/null +++ b/declarative/processor/src/test/resources/good/graph unannotated method is default.java @@ -0,0 +1,10 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; + +@Graph +interface X { + default Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/good/graph unannotated method is static.java b/declarative/processor/src/test/resources/good/graph unannotated method is static.java new file mode 100644 index 000000000..82a43cbe1 --- /dev/null +++ b/declarative/processor/src/test/resources/good/graph unannotated method is static.java @@ -0,0 +1,10 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Graph; + +@Graph +interface X { + static Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/good/resource extends Resource.java b/declarative/processor/src/test/resources/good/resource extends Resource.java new file mode 100644 index 000000000..a36b8eae5 --- /dev/null +++ b/declarative/processor/src/test/resources/good/resource extends Resource.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Resource +interface X extends org.apache.jena.rdf.model.Resource { +} diff --git a/declarative/processor/src/test/resources/good/resource extends nothing.java b/declarative/processor/src/test/resources/good/resource extends nothing.java new file mode 100644 index 000000000..778ffc722 --- /dev/null +++ b/declarative/processor/src/test/resources/good/resource extends nothing.java @@ -0,0 +1,7 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Resource +interface X { +} diff --git a/declarative/processor/src/test/resources/good/resource unannotated method is default.java b/declarative/processor/src/test/resources/good/resource unannotated method is default.java new file mode 100644 index 000000000..ca1fdc834 --- /dev/null +++ b/declarative/processor/src/test/resources/good/resource unannotated method is default.java @@ -0,0 +1,10 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Resource +interface X { + default Object x() { + return null; + } +} diff --git a/declarative/processor/src/test/resources/good/resource unannotated method is static.java b/declarative/processor/src/test/resources/good/resource unannotated method is static.java new file mode 100644 index 000000000..6f8f37afe --- /dev/null +++ b/declarative/processor/src/test/resources/good/resource unannotated method is static.java @@ -0,0 +1,10 @@ +package x; + +import com.inrupt.rdf.wrapping.declarative.annotation.Resource; + +@Resource +interface X { + static Object x() { + return null; + } +} diff --git a/pom.xml b/pom.xml index 9ef30eae6..0c8bc6508 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,7 @@ 2.0.7 2.2 5.4.0 + 0.21.0 ${maven.multiModuleProjectDirectory}/reports/target/site/jacoco-merged/jacoco.xml @@ -129,6 +130,11 @@ jdeparser ${jdeparser.version} + + com.google.testing.compile + compile-testing + ${compile-testing.version} + From 0c7bacd723d39a8d80e617fada3215791b9f4374 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Mon, 28 Aug 2023 14:40:09 +0200 Subject: [PATCH 039/141] Remove template module --- declarative/pom.xml | 1 - declarative/template/pom.xml | 69 ------------------- .../declarative/template/ExampleDataset.java | 37 ---------- .../template/ExampleDataset_$impl.java | 57 --------------- .../declarative/template/ExampleGraph.java | 36 ---------- .../template/ExampleGraph_$impl.java | 56 --------------- .../template/ExampleI1$ExampleI2_$impl.java | 47 ------------- .../declarative/template/ExampleI1.java | 34 --------- .../declarative/template/ExampleNode1.java | 29 -------- .../template/ExampleNode1_$impl.java | 52 -------------- .../declarative/template/ExampleNode2.java | 32 --------- .../template/ExampleNode2_$impl.java | 52 -------------- .../declarative/template/package-info.java | 25 ------- .../template/ExampleGraphTest.java | 64 ----------------- 14 files changed, 591 deletions(-) delete mode 100644 declarative/template/pom.xml delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java delete mode 100644 declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java delete mode 100644 declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java diff --git a/declarative/pom.xml b/declarative/pom.xml index dfe1fe523..3903ad0df 100644 --- a/declarative/pom.xml +++ b/declarative/pom.xml @@ -15,7 +15,6 @@ annotation processor test - template diff --git a/declarative/template/pom.xml b/declarative/template/pom.xml deleted file mode 100644 index 12a6178de..000000000 --- a/declarative/template/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - 4.0.0 - - com.inrupt.rdf - inrupt-rdf-wrapping-declarative - 1.0.1-SNAPSHOT - - - inrupt-rdf-wrapping-declarative-template - Inrupt RDF Wrapping Declarative - Template - - Examples of wrapper interfaces and the implementations the Processor should generate from them - - - - 1.8 - 1.8 - - - - - com.inrupt.rdf - inrupt-rdf-wrapping-jena - ${project.version} - - - com.inrupt.rdf - inrupt-rdf-wrapping-declarative-processor - ${project.version} - - - - org.junit.jupiter - junit-jupiter - test - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - default-compile - compile - - compile - - - -proc:none - - - - - - - diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java deleted file mode 100644 index a074f05cf..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; -import com.inrupt.rdf.wrapping.declarative.processor.Manager; - -@Dataset -public interface ExampleDataset { - static ExampleDataset wrap(final org.apache.jena.query.Dataset original) { - return Manager.wrap(original, ExampleDataset.class); - } - - // @DefaultGraph - ExampleGraph getGraph(); - - // @NamedGraph("urn:example:g1") - ExampleGraph getNamedGraph(); -} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java deleted file mode 100644 index c5e4a5c72..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleDataset_$impl.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import javax.annotation.Generated; - -import org.apache.jena.query.Dataset; -import org.apache.jena.sparql.core.DatasetGraph; -import org.apache.jena.sparql.core.DatasetGraphFactory; -import org.apache.jena.sparql.core.DatasetImpl; - -/** - * Warning this class consists of generated code. - */ -@Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") -public class ExampleDataset_$impl extends DatasetImpl implements ExampleDataset { - - protected ExampleDataset_$impl(final DatasetGraph original) { - super(original); - } - - public static ExampleDataset wrap(final Dataset original) { - return new ExampleDataset_$impl(original.asDatasetGraph()); - } - - public static ExampleDataset create() { - return new ExampleDataset_$impl(DatasetGraphFactory.create()); - } - - @Override - public ExampleGraph getGraph() { - return ExampleGraph.wrap(getDefaultModel()); - } - - @Override - public ExampleGraph getNamedGraph() { - return ExampleGraph.wrap(getNamedModel("urn:example:g1")); - } -} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java deleted file mode 100644 index 224489fc8..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.processor.Manager; - -import org.apache.jena.rdf.model.Model; - -@Graph -public interface ExampleGraph { - static ExampleGraph wrap(final Model original) { - return Manager.wrap(original, ExampleGraph.class); - } - - // @FirstInstanceOf("urn:example:C") - ExampleNode1 getResource(); -} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java deleted file mode 100644 index 5a76a56d1..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraph_$impl.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import com.inrupt.rdf.wrapping.jena.WrapperModel; - -import javax.annotation.Generated; - -import org.apache.jena.graph.Graph; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.sparql.graph.GraphFactory; - -/** - * Warning this class consists of generated code. - */ -@Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") -public class ExampleGraph_$impl extends WrapperModel implements ExampleGraph { - protected ExampleGraph_$impl(final Graph base) { - super(base); - - getPersonality() - .add(ExampleNode1_$impl.class, ExampleNode1_$impl.factory) - .add(ExampleNode2_$impl.class, ExampleNode2_$impl.factory); - } - - public static ExampleGraph wrap(final Model original) { - return new ExampleGraph_$impl(original.getGraph()); - } - - public static ExampleGraph create() { - return new ExampleGraph_$impl(GraphFactory.createDefaultGraph()); - } - - @Override - public ExampleNode1 getResource() { - return optionalFirstInstanceOfEither(ExampleNode1_$impl.class, "urn:example:C"); - } -} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java deleted file mode 100644 index 4794e6a9a..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1$ExampleI2_$impl.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import javax.annotation.Generated; - -import org.apache.jena.query.Dataset; -import org.apache.jena.sparql.core.DatasetGraph; -import org.apache.jena.sparql.core.DatasetGraphFactory; -import org.apache.jena.sparql.core.DatasetImpl; - -/** - * Warning this class consists of generated code. - */ -@Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") -public class ExampleI1$ExampleI2_$impl extends DatasetImpl implements ExampleI1.ExampleI2 { - - protected ExampleI1$ExampleI2_$impl(final DatasetGraph original) { - super(original); - } - - public static ExampleI1.ExampleI2 wrap(final Dataset original) { - return new ExampleI1$ExampleI2_$impl(original.asDatasetGraph()); - } - - public static ExampleI1.ExampleI2 create() { - return new ExampleI1$ExampleI2_$impl(DatasetGraphFactory.create()); - } -} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java deleted file mode 100644 index 22317af2b..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleI1.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import com.inrupt.rdf.wrapping.declarative.processor.Manager; - -import org.apache.jena.query.Dataset; - -public interface ExampleI1 { - interface ExampleI2 { - static ExampleI2 wrap(final Dataset original) { - return Manager.wrap(original, ExampleI2.class); - } - - } -} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java deleted file mode 100644 index d4b949235..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Resource -public interface ExampleNode1 { - // @Property(predicate = "urn:example:p1", type = PropertyMappingTypes.anyOrNull, mapping = ValueMappingTypes.as) - ExampleNode2 getP1(); -} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java deleted file mode 100644 index d7e7badd3..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode1_$impl.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import static org.apache.jena.rdf.model.ResourceFactory.createProperty; - -import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; -import com.inrupt.rdf.wrapping.jena.ValueMappings; -import com.inrupt.rdf.wrapping.jena.WrapperResource; - -import javax.annotation.Generated; - -import org.apache.jena.enhanced.EnhGraph; -import org.apache.jena.enhanced.Implementation; -import org.apache.jena.graph.Node; - -/** - * Warning this class consists of generated code. - */ -@Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") -public class ExampleNode1_$impl extends WrapperResource implements ExampleNode1 { - static final Implementation factory = new UriOrBlankFactory(ExampleNode1_$impl::new); - - protected ExampleNode1_$impl(final Node node, final EnhGraph model) { - super(node, model); - } - - @Override - public ExampleNode2 getP1() { - return anyOrNull( - createProperty("urn:example:p1"), - ValueMappings.as(ExampleNode2_$impl.class)); - } -} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java deleted file mode 100644 index 397582f17..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Resource -public interface ExampleNode2 { - // @Property( - // predicate = "urn:example:p2", - // type = PropertyMappingTypes.anyOrNull, - // mapping = ValueMappingTypes.literalAsString) - String getP2(); -} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java deleted file mode 100644 index e10e2c82e..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/ExampleNode2_$impl.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import static org.apache.jena.rdf.model.ResourceFactory.createProperty; - -import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; -import com.inrupt.rdf.wrapping.jena.ValueMappings; -import com.inrupt.rdf.wrapping.jena.WrapperResource; - -import javax.annotation.Generated; - -import org.apache.jena.enhanced.EnhGraph; -import org.apache.jena.enhanced.Implementation; -import org.apache.jena.graph.Node; - -/** - * Warning this class consists of generated code. - */ -@Generated(value = "TODO: FQCN of generator", date = "TODO: Generation date") -public class ExampleNode2_$impl extends WrapperResource implements ExampleNode2 { - static final Implementation factory = new UriOrBlankFactory(ExampleNode2_$impl::new); - - protected ExampleNode2_$impl(final Node node, final EnhGraph model) { - super(node, model); - } - - @Override - public String getP2() { - return anyOrNull( - createProperty("urn:example:p2"), - ValueMappings::literalAsString); - } -} diff --git a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java b/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java deleted file mode 100644 index b70d996e4..000000000 --- a/declarative/template/src/main/java/com/inrupt/rdf/wrapping/declarative/template/package-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * Examples of wrapper interfaces and the implementations the Processor should generate from them. - */ -package com.inrupt.rdf.wrapping.declarative.template; diff --git a/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java b/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java deleted file mode 100644 index 18780ef83..000000000 --- a/declarative/template/src/test/java/com/inrupt/rdf/wrapping/declarative/template/ExampleGraphTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.declarative.template; - -import com.github.jsonldjava.shaded.com.google.common.base.Charsets; - -import org.apache.commons.io.IOUtils; -import org.apache.jena.query.Dataset; -import org.apache.jena.query.DatasetFactory; -import org.apache.jena.riot.Lang; -import org.apache.jena.riot.RDFDataMgr; -import org.junit.jupiter.api.Test; - -class ExampleGraphTest { - @Test - void test() { - final Dataset dataset = datasetFrom("" + - "PREFIX : \n" + - "\n" + - "[\n" + - " a :C ;\n" + - " :p1 [\n" + - " :p2 \"XXX\" ;\n" + - " ] ;\n" + - "] .\n"); - - final ExampleDataset wrap = ExampleDataset.wrap(dataset); - final ExampleGraph graph = wrap.getGraph(); - final ExampleNode1 resource = graph.getResource(); - final ExampleNode2 p1 = resource.getP1(); - final String p2 = p1.getP2(); - - System.out.println(p2); - } - - @Test - void test2() { - final ExampleI1.ExampleI2 wrap = ExampleI1.ExampleI2.wrap(DatasetFactory.create()); - } - - private static Dataset datasetFrom(final String rdf) { - final Dataset dataset = DatasetFactory.create(); - RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); - return dataset; - } -} From dc6809f4f5c664d4bb350e83c0f35845459cf2b5 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Mon, 28 Aug 2023 14:41:12 +0200 Subject: [PATCH 040/141] Fold test module into processor --- declarative/pom.xml | 1 - .../wrapping/declarative/processor}/X.java | 3 +- .../declarative/processor}/XTest.java | 2 +- declarative/test/pom.xml | 61 ------------------- 4 files changed, 2 insertions(+), 65 deletions(-) rename declarative/{test/src/main/java/com/inrupt/rdf/wrapping/declarative/test => processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor}/X.java (94%) rename declarative/{test/src/test/java/com/inrupt/rdf/wrapping/declarative/test => processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor}/XTest.java (98%) delete mode 100644 declarative/test/pom.xml diff --git a/declarative/pom.xml b/declarative/pom.xml index 3903ad0df..5d2520c33 100644 --- a/declarative/pom.xml +++ b/declarative/pom.xml @@ -14,7 +14,6 @@ annotation processor - test diff --git a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java b/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/X.java similarity index 94% rename from declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java rename to declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/X.java index 2e39cc04b..38362629c 100644 --- a/declarative/test/src/main/java/com/inrupt/rdf/wrapping/declarative/test/X.java +++ b/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/X.java @@ -18,10 +18,9 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.test; +package com.inrupt.rdf.wrapping.declarative.processor; import com.inrupt.rdf.wrapping.declarative.annotation.*; -import com.inrupt.rdf.wrapping.declarative.processor.Manager; import org.apache.jena.rdf.model.Model; diff --git a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java b/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/XTest.java similarity index 98% rename from declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java rename to declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/XTest.java index 429bc29d0..ee345a616 100644 --- a/declarative/test/src/test/java/com/inrupt/rdf/wrapping/declarative/test/XTest.java +++ b/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/XTest.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.test; +package com.inrupt.rdf.wrapping.declarative.processor; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; diff --git a/declarative/test/pom.xml b/declarative/test/pom.xml deleted file mode 100644 index 60eb8573d..000000000 --- a/declarative/test/pom.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - 4.0.0 - - com.inrupt.rdf - inrupt-rdf-wrapping-declarative - 1.0.1-SNAPSHOT - - - inrupt-rdf-wrapping-declarative-test - Inrupt RDF Wrapping Declarative - Test - - - - - - 1.8 - 1.8 - - - - - com.inrupt.rdf - inrupt-rdf-wrapping-declarative-processor - ${project.version} - provided - true - - - - org.junit.jupiter - junit-jupiter-api - test - - - org.hamcrest - hamcrest - test - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.jacoco - jacoco-maven-plugin - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - - From a5a016f1cb072ab2103c33e3b90ffc27cdac5560 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 9 Sep 2023 10:57:17 +0100 Subject: [PATCH 041/141] Hoist declarative modules --- .../annotation => annotation}/pom.xml | 6 ++-- .../rdf/wrapping}/annotation/Dataset.java | 2 +- .../wrapping}/annotation/DefaultGraph.java | 2 +- .../rdf/wrapping}/annotation/Graph.java | 2 +- .../rdf/wrapping}/annotation/NamedGraph.java | 2 +- .../OptionalFirstInstanceOfEither.java | 2 +- .../OptionalFirstObjectOfEither.java | 2 +- .../OptionalFirstSubjectOfEither.java | 2 +- .../rdf/wrapping}/annotation/Property.java | 2 +- .../rdf/wrapping}/annotation/Resource.java | 2 +- declarative/pom.xml | 30 ------------------- .../javax.annotation.processing.Processor | 1 - ...taset default graph method is default.java | 12 -------- ...ataset default graph method is static.java | 12 -------- .../bad/dataset extends unacceptable.java | 7 ----- ...aset instance method is not annotated.java | 8 ----- .../bad/dataset is not an interface.java | 7 ----- ...dataset named graph method is default.java | 12 -------- .../dataset named graph method is static.java | 12 -------- .../bad/graph extends unacceptable.java | 7 ----- ...raph instance method is not annotated.java | 8 ----- .../graph instance of method is default.java | 12 -------- .../graph instance of method is static.java | 12 -------- .../bad/graph is not an interface.java | 7 ----- .../graph object of method is default.java | 12 -------- .../bad/graph object of method is static.java | 12 -------- .../graph subject of method is default.java | 12 -------- .../graph subject of method is static.java | 12 -------- .../bad/resource extends unacceptable.java | 7 ----- ...urce instance method is not annotated.java | 8 ----- .../bad/resource is not an interface.java | 7 ----- .../resource property method is default.java | 12 -------- .../resource property method is static.java | 12 -------- ...aset default graph method is instance.java | 15 ---------- .../good/dataset extends Dataset.java | 7 ----- .../good/dataset extends nothing.java | 7 ----- ...ataset named graph method is instance.java | 15 ---------- .../dataset unannotated method is static.java | 10 ------- .../resources/good/graph extends Model.java | 7 ----- .../resources/good/graph extends nothing.java | 7 ----- .../graph instance of method is instance.java | 15 ---------- .../graph object of method is instance.java | 15 ---------- .../graph subject of method is instance.java | 15 ---------- .../graph unannotated method is static.java | 10 ------- .../good/resource extends Resource.java | 7 ----- .../good/resource extends nothing.java | 7 ----- ...resource unannotated method is static.java | 10 ------- pom.xml | 3 +- {declarative/processor => processor}/pom.xml | 8 ++--- .../processor/DatasetImplementor.java | 6 ++-- .../wrapping}/processor/DatasetValidator.java | 6 ++-- .../wrapping}/processor/GraphImplementor.java | 8 ++--- .../wrapping}/processor/GraphValidator.java | 8 ++--- .../rdf/wrapping}/processor/Implementor.java | 8 ++--- .../rdf/wrapping}/processor/Manager.java | 6 ++-- .../rdf/wrapping}/processor/Processor.java | 8 ++--- .../processor/ResourceImplementor.java | 2 +- .../processor/ResourceValidator.java | 4 +-- .../wrapping}/processor/ValidationError.java | 2 +- .../rdf/wrapping}/processor/Validator.java | 8 ++--- .../javax.annotation.processing.Processor | 1 + .../wrapping}/processor/ValidatorTest.java | 6 ++-- .../com/inrupt/rdf/wrapping}/processor/X.java | 4 +-- .../inrupt/rdf/wrapping}/processor/XTest.java | 10 +++---- .../resources/validationExamples/README.md | 1 + ...taset default graph method is default.java | 13 ++++++++ ...ataset default graph method is static.java | 13 ++++++++ .../bad/dataset extends unacceptable.java | 8 +++++ ...aset instance method is not annotated.java | 9 ++++++ .../bad/dataset is not an interface.java | 8 +++++ ...dataset named graph method is default.java | 13 ++++++++ .../dataset named graph method is static.java | 13 ++++++++ .../bad/graph extends unacceptable.java | 8 +++++ ...raph instance method is not annotated.java | 9 ++++++ .../graph instance of method is default.java | 13 ++++++++ .../graph instance of method is static.java | 13 ++++++++ .../bad/graph is not an interface.java | 8 +++++ .../graph object of method is default.java | 13 ++++++++ .../bad/graph object of method is static.java | 13 ++++++++ .../graph subject of method is default.java | 13 ++++++++ .../graph subject of method is static.java | 13 ++++++++ .../bad/resource extends unacceptable.java | 8 +++++ ...urce instance method is not annotated.java | 9 ++++++ .../bad/resource is not an interface.java | 8 +++++ .../resource property method is default.java | 13 ++++++++ .../resource property method is static.java | 13 ++++++++ ...aset default graph method is instance.java | 16 ++++++++++ .../good/dataset extends Dataset.java | 8 +++++ .../good/dataset extends nothing.java | 8 +++++ ...ataset named graph method is instance.java | 16 ++++++++++ ...dataset unannotated method is default.java | 3 +- .../dataset unannotated method is static.java | 11 +++++++ .../good/graph extends Model.java | 8 +++++ .../good/graph extends nothing.java | 8 +++++ .../graph instance of method is instance.java | 16 ++++++++++ .../graph object of method is instance.java | 16 ++++++++++ .../graph subject of method is instance.java | 16 ++++++++++ .../graph unannotated method is default.java | 3 +- .../graph unannotated method is static.java | 11 +++++++ .../good/resource extends Resource.java | 8 +++++ .../good/resource extends nothing.java | 8 +++++ ...esource unannotated method is default.java | 3 +- ...resource unannotated method is static.java | 11 +++++++ 103 files changed, 461 insertions(+), 451 deletions(-) rename {declarative/annotation => annotation}/pom.xml (82%) rename {declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative => annotation/src/main/java/com/inrupt/rdf/wrapping}/annotation/Dataset.java (96%) rename {declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative => annotation/src/main/java/com/inrupt/rdf/wrapping}/annotation/DefaultGraph.java (96%) rename {declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative => annotation/src/main/java/com/inrupt/rdf/wrapping}/annotation/Graph.java (96%) rename {declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative => annotation/src/main/java/com/inrupt/rdf/wrapping}/annotation/NamedGraph.java (96%) rename {declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative => annotation/src/main/java/com/inrupt/rdf/wrapping}/annotation/OptionalFirstInstanceOfEither.java (96%) rename {declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative => annotation/src/main/java/com/inrupt/rdf/wrapping}/annotation/OptionalFirstObjectOfEither.java (96%) rename {declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative => annotation/src/main/java/com/inrupt/rdf/wrapping}/annotation/OptionalFirstSubjectOfEither.java (96%) rename {declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative => annotation/src/main/java/com/inrupt/rdf/wrapping}/annotation/Property.java (96%) rename {declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative => annotation/src/main/java/com/inrupt/rdf/wrapping}/annotation/Resource.java (96%) delete mode 100644 declarative/pom.xml delete mode 100644 declarative/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor delete mode 100644 declarative/processor/src/test/resources/bad/dataset default graph method is default.java delete mode 100644 declarative/processor/src/test/resources/bad/dataset default graph method is static.java delete mode 100644 declarative/processor/src/test/resources/bad/dataset extends unacceptable.java delete mode 100644 declarative/processor/src/test/resources/bad/dataset instance method is not annotated.java delete mode 100644 declarative/processor/src/test/resources/bad/dataset is not an interface.java delete mode 100644 declarative/processor/src/test/resources/bad/dataset named graph method is default.java delete mode 100644 declarative/processor/src/test/resources/bad/dataset named graph method is static.java delete mode 100644 declarative/processor/src/test/resources/bad/graph extends unacceptable.java delete mode 100644 declarative/processor/src/test/resources/bad/graph instance method is not annotated.java delete mode 100644 declarative/processor/src/test/resources/bad/graph instance of method is default.java delete mode 100644 declarative/processor/src/test/resources/bad/graph instance of method is static.java delete mode 100644 declarative/processor/src/test/resources/bad/graph is not an interface.java delete mode 100644 declarative/processor/src/test/resources/bad/graph object of method is default.java delete mode 100644 declarative/processor/src/test/resources/bad/graph object of method is static.java delete mode 100644 declarative/processor/src/test/resources/bad/graph subject of method is default.java delete mode 100644 declarative/processor/src/test/resources/bad/graph subject of method is static.java delete mode 100644 declarative/processor/src/test/resources/bad/resource extends unacceptable.java delete mode 100644 declarative/processor/src/test/resources/bad/resource instance method is not annotated.java delete mode 100644 declarative/processor/src/test/resources/bad/resource is not an interface.java delete mode 100644 declarative/processor/src/test/resources/bad/resource property method is default.java delete mode 100644 declarative/processor/src/test/resources/bad/resource property method is static.java delete mode 100644 declarative/processor/src/test/resources/good/dataset default graph method is instance.java delete mode 100644 declarative/processor/src/test/resources/good/dataset extends Dataset.java delete mode 100644 declarative/processor/src/test/resources/good/dataset extends nothing.java delete mode 100644 declarative/processor/src/test/resources/good/dataset named graph method is instance.java delete mode 100644 declarative/processor/src/test/resources/good/dataset unannotated method is static.java delete mode 100644 declarative/processor/src/test/resources/good/graph extends Model.java delete mode 100644 declarative/processor/src/test/resources/good/graph extends nothing.java delete mode 100644 declarative/processor/src/test/resources/good/graph instance of method is instance.java delete mode 100644 declarative/processor/src/test/resources/good/graph object of method is instance.java delete mode 100644 declarative/processor/src/test/resources/good/graph subject of method is instance.java delete mode 100644 declarative/processor/src/test/resources/good/graph unannotated method is static.java delete mode 100644 declarative/processor/src/test/resources/good/resource extends Resource.java delete mode 100644 declarative/processor/src/test/resources/good/resource extends nothing.java delete mode 100644 declarative/processor/src/test/resources/good/resource unannotated method is static.java rename {declarative/processor => processor}/pom.xml (91%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/DatasetImplementor.java (95%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/DatasetValidator.java (90%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/GraphImplementor.java (96%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/GraphValidator.java (87%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/Implementor.java (95%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/Manager.java (93%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/Processor.java (92%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/ResourceImplementor.java (98%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/ResourceValidator.java (93%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/ValidationError.java (97%) rename {declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative => processor/src/main/java/com/inrupt/rdf/wrapping}/processor/Validator.java (95%) create mode 100644 processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor rename {declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative => processor/src/test/java/com/inrupt/rdf/wrapping}/processor/ValidatorTest.java (96%) rename {declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative => processor/src/test/java/com/inrupt/rdf/wrapping}/processor/X.java (94%) rename {declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative => processor/src/test/java/com/inrupt/rdf/wrapping}/processor/XTest.java (93%) create mode 100644 processor/src/test/resources/validationExamples/README.md create mode 100644 processor/src/test/resources/validationExamples/bad/dataset default graph method is default.java create mode 100644 processor/src/test/resources/validationExamples/bad/dataset default graph method is static.java create mode 100644 processor/src/test/resources/validationExamples/bad/dataset extends unacceptable.java create mode 100644 processor/src/test/resources/validationExamples/bad/dataset instance method is not annotated.java create mode 100644 processor/src/test/resources/validationExamples/bad/dataset is not an interface.java create mode 100644 processor/src/test/resources/validationExamples/bad/dataset named graph method is default.java create mode 100644 processor/src/test/resources/validationExamples/bad/dataset named graph method is static.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph extends unacceptable.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph instance method is not annotated.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph instance of method is default.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph instance of method is static.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph is not an interface.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph object of method is default.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph object of method is static.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph subject of method is default.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph subject of method is static.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource extends unacceptable.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource instance method is not annotated.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource is not an interface.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource property method is default.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource property method is static.java create mode 100644 processor/src/test/resources/validationExamples/good/dataset default graph method is instance.java create mode 100644 processor/src/test/resources/validationExamples/good/dataset extends Dataset.java create mode 100644 processor/src/test/resources/validationExamples/good/dataset extends nothing.java create mode 100644 processor/src/test/resources/validationExamples/good/dataset named graph method is instance.java rename {declarative/processor/src/test/resources => processor/src/test/resources/validationExamples}/good/dataset unannotated method is default.java (50%) create mode 100644 processor/src/test/resources/validationExamples/good/dataset unannotated method is static.java create mode 100644 processor/src/test/resources/validationExamples/good/graph extends Model.java create mode 100644 processor/src/test/resources/validationExamples/good/graph extends nothing.java create mode 100644 processor/src/test/resources/validationExamples/good/graph instance of method is instance.java create mode 100644 processor/src/test/resources/validationExamples/good/graph object of method is instance.java create mode 100644 processor/src/test/resources/validationExamples/good/graph subject of method is instance.java rename {declarative/processor/src/test/resources => processor/src/test/resources/validationExamples}/good/graph unannotated method is default.java (50%) create mode 100644 processor/src/test/resources/validationExamples/good/graph unannotated method is static.java create mode 100644 processor/src/test/resources/validationExamples/good/resource extends Resource.java create mode 100644 processor/src/test/resources/validationExamples/good/resource extends nothing.java rename {declarative/processor/src/test/resources => processor/src/test/resources/validationExamples}/good/resource unannotated method is default.java (50%) create mode 100644 processor/src/test/resources/validationExamples/good/resource unannotated method is static.java diff --git a/declarative/annotation/pom.xml b/annotation/pom.xml similarity index 82% rename from declarative/annotation/pom.xml rename to annotation/pom.xml index 9019e2fe4..f85aab6bd 100644 --- a/declarative/annotation/pom.xml +++ b/annotation/pom.xml @@ -3,12 +3,12 @@ 4.0.0 com.inrupt.rdf - inrupt-rdf-wrapping-declarative + inrupt-rdf-wrapping 1.0.1-SNAPSHOT - inrupt-rdf-wrapping-declarative-annotation - Inrupt RDF Wrapping Declarative - Annotation + inrupt-rdf-wrapping-annotation + Inrupt RDF Wrapping - Annotation 1.8 diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Dataset.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Dataset.java similarity index 96% rename from declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Dataset.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Dataset.java index 7db497266..ce2c5f99d 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Dataset.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Dataset.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotation; +package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/DefaultGraph.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java similarity index 96% rename from declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/DefaultGraph.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java index 2d53f9afe..a35f0a3ca 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/DefaultGraph.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotation; +package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.SOURCE; diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Graph.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Graph.java similarity index 96% rename from declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Graph.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Graph.java index eedd4cbe7..f43078cab 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Graph.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Graph.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotation; +package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/NamedGraph.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java similarity index 96% rename from declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/NamedGraph.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java index c8514351f..d4db7e4b8 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/NamedGraph.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotation; +package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.SOURCE; diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstInstanceOfEither.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstInstanceOfEither.java similarity index 96% rename from declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstInstanceOfEither.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstInstanceOfEither.java index 67743eaac..49f33d90f 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstInstanceOfEither.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstInstanceOfEither.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotation; +package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.SOURCE; diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstObjectOfEither.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java similarity index 96% rename from declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstObjectOfEither.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java index f6cfd2b75..ea0b112dd 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstObjectOfEither.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotation; +package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.SOURCE; diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstSubjectOfEither.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java similarity index 96% rename from declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstSubjectOfEither.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java index 6eef65cef..ca845c3f1 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/OptionalFirstSubjectOfEither.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotation; +package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.SOURCE; diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java similarity index 96% rename from declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Property.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java index 9cfa09bb4..6c821daf0 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotation; +package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.SOURCE; diff --git a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Resource.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Resource.java similarity index 96% rename from declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Resource.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Resource.java index e15566f0f..72300f460 100644 --- a/declarative/annotation/src/main/java/com/inrupt/rdf/wrapping/declarative/annotation/Resource.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Resource.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.annotation; +package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; diff --git a/declarative/pom.xml b/declarative/pom.xml deleted file mode 100644 index 5d2520c33..000000000 --- a/declarative/pom.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - 4.0.0 - - com.inrupt.rdf - inrupt-rdf-wrapping - 1.0.1-SNAPSHOT - - - inrupt-rdf-wrapping-declarative - Inrupt RDF Wrapping Declarative - pom - - - annotation - processor - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - - diff --git a/declarative/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/declarative/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor deleted file mode 100644 index 63e203cdb..000000000 --- a/declarative/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ /dev/null @@ -1 +0,0 @@ -com.inrupt.rdf.wrapping.declarative.processor.Processor diff --git a/declarative/processor/src/test/resources/bad/dataset default graph method is default.java b/declarative/processor/src/test/resources/bad/dataset default graph method is default.java deleted file mode 100644 index ba49653c6..000000000 --- a/declarative/processor/src/test/resources/bad/dataset default graph method is default.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; -import com.inrupt.rdf.wrapping.declarative.annotation.DefaultGraph; - -@Dataset -interface X { - @DefaultGraph - default Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/dataset default graph method is static.java b/declarative/processor/src/test/resources/bad/dataset default graph method is static.java deleted file mode 100644 index 994179ee0..000000000 --- a/declarative/processor/src/test/resources/bad/dataset default graph method is static.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; -import com.inrupt.rdf.wrapping.declarative.annotation.DefaultGraph; - -@Dataset -interface X { - @DefaultGraph - static Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/dataset extends unacceptable.java b/declarative/processor/src/test/resources/bad/dataset extends unacceptable.java deleted file mode 100644 index 8ec63b2ef..000000000 --- a/declarative/processor/src/test/resources/bad/dataset extends unacceptable.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; - -@Dataset -interface X extends Comparable { -} diff --git a/declarative/processor/src/test/resources/bad/dataset instance method is not annotated.java b/declarative/processor/src/test/resources/bad/dataset instance method is not annotated.java deleted file mode 100644 index 1e1f2ff2f..000000000 --- a/declarative/processor/src/test/resources/bad/dataset instance method is not annotated.java +++ /dev/null @@ -1,8 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; - -@Dataset -interface X { - Object x(); -} diff --git a/declarative/processor/src/test/resources/bad/dataset is not an interface.java b/declarative/processor/src/test/resources/bad/dataset is not an interface.java deleted file mode 100644 index 7db3930b6..000000000 --- a/declarative/processor/src/test/resources/bad/dataset is not an interface.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; - -@Dataset -class X { -} diff --git a/declarative/processor/src/test/resources/bad/dataset named graph method is default.java b/declarative/processor/src/test/resources/bad/dataset named graph method is default.java deleted file mode 100644 index 248f81204..000000000 --- a/declarative/processor/src/test/resources/bad/dataset named graph method is default.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; -import com.inrupt.rdf.wrapping.declarative.annotation.NamedGraph; - -@Dataset -interface X { - @NamedGraph("x") - default Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/dataset named graph method is static.java b/declarative/processor/src/test/resources/bad/dataset named graph method is static.java deleted file mode 100644 index d6ac902a7..000000000 --- a/declarative/processor/src/test/resources/bad/dataset named graph method is static.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; -import com.inrupt.rdf.wrapping.declarative.annotation.NamedGraph; - -@Dataset -interface X { - @NamedGraph("x") - static Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/graph extends unacceptable.java b/declarative/processor/src/test/resources/bad/graph extends unacceptable.java deleted file mode 100644 index 46af15af5..000000000 --- a/declarative/processor/src/test/resources/bad/graph extends unacceptable.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; - -@Graph -interface X extends Comparable { -} diff --git a/declarative/processor/src/test/resources/bad/graph instance method is not annotated.java b/declarative/processor/src/test/resources/bad/graph instance method is not annotated.java deleted file mode 100644 index cee38a511..000000000 --- a/declarative/processor/src/test/resources/bad/graph instance method is not annotated.java +++ /dev/null @@ -1,8 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; - -@Graph -interface X { - Object x(); -} diff --git a/declarative/processor/src/test/resources/bad/graph instance of method is default.java b/declarative/processor/src/test/resources/bad/graph instance of method is default.java deleted file mode 100644 index 3c1a8e833..000000000 --- a/declarative/processor/src/test/resources/bad/graph instance of method is default.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; - -@Graph -interface X { - @OptionalFirstInstanceOfEither("x") - default Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/graph instance of method is static.java b/declarative/processor/src/test/resources/bad/graph instance of method is static.java deleted file mode 100644 index a7a7ac42b..000000000 --- a/declarative/processor/src/test/resources/bad/graph instance of method is static.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; - -@Graph -interface X { - @OptionalFirstInstanceOfEither("x") - static Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/graph is not an interface.java b/declarative/processor/src/test/resources/bad/graph is not an interface.java deleted file mode 100644 index 937f396db..000000000 --- a/declarative/processor/src/test/resources/bad/graph is not an interface.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; - -@Graph -class X { -} diff --git a/declarative/processor/src/test/resources/bad/graph object of method is default.java b/declarative/processor/src/test/resources/bad/graph object of method is default.java deleted file mode 100644 index f10cc8417..000000000 --- a/declarative/processor/src/test/resources/bad/graph object of method is default.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstObjectOfEither; - -@Graph -interface X { - @OptionalFirstObjectOfEither("x") - default Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/graph object of method is static.java b/declarative/processor/src/test/resources/bad/graph object of method is static.java deleted file mode 100644 index febf6e39f..000000000 --- a/declarative/processor/src/test/resources/bad/graph object of method is static.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstObjectOfEither; - -@Graph -interface X { - @OptionalFirstObjectOfEither("x") - static Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/graph subject of method is default.java b/declarative/processor/src/test/resources/bad/graph subject of method is default.java deleted file mode 100644 index 77da7d339..000000000 --- a/declarative/processor/src/test/resources/bad/graph subject of method is default.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; - -@Graph -interface X { - @OptionalFirstSubjectOfEither("x") - default Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/graph subject of method is static.java b/declarative/processor/src/test/resources/bad/graph subject of method is static.java deleted file mode 100644 index 1dda00476..000000000 --- a/declarative/processor/src/test/resources/bad/graph subject of method is static.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; - -@Graph -interface X { - @OptionalFirstSubjectOfEither("x") - static Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/resource extends unacceptable.java b/declarative/processor/src/test/resources/bad/resource extends unacceptable.java deleted file mode 100644 index dcc95023e..000000000 --- a/declarative/processor/src/test/resources/bad/resource extends unacceptable.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Resource -interface X extends Comparable { -} diff --git a/declarative/processor/src/test/resources/bad/resource instance method is not annotated.java b/declarative/processor/src/test/resources/bad/resource instance method is not annotated.java deleted file mode 100644 index 3a7f4ff88..000000000 --- a/declarative/processor/src/test/resources/bad/resource instance method is not annotated.java +++ /dev/null @@ -1,8 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Resource -interface X { - Object x(); -} diff --git a/declarative/processor/src/test/resources/bad/resource is not an interface.java b/declarative/processor/src/test/resources/bad/resource is not an interface.java deleted file mode 100644 index d20a92715..000000000 --- a/declarative/processor/src/test/resources/bad/resource is not an interface.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Resource -class X { -} diff --git a/declarative/processor/src/test/resources/bad/resource property method is default.java b/declarative/processor/src/test/resources/bad/resource property method is default.java deleted file mode 100644 index 5fd82296d..000000000 --- a/declarative/processor/src/test/resources/bad/resource property method is default.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Property; -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Resource -interface X { - @Property - default Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/bad/resource property method is static.java b/declarative/processor/src/test/resources/bad/resource property method is static.java deleted file mode 100644 index 5fd82296d..000000000 --- a/declarative/processor/src/test/resources/bad/resource property method is static.java +++ /dev/null @@ -1,12 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Property; -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Resource -interface X { - @Property - default Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/good/dataset default graph method is instance.java b/declarative/processor/src/test/resources/good/dataset default graph method is instance.java deleted file mode 100644 index 2914666b6..000000000 --- a/declarative/processor/src/test/resources/good/dataset default graph method is instance.java +++ /dev/null @@ -1,15 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; -import com.inrupt.rdf.wrapping.declarative.annotation.DefaultGraph; -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; - -@Dataset -interface X { - @DefaultGraph - Y x(); - - @Graph - interface Y { - } -} diff --git a/declarative/processor/src/test/resources/good/dataset extends Dataset.java b/declarative/processor/src/test/resources/good/dataset extends Dataset.java deleted file mode 100644 index 8dce4683c..000000000 --- a/declarative/processor/src/test/resources/good/dataset extends Dataset.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; - -@Dataset -interface X extends org.apache.jena.query.Dataset { -} diff --git a/declarative/processor/src/test/resources/good/dataset extends nothing.java b/declarative/processor/src/test/resources/good/dataset extends nothing.java deleted file mode 100644 index 7126e04c9..000000000 --- a/declarative/processor/src/test/resources/good/dataset extends nothing.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; - -@Dataset -interface X { -} diff --git a/declarative/processor/src/test/resources/good/dataset named graph method is instance.java b/declarative/processor/src/test/resources/good/dataset named graph method is instance.java deleted file mode 100644 index 6b94fc98f..000000000 --- a/declarative/processor/src/test/resources/good/dataset named graph method is instance.java +++ /dev/null @@ -1,15 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.annotation.NamedGraph; - -@Dataset -interface X { - @NamedGraph("x") - Y x(); - - @Graph - interface Y { - } -} diff --git a/declarative/processor/src/test/resources/good/dataset unannotated method is static.java b/declarative/processor/src/test/resources/good/dataset unannotated method is static.java deleted file mode 100644 index c89fe7ce5..000000000 --- a/declarative/processor/src/test/resources/good/dataset unannotated method is static.java +++ /dev/null @@ -1,10 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; - -@Dataset -interface X { - static Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/good/graph extends Model.java b/declarative/processor/src/test/resources/good/graph extends Model.java deleted file mode 100644 index 6be7f94cb..000000000 --- a/declarative/processor/src/test/resources/good/graph extends Model.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; - -@Graph -interface X extends org.apache.jena.rdf.model.Model { -} diff --git a/declarative/processor/src/test/resources/good/graph extends nothing.java b/declarative/processor/src/test/resources/good/graph extends nothing.java deleted file mode 100644 index 018fa6760..000000000 --- a/declarative/processor/src/test/resources/good/graph extends nothing.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; - -@Graph -interface X { -} diff --git a/declarative/processor/src/test/resources/good/graph instance of method is instance.java b/declarative/processor/src/test/resources/good/graph instance of method is instance.java deleted file mode 100644 index 0653cffe0..000000000 --- a/declarative/processor/src/test/resources/good/graph instance of method is instance.java +++ /dev/null @@ -1,15 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Graph -interface X { - @OptionalFirstInstanceOfEither("x") - Y x(); - - @Resource - interface Y { - } -} diff --git a/declarative/processor/src/test/resources/good/graph object of method is instance.java b/declarative/processor/src/test/resources/good/graph object of method is instance.java deleted file mode 100644 index b9d2323b4..000000000 --- a/declarative/processor/src/test/resources/good/graph object of method is instance.java +++ /dev/null @@ -1,15 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstObjectOfEither; -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Graph -interface X { - @OptionalFirstObjectOfEither("x") - Y x(); - - @Resource - interface Y { - } -} diff --git a/declarative/processor/src/test/resources/good/graph subject of method is instance.java b/declarative/processor/src/test/resources/good/graph subject of method is instance.java deleted file mode 100644 index 672f98b72..000000000 --- a/declarative/processor/src/test/resources/good/graph subject of method is instance.java +++ /dev/null @@ -1,15 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Graph -interface X { - @OptionalFirstSubjectOfEither("x") - Y x(); - - @Resource - interface Y { - } -} diff --git a/declarative/processor/src/test/resources/good/graph unannotated method is static.java b/declarative/processor/src/test/resources/good/graph unannotated method is static.java deleted file mode 100644 index 82a43cbe1..000000000 --- a/declarative/processor/src/test/resources/good/graph unannotated method is static.java +++ /dev/null @@ -1,10 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; - -@Graph -interface X { - static Object x() { - return null; - } -} diff --git a/declarative/processor/src/test/resources/good/resource extends Resource.java b/declarative/processor/src/test/resources/good/resource extends Resource.java deleted file mode 100644 index a36b8eae5..000000000 --- a/declarative/processor/src/test/resources/good/resource extends Resource.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Resource -interface X extends org.apache.jena.rdf.model.Resource { -} diff --git a/declarative/processor/src/test/resources/good/resource extends nothing.java b/declarative/processor/src/test/resources/good/resource extends nothing.java deleted file mode 100644 index 778ffc722..000000000 --- a/declarative/processor/src/test/resources/good/resource extends nothing.java +++ /dev/null @@ -1,7 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Resource -interface X { -} diff --git a/declarative/processor/src/test/resources/good/resource unannotated method is static.java b/declarative/processor/src/test/resources/good/resource unannotated method is static.java deleted file mode 100644 index 6f8f37afe..000000000 --- a/declarative/processor/src/test/resources/good/resource unannotated method is static.java +++ /dev/null @@ -1,10 +0,0 @@ -package x; - -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; - -@Resource -interface X { - static Object x() { - return null; - } -} diff --git a/pom.xml b/pom.xml index 0c8bc6508..8299ba28d 100644 --- a/pom.xml +++ b/pom.xml @@ -66,12 +66,13 @@ + annotation commons test jena rdf4j + processor reports - declarative diff --git a/declarative/processor/pom.xml b/processor/pom.xml similarity index 91% rename from declarative/processor/pom.xml rename to processor/pom.xml index 1de296607..38f8028c9 100644 --- a/declarative/processor/pom.xml +++ b/processor/pom.xml @@ -3,12 +3,12 @@ 4.0.0 com.inrupt.rdf - inrupt-rdf-wrapping-declarative + inrupt-rdf-wrapping 1.0.1-SNAPSHOT - inrupt-rdf-wrapping-declarative-processor - Inrupt RDF Wrapping Declarative - Processor + inrupt-rdf-wrapping-processor + Inrupt RDF Wrapping - Processor @@ -21,7 +21,7 @@ com.inrupt.rdf - inrupt-rdf-wrapping-declarative-annotation + inrupt-rdf-wrapping-annotation ${project.version} diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java similarity index 95% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 838c0713b..09941bd4e 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -18,15 +18,15 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; import static org.jboss.jdeparser.JExpr.THIS; import static org.jboss.jdeparser.JExprs.$v; import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; -import com.inrupt.rdf.wrapping.declarative.annotation.DefaultGraph; -import com.inrupt.rdf.wrapping.declarative.annotation.NamedGraph; +import com.inrupt.rdf.wrapping.annotation.DefaultGraph; +import com.inrupt.rdf.wrapping.annotation.NamedGraph; import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java similarity index 90% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetValidator.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java index b2d5f3276..b3ea97f14 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/DatasetValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java @@ -18,10 +18,10 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; -import com.inrupt.rdf.wrapping.declarative.annotation.DefaultGraph; -import com.inrupt.rdf.wrapping.declarative.annotation.NamedGraph; +import com.inrupt.rdf.wrapping.annotation.DefaultGraph; +import com.inrupt.rdf.wrapping.annotation.NamedGraph; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java similarity index 96% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 8395b4ff5..01ee5da63 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -18,16 +18,16 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; import static org.jboss.jdeparser.JExpr.THIS; import static org.jboss.jdeparser.JExprs.$v; import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstObjectOfEither; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; import com.inrupt.rdf.wrapping.jena.WrapperModel; import javax.annotation.Generated; diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java similarity index 87% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphValidator.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java index b7dafb6d2..99e73d856 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/GraphValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java @@ -18,11 +18,11 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstInstanceOfEither; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstObjectOfEither; -import com.inrupt.rdf.wrapping.declarative.annotation.OptionalFirstSubjectOfEither; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java similarity index 95% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 4c1396cc0..ef16da50d 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; import static org.jboss.jdeparser.JMod.PUBLIC; import static org.jboss.jdeparser.JTypes.$t; @@ -85,11 +85,11 @@ static Implementor get(final TypeElement annotation, final ProcessingEnvironment final TypeElement annotatedType = (TypeElement) element; switch (annotation.getQualifiedName().toString()) { - case "com.inrupt.rdf.wrapping.declarative.annotation.Dataset": + case "com.inrupt.rdf.wrapping.annotation.Dataset": return new DatasetImplementor(env, annotatedType); - case "com.inrupt.rdf.wrapping.declarative.annotation.Graph": + case "com.inrupt.rdf.wrapping.annotation.Graph": return new GraphImplementor(env, annotatedType); - case "com.inrupt.rdf.wrapping.declarative.annotation.Resource": + case "com.inrupt.rdf.wrapping.annotation.Resource": return new ResourceImplementor(env, annotatedType); default: throw new RuntimeException("unknown annotation type"); diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Manager.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java similarity index 93% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Manager.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java index 3d65fd5f2..67c917016 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Manager.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java @@ -18,10 +18,10 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.declarative.processor.Implementor.WRAP; -import static com.inrupt.rdf.wrapping.declarative.processor.Implementor.asImplementation; +import static com.inrupt.rdf.wrapping.processor.Implementor.WRAP; +import static com.inrupt.rdf.wrapping.processor.Implementor.asImplementation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java similarity index 92% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java index 94ef02a67..c6a82f978 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Processor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; import java.util.ArrayList; import java.util.Set; @@ -33,9 +33,9 @@ import javax.tools.Diagnostic; @SupportedAnnotationTypes({ - "com.inrupt.rdf.wrapping.declarative.annotation.Dataset", - "com.inrupt.rdf.wrapping.declarative.annotation.Graph", - "com.inrupt.rdf.wrapping.declarative.annotation.Resource" + "com.inrupt.rdf.wrapping.annotation.Dataset", + "com.inrupt.rdf.wrapping.annotation.Graph", + "com.inrupt.rdf.wrapping.annotation.Resource" }) @SupportedSourceVersion(SourceVersion.RELEASE_8) public class Processor extends AbstractProcessor { diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java similarity index 98% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index fee28d100..19a168eb9 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; import static org.jboss.jdeparser.JExprs.$v; import static org.jboss.jdeparser.JMod.*; diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java similarity index 93% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceValidator.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 18b36911f..1143bcc72 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -18,9 +18,9 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; -import com.inrupt.rdf.wrapping.declarative.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Property; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ValidationError.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java similarity index 97% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ValidationError.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java index 1a712fa40..900fcb9a5 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/ValidationError.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; import javax.annotation.processing.Messager; import javax.lang.model.element.AnnotationMirror; diff --git a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java similarity index 95% rename from declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Validator.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 9def55fdf..3d790ea71 100644 --- a/declarative/processor/src/main/java/com/inrupt/rdf/wrapping/declarative/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; import java.lang.annotation.Annotation; import java.util.ArrayList; @@ -48,11 +48,11 @@ protected Validator(final TypeElement annotation, final ProcessingEnvironment en static Validator get(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { switch (annotation.getQualifiedName().toString()) { - case "com.inrupt.rdf.wrapping.declarative.annotation.Dataset": + case "com.inrupt.rdf.wrapping.annotation.Dataset": return new DatasetValidator(annotation, env, element); - case "com.inrupt.rdf.wrapping.declarative.annotation.Graph": + case "com.inrupt.rdf.wrapping.annotation.Graph": return new GraphValidator(annotation, env, element); - case "com.inrupt.rdf.wrapping.declarative.annotation.Resource": + case "com.inrupt.rdf.wrapping.annotation.Resource": return new ResourceValidator(annotation, env, element); default: throw new RuntimeException("unknown annotation type"); diff --git a/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 000000000..91d7b49ba --- /dev/null +++ b/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +com.inrupt.rdf.wrapping.processor.Processor diff --git a/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java similarity index 96% rename from declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/ValidatorTest.java rename to processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index fd1231663..ed5e302a5 100644 --- a/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; import static com.google.testing.compile.CompilationSubject.assertThat; import static com.google.testing.compile.JavaFileObjects.forResource; @@ -54,7 +54,7 @@ void init() { @ParameterizedTest(name = "[{1}] when {0}") @MethodSource void compilationErrorOnInvalid(final String name, final String error) { - final JavaFileObject file = forResource("bad/" + name + ".java"); + final JavaFileObject file = forResource("validationExamples/bad/" + name + ".java"); final Compilation compilation = compiler.compile(file); assertThat(compilation).hadErrorContaining(error).inFile(file); @@ -92,7 +92,7 @@ private static Stream compilationErrorOnInvalid() { @ParameterizedTest(name = "{0}") @MethodSource void compilationSucceeds(final String name) { - final JavaFileObject file = forResource("good/" + name + ".java"); + final JavaFileObject file = forResource("validationExamples/good/" + name + ".java"); final Compilation compilation = compiler.compile(file); assertThat(compilation).succeeded(); diff --git a/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/X.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java similarity index 94% rename from declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/X.java rename to processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java index 38362629c..44a398dfe 100644 --- a/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/X.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java @@ -18,9 +18,9 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; -import com.inrupt.rdf.wrapping.declarative.annotation.*; +import com.inrupt.rdf.wrapping.annotation.*; import org.apache.jena.rdf.model.Model; diff --git a/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/XTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java similarity index 93% rename from declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/XTest.java rename to processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java index ee345a616..e776daf9f 100644 --- a/declarative/processor/src/test/java/com/inrupt/rdf/wrapping/declarative/processor/XTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java @@ -18,7 +18,7 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.declarative.processor; +package com.inrupt.rdf.wrapping.processor; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -31,6 +31,7 @@ import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFDataMgr; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class XTest { @@ -38,7 +39,7 @@ class XTest { void datasetCanWrap() { final Dataset dataset = DatasetFactory.create(); - assertDoesNotThrow(() -> X.wrap(dataset)); + Assertions.assertDoesNotThrow(() -> X.wrap(dataset)); } @Test @@ -59,7 +60,7 @@ void datasetCanGetNamedGraph() { void graphCanWrap() { final Model model = ModelFactory.createDefaultModel(); - assertDoesNotThrow(() -> X.Y.wrap(model)); + Assertions.assertDoesNotThrow(() -> X.Y.wrap(model)); } @Test @@ -88,8 +89,7 @@ void graphCanGetFirstObjectOf() { @Test void e2e() { - final Dataset dataset = datasetFrom("" + - "PREFIX : \n" + + final Dataset dataset = datasetFrom("PREFIX : \n" + "\n" + "GRAPH {\n" + " [\n" + diff --git a/processor/src/test/resources/validationExamples/README.md b/processor/src/test/resources/validationExamples/README.md new file mode 100644 index 000000000..c8b082d9a --- /dev/null +++ b/processor/src/test/resources/validationExamples/README.md @@ -0,0 +1 @@ +This folder contains Java files that are compiled only during [compile-time validation testing](../../java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java). diff --git a/processor/src/test/resources/validationExamples/bad/dataset default graph method is default.java b/processor/src/test/resources/validationExamples/bad/dataset default graph method is default.java new file mode 100644 index 000000000..ad4efb7e5 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset default graph method is default.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.DefaultGraph; + +@Dataset +interface X { + @DefaultGraph + default Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/dataset default graph method is static.java b/processor/src/test/resources/validationExamples/bad/dataset default graph method is static.java new file mode 100644 index 000000000..91b901b3e --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset default graph method is static.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.DefaultGraph; + +@Dataset +interface X { + @DefaultGraph + static Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/dataset extends unacceptable.java b/processor/src/test/resources/validationExamples/bad/dataset extends unacceptable.java new file mode 100644 index 000000000..530a9092e --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset extends unacceptable.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; + +@Dataset +interface X extends Comparable { +} diff --git a/processor/src/test/resources/validationExamples/bad/dataset instance method is not annotated.java b/processor/src/test/resources/validationExamples/bad/dataset instance method is not annotated.java new file mode 100644 index 000000000..ca7ef4cca --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset instance method is not annotated.java @@ -0,0 +1,9 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; + +@Dataset +interface X { + Object x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/dataset is not an interface.java b/processor/src/test/resources/validationExamples/bad/dataset is not an interface.java new file mode 100644 index 000000000..6df63a1af --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset is not an interface.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; + +@Dataset +class X { +} diff --git a/processor/src/test/resources/validationExamples/bad/dataset named graph method is default.java b/processor/src/test/resources/validationExamples/bad/dataset named graph method is default.java new file mode 100644 index 000000000..09878d616 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset named graph method is default.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.NamedGraph; + +@Dataset +interface X { + @NamedGraph("x") + default Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/dataset named graph method is static.java b/processor/src/test/resources/validationExamples/bad/dataset named graph method is static.java new file mode 100644 index 000000000..117b4b22f --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset named graph method is static.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.NamedGraph; + +@Dataset +interface X { + @NamedGraph("x") + static Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/graph extends unacceptable.java b/processor/src/test/resources/validationExamples/bad/graph extends unacceptable.java new file mode 100644 index 000000000..7269ec616 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph extends unacceptable.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; + +@Graph +interface X extends Comparable { +} diff --git a/processor/src/test/resources/validationExamples/bad/graph instance method is not annotated.java b/processor/src/test/resources/validationExamples/bad/graph instance method is not annotated.java new file mode 100644 index 000000000..370a3c4a5 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph instance method is not annotated.java @@ -0,0 +1,9 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; + +@Graph +interface X { + Object x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/graph instance of method is default.java b/processor/src/test/resources/validationExamples/bad/graph instance of method is default.java new file mode 100644 index 000000000..abbe18502 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph instance of method is default.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; + +@Graph +interface X { + @OptionalFirstInstanceOfEither("x") + default Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/graph instance of method is static.java b/processor/src/test/resources/validationExamples/bad/graph instance of method is static.java new file mode 100644 index 000000000..114ca2699 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph instance of method is static.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; + +@Graph +interface X { + @OptionalFirstInstanceOfEither("x") + static Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/graph is not an interface.java b/processor/src/test/resources/validationExamples/bad/graph is not an interface.java new file mode 100644 index 000000000..2f736ae9f --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph is not an interface.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; + +@Graph +class X { +} diff --git a/processor/src/test/resources/validationExamples/bad/graph object of method is default.java b/processor/src/test/resources/validationExamples/bad/graph object of method is default.java new file mode 100644 index 000000000..1642453d0 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph object of method is default.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; + +@Graph +interface X { + @OptionalFirstObjectOfEither("x") + default Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/graph object of method is static.java b/processor/src/test/resources/validationExamples/bad/graph object of method is static.java new file mode 100644 index 000000000..8749cd7b6 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph object of method is static.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; + +@Graph +interface X { + @OptionalFirstObjectOfEither("x") + static Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/graph subject of method is default.java b/processor/src/test/resources/validationExamples/bad/graph subject of method is default.java new file mode 100644 index 000000000..886457f49 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph subject of method is default.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; + +@Graph +interface X { + @OptionalFirstSubjectOfEither("x") + default Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/graph subject of method is static.java b/processor/src/test/resources/validationExamples/bad/graph subject of method is static.java new file mode 100644 index 000000000..bb18a779d --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph subject of method is static.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; + +@Graph +interface X { + @OptionalFirstSubjectOfEither("x") + static Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/resource extends unacceptable.java b/processor/src/test/resources/validationExamples/bad/resource extends unacceptable.java new file mode 100644 index 000000000..b23e09188 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource extends unacceptable.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X extends Comparable { +} diff --git a/processor/src/test/resources/validationExamples/bad/resource instance method is not annotated.java b/processor/src/test/resources/validationExamples/bad/resource instance method is not annotated.java new file mode 100644 index 000000000..93890b868 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource instance method is not annotated.java @@ -0,0 +1,9 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + Object x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/resource is not an interface.java b/processor/src/test/resources/validationExamples/bad/resource is not an interface.java new file mode 100644 index 000000000..3945992a5 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource is not an interface.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +class X { +} diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is default.java b/processor/src/test/resources/validationExamples/bad/resource property method is default.java new file mode 100644 index 000000000..39e70dd34 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource property method is default.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + @Property + default Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is static.java b/processor/src/test/resources/validationExamples/bad/resource property method is static.java new file mode 100644 index 000000000..39e70dd34 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource property method is static.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + @Property + default Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/good/dataset default graph method is instance.java b/processor/src/test/resources/validationExamples/good/dataset default graph method is instance.java new file mode 100644 index 000000000..ab5324bc8 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/dataset default graph method is instance.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.DefaultGraph; +import com.inrupt.rdf.wrapping.annotation.Graph; + +@Dataset +interface X { + @DefaultGraph + Y x(); + + @Graph + interface Y { + } +} diff --git a/processor/src/test/resources/validationExamples/good/dataset extends Dataset.java b/processor/src/test/resources/validationExamples/good/dataset extends Dataset.java new file mode 100644 index 000000000..ba7b2c281 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/dataset extends Dataset.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; + +@Dataset +interface X extends org.apache.jena.query.Dataset { +} diff --git a/processor/src/test/resources/validationExamples/good/dataset extends nothing.java b/processor/src/test/resources/validationExamples/good/dataset extends nothing.java new file mode 100644 index 000000000..a905418f4 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/dataset extends nothing.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; + +@Dataset +interface X { +} diff --git a/processor/src/test/resources/validationExamples/good/dataset named graph method is instance.java b/processor/src/test/resources/validationExamples/good/dataset named graph method is instance.java new file mode 100644 index 000000000..f43a4a9ae --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/dataset named graph method is instance.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.NamedGraph; + +@Dataset +interface X { + @NamedGraph("x") + Y x(); + + @Graph + interface Y { + } +} diff --git a/declarative/processor/src/test/resources/good/dataset unannotated method is default.java b/processor/src/test/resources/validationExamples/good/dataset unannotated method is default.java similarity index 50% rename from declarative/processor/src/test/resources/good/dataset unannotated method is default.java rename to processor/src/test/resources/validationExamples/good/dataset unannotated method is default.java index 3ad3e68ae..4a783b098 100644 --- a/declarative/processor/src/test/resources/good/dataset unannotated method is default.java +++ b/processor/src/test/resources/validationExamples/good/dataset unannotated method is default.java @@ -1,6 +1,7 @@ +// This file is compiled only in test. package x; -import com.inrupt.rdf.wrapping.declarative.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.Dataset; @Dataset interface X { diff --git a/processor/src/test/resources/validationExamples/good/dataset unannotated method is static.java b/processor/src/test/resources/validationExamples/good/dataset unannotated method is static.java new file mode 100644 index 000000000..3d3a7a8f9 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/dataset unannotated method is static.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; + +@Dataset +interface X { + static Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/good/graph extends Model.java b/processor/src/test/resources/validationExamples/good/graph extends Model.java new file mode 100644 index 000000000..f3cde527a --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/graph extends Model.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; + +@Graph +interface X extends org.apache.jena.rdf.model.Model { +} diff --git a/processor/src/test/resources/validationExamples/good/graph extends nothing.java b/processor/src/test/resources/validationExamples/good/graph extends nothing.java new file mode 100644 index 000000000..00eca9ac0 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/graph extends nothing.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; + +@Graph +interface X { +} diff --git a/processor/src/test/resources/validationExamples/good/graph instance of method is instance.java b/processor/src/test/resources/validationExamples/good/graph instance of method is instance.java new file mode 100644 index 000000000..02de4b59f --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/graph instance of method is instance.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Graph +interface X { + @OptionalFirstInstanceOfEither("x") + Y x(); + + @Resource + interface Y { + } +} diff --git a/processor/src/test/resources/validationExamples/good/graph object of method is instance.java b/processor/src/test/resources/validationExamples/good/graph object of method is instance.java new file mode 100644 index 000000000..466f690d8 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/graph object of method is instance.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Graph +interface X { + @OptionalFirstObjectOfEither("x") + Y x(); + + @Resource + interface Y { + } +} diff --git a/processor/src/test/resources/validationExamples/good/graph subject of method is instance.java b/processor/src/test/resources/validationExamples/good/graph subject of method is instance.java new file mode 100644 index 000000000..f2fa18f1e --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/graph subject of method is instance.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Graph +interface X { + @OptionalFirstSubjectOfEither("x") + Y x(); + + @Resource + interface Y { + } +} diff --git a/declarative/processor/src/test/resources/good/graph unannotated method is default.java b/processor/src/test/resources/validationExamples/good/graph unannotated method is default.java similarity index 50% rename from declarative/processor/src/test/resources/good/graph unannotated method is default.java rename to processor/src/test/resources/validationExamples/good/graph unannotated method is default.java index 707e05b06..f54562193 100644 --- a/declarative/processor/src/test/resources/good/graph unannotated method is default.java +++ b/processor/src/test/resources/validationExamples/good/graph unannotated method is default.java @@ -1,6 +1,7 @@ +// This file is compiled only in test. package x; -import com.inrupt.rdf.wrapping.declarative.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.Graph; @Graph interface X { diff --git a/processor/src/test/resources/validationExamples/good/graph unannotated method is static.java b/processor/src/test/resources/validationExamples/good/graph unannotated method is static.java new file mode 100644 index 000000000..1ebaf8b87 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/graph unannotated method is static.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; + +@Graph +interface X { + static Object x() { + return null; + } +} diff --git a/processor/src/test/resources/validationExamples/good/resource extends Resource.java b/processor/src/test/resources/validationExamples/good/resource extends Resource.java new file mode 100644 index 000000000..0a2c822b8 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource extends Resource.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X extends org.apache.jena.rdf.model.Resource { +} diff --git a/processor/src/test/resources/validationExamples/good/resource extends nothing.java b/processor/src/test/resources/validationExamples/good/resource extends nothing.java new file mode 100644 index 000000000..77aba9b6e --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource extends nothing.java @@ -0,0 +1,8 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { +} diff --git a/declarative/processor/src/test/resources/good/resource unannotated method is default.java b/processor/src/test/resources/validationExamples/good/resource unannotated method is default.java similarity index 50% rename from declarative/processor/src/test/resources/good/resource unannotated method is default.java rename to processor/src/test/resources/validationExamples/good/resource unannotated method is default.java index ca1fdc834..1e6b5c847 100644 --- a/declarative/processor/src/test/resources/good/resource unannotated method is default.java +++ b/processor/src/test/resources/validationExamples/good/resource unannotated method is default.java @@ -1,6 +1,7 @@ +// This file is compiled only in test. package x; -import com.inrupt.rdf.wrapping.declarative.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { diff --git a/processor/src/test/resources/validationExamples/good/resource unannotated method is static.java b/processor/src/test/resources/validationExamples/good/resource unannotated method is static.java new file mode 100644 index 000000000..c14528838 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource unannotated method is static.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + static Object x() { + return null; + } +} From e12e53cb6737c07e8907231012f06e1b39882fd2 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 9 Sep 2023 11:54:36 +0100 Subject: [PATCH 042/141] Type-safe annotation handling --- .../processor/DatasetImplementor.java | 4 +- .../wrapping/processor/GraphImplementor.java | 4 +- .../rdf/wrapping/processor/Implementor.java | 38 +++++++++---------- .../rdf/wrapping/processor/Processor.java | 24 ++++++++---- .../processor/ResourceImplementor.java | 4 +- .../rdf/wrapping/processor/Validator.java | 21 +++++----- 6 files changed, 54 insertions(+), 41 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 09941bd4e..654bf9da5 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -30,7 +30,7 @@ import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.TypeElement; +import javax.lang.model.element.Element; import org.apache.jena.query.Dataset; import org.apache.jena.sparql.core.DatasetGraph; @@ -38,7 +38,7 @@ import org.jboss.jdeparser.*; class DatasetImplementor extends Implementor { - DatasetImplementor(final ProcessingEnvironment environment, final TypeElement element) { + DatasetImplementor(final ProcessingEnvironment environment, final Element element) { super(environment, element); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 01ee5da63..b483712b8 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -32,8 +32,8 @@ import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; @@ -41,7 +41,7 @@ import org.jboss.jdeparser.*; class GraphImplementor extends Implementor { - GraphImplementor(final ProcessingEnvironment environment, final TypeElement element) { + GraphImplementor(final ProcessingEnvironment environment, final Element element) { super(environment, element); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index ef16da50d..0ea154ed3 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -23,6 +23,10 @@ import static org.jboss.jdeparser.JMod.PUBLIC; import static org.jboss.jdeparser.JTypes.$t; +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.Resource; + import java.io.IOException; import java.lang.annotation.Annotation; import java.time.Instant; @@ -45,19 +49,19 @@ abstract class Implementor { protected static final String WRAP = "wrap"; protected final ProcessingEnvironment environment; - protected final TypeElement element; + protected final TypeElement type; protected final JSources sources; protected final String originalInterface; protected JSourceFile sourceFile; private final String implementationClass; - protected Implementor(final ProcessingEnvironment environment, final TypeElement element) { + protected Implementor(final ProcessingEnvironment environment, final Element element) { this.environment = environment; - this.element = element; + type = (TypeElement) element; - originalInterface = element.getQualifiedName().toString(); - final String originalBinaryName = environment.getElementUtils().getBinaryName(element).toString(); + originalInterface = type.getQualifiedName().toString(); + final String originalBinaryName = environment.getElementUtils().getBinaryName(type).toString(); final String qualifiedName = asImplementation(originalBinaryName); final int lastDot = originalBinaryName.lastIndexOf('.'); implementationClass = qualifiedName.substring(lastDot + 1); @@ -80,19 +84,15 @@ void implement() { protected abstract void implementInternal(); - static Implementor get(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { - - final TypeElement annotatedType = (TypeElement) element; - - switch (annotation.getQualifiedName().toString()) { - case "com.inrupt.rdf.wrapping.annotation.Dataset": - return new DatasetImplementor(env, annotatedType); - case "com.inrupt.rdf.wrapping.annotation.Graph": - return new GraphImplementor(env, annotatedType); - case "com.inrupt.rdf.wrapping.annotation.Resource": - return new ResourceImplementor(env, annotatedType); - default: - throw new RuntimeException("unknown annotation type"); + static Implementor get(final ProcessingEnvironment env, final Element element) { + if (element.getAnnotation(Dataset.class) != null) { + return new DatasetImplementor(env, element); + } else if (element.getAnnotation(Graph.class) != null) { + return new GraphImplementor(env, element); + } else if (element.getAnnotation(Resource.class) != null) { + return new ResourceImplementor(env, element); + } else { + throw new RuntimeException("unknown annotation type"); } } @@ -125,7 +125,7 @@ protected JClassDef createClass(final Class base) { protected final Stream membersAnnotatedWithAny( final Class... annotations) { - return ElementFilter.methodsIn(element.getEnclosedElements()).stream() + return ElementFilter.methodsIn(type.getEnclosedElements()).stream() .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC) && !method.getReturnType().equals($t(Void.class))) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java index c6a82f978..cc51f00b0 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java @@ -20,25 +20,35 @@ */ package com.inrupt.rdf.wrapping.processor; +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.Resource; + import java.util.ArrayList; +import java.util.HashSet; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; -@SupportedAnnotationTypes({ - "com.inrupt.rdf.wrapping.annotation.Dataset", - "com.inrupt.rdf.wrapping.annotation.Graph", - "com.inrupt.rdf.wrapping.annotation.Resource" -}) @SupportedSourceVersion(SourceVersion.RELEASE_8) public class Processor extends AbstractProcessor { + @Override + public Set getSupportedAnnotationTypes() { + final Set annotations = new HashSet<>(); + + annotations.add(Dataset.class.getName()); + annotations.add(Graph.class.getName()); + annotations.add(Resource.class.getName()); + + return annotations; + } + @Override public boolean process(final Set annotations, final RoundEnvironment roundEnv) { if (roundEnv.processingOver()) { @@ -50,7 +60,7 @@ public boolean process(final Set annotations, final Round final ArrayList validationErrors = new ArrayList<>(); for (final TypeElement annotation : annotations) { for (final Element annotatedElement : roundEnv.getElementsAnnotatedWith(annotation)) { - implementors.add(Implementor.get(annotation, processingEnv, annotatedElement)); + implementors.add(Implementor.get(processingEnv, annotatedElement)); validationErrors.addAll(Validator.get(annotation, processingEnv, annotatedElement).validate()); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 19a168eb9..87eab86c7 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -29,7 +29,7 @@ import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.TypeElement; +import javax.lang.model.element.Element; import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.enhanced.Implementation; @@ -41,7 +41,7 @@ class ResourceImplementor extends Implementor { static final String FACTORY = "factory"; - ResourceImplementor(final ProcessingEnvironment environment, final TypeElement element) { + ResourceImplementor(final ProcessingEnvironment environment, final Element element) { super(environment, element); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 3d790ea71..677e2af04 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -20,6 +20,10 @@ */ package com.inrupt.rdf.wrapping.processor; +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.Resource; + import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; @@ -47,15 +51,14 @@ protected Validator(final TypeElement annotation, final ProcessingEnvironment en } static Validator get(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { - switch (annotation.getQualifiedName().toString()) { - case "com.inrupt.rdf.wrapping.annotation.Dataset": - return new DatasetValidator(annotation, env, element); - case "com.inrupt.rdf.wrapping.annotation.Graph": - return new GraphValidator(annotation, env, element); - case "com.inrupt.rdf.wrapping.annotation.Resource": - return new ResourceValidator(annotation, env, element); - default: - throw new RuntimeException("unknown annotation type"); + if (element.getAnnotation(Dataset.class) != null) { + return new DatasetValidator(annotation, env, element); + } else if (element.getAnnotation(Graph.class) != null) { + return new GraphValidator(annotation, env, element); + } else if (element.getAnnotation(Resource.class) != null) { + return new ResourceValidator(annotation, env, element); + } else { + throw new RuntimeException("unknown annotation type"); } } From d7b1abd9cf2863a8560ea3730316b284e5c57a35 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 9 Sep 2023 11:54:50 +0100 Subject: [PATCH 043/141] Report processor coverage --- reports/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/reports/pom.xml b/reports/pom.xml index 8e5605bb7..2be12cb2b 100644 --- a/reports/pom.xml +++ b/reports/pom.xml @@ -37,6 +37,11 @@ inrupt-rdf-wrapping-test-rdf4j ${project.version} + + com.inrupt.rdf + inrupt-rdf-wrapping-processor + ${project.version} + From a700b104dc84e21c5692b77e412fb425f1b6f015 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 9 Sep 2023 15:24:48 +0100 Subject: [PATCH 044/141] Tidy dataset implementor --- .../processor/DatasetImplementor.java | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 654bf9da5..4c881416d 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -28,9 +28,13 @@ import com.inrupt.rdf.wrapping.annotation.DefaultGraph; import com.inrupt.rdf.wrapping.annotation.NamedGraph; +import java.lang.annotation.Annotation; +import java.util.function.BiFunction; + import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; import org.apache.jena.query.Dataset; import org.apache.jena.sparql.core.DatasetGraph; @@ -53,9 +57,9 @@ protected void implementInternal() { createWrapMethod(myClass, myType); - createDefaultGraphMethods(myClass); + createGraphMethods(myClass, DefaultGraph.class, DatasetImplementor::createDefaultGraphReturn); - createNamedGraphMethods(myClass); + createGraphMethods(myClass, NamedGraph.class, DatasetImplementor::createNamedGraphReturn); } private void addImports() { @@ -78,35 +82,27 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { myWrap.body()._return(myType._new().arg($v(ORIGINAL).call("asDatasetGraph"))); } - private void createDefaultGraphMethods(final JClassDef myClass) { - membersAnnotatedWithAny(DefaultGraph.class).forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final JType implementationType = asImplementation(method.getReturnType()); + private static JExpr createDefaultGraphReturn(final JType implementation, final ExecutableElement ignored) { + return implementation.call(WRAP).arg(THIS.call("getDefaultModel")); + } - final JMethodDef myMethod = myClass - .method(PUBLIC, returnType, method.getSimpleName().toString()); - myMethod.annotate(Override.class); - myMethod - .body() - ._return(implementationType.call(WRAP).arg(THIS.call("getDefaultModel"))); - }); + private static JExpr createNamedGraphReturn(final JType implementation, final ExecutableElement element) { + final JExpr graphName = JExprs.str(element.getAnnotation(NamedGraph.class).value()); + return implementation.call(WRAP).arg(THIS.call("getNamedModel").arg(graphName)); } - private void createNamedGraphMethods(final JClassDef myClass) { - membersAnnotatedWithAny(NamedGraph.class).forEach(method -> { + private void createGraphMethods( + final JClassDef myClass, + final Class annotation, + final BiFunction returnCreator) { + + membersAnnotatedWithAny(annotation).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = asImplementation(method.getReturnType()); + final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); - final JMethodDef myMethod = myClass - .method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); - myMethod - .body() - ._return(implementationType - .call(WRAP) - .arg(THIS - .call("getNamedModel") - .arg(JExprs.str(method.getAnnotation(NamedGraph.class).value())))); + myMethod.body()._return(returnCreator.apply(implementationType, method)); }); } } From 0123c9a834d35604ff7ca0326b1153bff240a85b Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Fri, 29 Sep 2023 18:58:00 +0100 Subject: [PATCH 045/141] Tidy graph implementor --- .../wrapping/processor/GraphImplementor.java | 83 +++++++------------ 1 file changed, 31 insertions(+), 52 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index b483712b8..42aa0ea7f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -30,6 +30,9 @@ import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; import com.inrupt.rdf.wrapping.jena.WrapperModel; +import java.lang.annotation.Annotation; +import java.util.function.Function; + import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; @@ -58,11 +61,26 @@ protected void implementInternal() { createWrapMethod(myClass, myType); - createOptionalFirstInstanceOfEitherMethods(myClass); - - createOptionalFirstSubjectOfEitherMethods(myClass); + createMethods( + myClass, + OptionalFirstInstanceOfEither.class, + "optionalFirstInstanceOfEither", + m -> m.getAnnotation(OptionalFirstInstanceOfEither.class).value() + ); - createOptionalFirstObjectOfEitherMethods(myClass); + createMethods( + myClass, + OptionalFirstSubjectOfEither.class, + "optionalFirstSubjectOfEither", + m -> m.getAnnotation(OptionalFirstSubjectOfEither.class).value() + ); + + createMethods( + myClass, + OptionalFirstObjectOfEither.class, + "optionalFirstObjectOfEither", + m -> m.getAnnotation(OptionalFirstObjectOfEither.class).value() + ); } private void addImports() { @@ -106,52 +124,13 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { myWrap.body()._return(myType._new().arg($v(ORIGINAL).call("getGraph"))); } - private void createOptionalFirstInstanceOfEitherMethods(final JClassDef myClass) { - membersAnnotatedWithAny(OptionalFirstInstanceOfEither.class).forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final JType implementationType = asImplementation(method.getReturnType()); - - final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); - myMethod.annotate(Override.class); - - // Call model wrapper convenience method passing projection class argument - final JCall wrapperConvenienceCall = THIS - .call("optionalFirstInstanceOfEither") - .arg(implementationType._class()); - - // Pass each filter class value from the annotation as additional argument - for (final String s : method.getAnnotation(OptionalFirstInstanceOfEither.class).value()) { - wrapperConvenienceCall.arg(JExprs.str(s)); - } - - myMethod.body()._return(wrapperConvenienceCall); - }); - } - - private void createOptionalFirstSubjectOfEitherMethods(final JClassDef myClass) { - membersAnnotatedWithAny(OptionalFirstSubjectOfEither.class).forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final JType implementationType = asImplementation(method.getReturnType()); - - final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); - myMethod.annotate(Override.class); - - // Call model wrapper convenience method passing projection class argument - final JCall wrapperConvenienceCall = THIS - .call("optionalFirstSubjectOfEither") - .arg(implementationType._class()); - - // Pass each filter predicate value from the annotation as additional argument - for (final String s : method.getAnnotation(OptionalFirstSubjectOfEither.class).value()) { - wrapperConvenienceCall.arg(JExprs.str(s)); - } - - myMethod.body()._return(wrapperConvenienceCall); - }); - } + private void createMethods( + final JClassDef myClass, + final Class annotation, + final String convenienceMethod, + final Function annotationValueExtractor) { - private void createOptionalFirstObjectOfEitherMethods(final JClassDef myClass) { - membersAnnotatedWithAny(OptionalFirstObjectOfEither.class).forEach(method -> { + membersAnnotatedWithAny(annotation).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); final JType implementationType = asImplementation(method.getReturnType()); @@ -160,11 +139,11 @@ private void createOptionalFirstObjectOfEitherMethods(final JClassDef myClass) { // Call model wrapper convenience method passing projection class argument final JCall wrapperConvenienceCall = THIS - .call("optionalFirstObjectOfEither") + .call(convenienceMethod) .arg(implementationType._class()); - // Pass each filter predicate value from the annotation as additional argument - for (final String s : method.getAnnotation(OptionalFirstObjectOfEither.class).value()) { + // Pass each filter value from the annotation as additional argument + for (final String s : annotationValueExtractor.apply(method)) { wrapperConvenienceCall.arg(JExprs.str(s)); } From 5f54a0f3d8daf3c193f1bc0564d970a8e6ea218a Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Fri, 29 Sep 2023 20:28:16 +0100 Subject: [PATCH 046/141] Validate graph methods return resources --- .../wrapping/processor/GraphValidator.java | 25 ++++++++++++++++++- .../rdf/wrapping/processor/Validator.java | 12 ++++++--- .../rdf/wrapping/processor/ValidatorTest.java | 10 +++++--- ...ph instance of method is not resource.java | 11 ++++++++ ...raph object of method is not resource.java | 11 ++++++++ ...aph subject of method is not resource.java | 11 ++++++++ ...tance of method is resource instance.java} | 0 ...bject of method is resource instance.java} | 0 ...bject of method is resource instance.java} | 0 9 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/bad/graph instance of method is not resource.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph object of method is not resource.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph subject of method is not resource.java rename processor/src/test/resources/validationExamples/good/{graph instance of method is instance.java => graph instance of method is resource instance.java} (100%) rename processor/src/test/resources/validationExamples/good/{graph object of method is instance.java => graph object of method is resource instance.java} (100%) rename processor/src/test/resources/validationExamples/good/{graph subject of method is instance.java => graph subject of method is resource instance.java} (100%) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java index 99e73d856..4fa30a68d 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java @@ -23,9 +23,14 @@ import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; +import com.inrupt.rdf.wrapping.annotation.Resource; + +import java.lang.annotation.Annotation; +import java.util.function.Predicate; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import org.apache.jena.rdf.model.Model; @@ -50,6 +55,24 @@ protected void validateInternal() { OptionalFirstObjectOfEither.class, OptionalFirstSubjectOfEither.class); - // TODO: Validate that member return type is annotated with @Resource + requireResourceMethods(OptionalFirstInstanceOfEither.class); + requireResourceMethods(OptionalFirstObjectOfEither.class); + requireResourceMethods(OptionalFirstSubjectOfEither.class); + } + + protected void requireResourceMethods(final Class annotation) { + final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; + final Predicate isNotResource = method -> + env.getTypeUtils().asElement(method.getReturnType()).getAnnotation(Resource.class) == null; + + getMethods() + .filter(isAnnotated) + .filter(isNotResource) + .forEach(method -> errors.add(new ValidationError( + method, + "Method %s on interface %s annotated with @%s must return resource interface", + method.getSimpleName(), + element.getSimpleName(), + annotation.getSimpleName()))); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 677e2af04..8d501e584 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -20,6 +20,8 @@ */ package com.inrupt.rdf.wrapping.processor; +import static javax.lang.model.util.ElementFilter.methodsIn; + import com.inrupt.rdf.wrapping.annotation.Dataset; import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.Resource; @@ -29,6 +31,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.function.Predicate; +import java.util.stream.Stream; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; @@ -36,7 +39,6 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; abstract class Validator { protected final TypeElement annotation; @@ -76,7 +78,7 @@ protected void requireMemberMethods(final Class annotation final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; - ElementFilter.methodsIn(element.getEnclosedElements()).stream() + getMethods() .filter(isNotMember) .filter(isAnnotated) .forEach(method -> errors.add(new ValidationError( @@ -95,7 +97,7 @@ protected final void requireNonMemberMethods(final Class.. final Predicate isUnannotated = method -> Arrays.stream(annotations).noneMatch(a -> method.getAnnotation(a) != null); - ElementFilter.methodsIn(element.getEnclosedElements()).stream() + getMethods() .filter(isMember) .filter(isUnannotated) .forEach(method -> errors.add(new ValidationError( @@ -139,4 +141,8 @@ protected void requireInterface() { annotation.getSimpleName(), element.getKind())); } + + protected Stream getMethods() { + return methodsIn(element.getEnclosedElements()).stream(); + } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index ed5e302a5..5b3b17962 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -42,6 +42,7 @@ class ValidatorTest { private static final String MUST_BE_AN_INTERFACE = "must be an interface"; private static final String CANNOT_BE_STATIC_OR_DEFAULT = "cannot be static or default"; private static final String MUST_BE_STATIC_OR_DEFAULT = "must be static or default"; + private static final String MUST_RETURN_RESOURCE_INTERFACE = "must return resource interface"; private Compiler compiler; @@ -74,10 +75,13 @@ private static Stream compilationErrorOnInvalid() { arguments("graph extends unacceptable", "can only extend org.apache.jena.rdf.model.Model"), arguments("graph instance of method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("graph instance of method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph instance of method is not resource", MUST_RETURN_RESOURCE_INTERFACE), arguments("graph object of method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("graph object of method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph object of method is not resource", MUST_RETURN_RESOURCE_INTERFACE), arguments("graph subject of method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("graph subject of method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph subject of method is not resource", MUST_RETURN_RESOURCE_INTERFACE), arguments("graph instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), arguments("resource is not an interface", MUST_BE_AN_INTERFACE), @@ -109,9 +113,9 @@ private static Stream compilationSucceeds() { arguments("graph extends nothing"), arguments("graph extends Model"), - arguments("graph instance of method is instance"), - arguments("graph subject of method is instance"), - arguments("graph object of method is instance"), + arguments("graph instance of method is resource instance"), + arguments("graph subject of method is resource instance"), + arguments("graph object of method is resource instance"), arguments("graph unannotated method is static"), arguments("graph unannotated method is default"), diff --git a/processor/src/test/resources/validationExamples/bad/graph instance of method is not resource.java b/processor/src/test/resources/validationExamples/bad/graph instance of method is not resource.java new file mode 100644 index 000000000..ea7bdcb48 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph instance of method is not resource.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; + +@Graph +interface X { + @OptionalFirstInstanceOfEither("x") + Object x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/graph object of method is not resource.java b/processor/src/test/resources/validationExamples/bad/graph object of method is not resource.java new file mode 100644 index 000000000..32963630c --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph object of method is not resource.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; + +@Graph +interface X { + @OptionalFirstObjectOfEither("x") + Object x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/graph subject of method is not resource.java b/processor/src/test/resources/validationExamples/bad/graph subject of method is not resource.java new file mode 100644 index 000000000..a5a2e94d9 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph subject of method is not resource.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; + +@Graph +interface X { + @OptionalFirstSubjectOfEither("x") + Object x(); +} diff --git a/processor/src/test/resources/validationExamples/good/graph instance of method is instance.java b/processor/src/test/resources/validationExamples/good/graph instance of method is resource instance.java similarity index 100% rename from processor/src/test/resources/validationExamples/good/graph instance of method is instance.java rename to processor/src/test/resources/validationExamples/good/graph instance of method is resource instance.java diff --git a/processor/src/test/resources/validationExamples/good/graph object of method is instance.java b/processor/src/test/resources/validationExamples/good/graph object of method is resource instance.java similarity index 100% rename from processor/src/test/resources/validationExamples/good/graph object of method is instance.java rename to processor/src/test/resources/validationExamples/good/graph object of method is resource instance.java diff --git a/processor/src/test/resources/validationExamples/good/graph subject of method is instance.java b/processor/src/test/resources/validationExamples/good/graph subject of method is resource instance.java similarity index 100% rename from processor/src/test/resources/validationExamples/good/graph subject of method is instance.java rename to processor/src/test/resources/validationExamples/good/graph subject of method is resource instance.java From 4437633749fd00def26bc32559b7ea137c334dad Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Fri, 29 Sep 2023 20:56:24 +0100 Subject: [PATCH 047/141] Validate dataset methods return graphs --- .../wrapping/processor/DatasetValidator.java | 25 ++++++++++++++++++- .../rdf/wrapping/processor/ValidatorTest.java | 7 ++++-- ...set default graph method is not graph.java | 11 ++++++++ ...taset named graph method is not graph.java | 11 ++++++++ ...fault graph method is graph instance.java} | 0 ...named graph method is graph instance.java} | 0 6 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/bad/dataset default graph method is not graph.java create mode 100644 processor/src/test/resources/validationExamples/bad/dataset named graph method is not graph.java rename processor/src/test/resources/validationExamples/good/{dataset default graph method is instance.java => dataset default graph method is graph instance.java} (100%) rename processor/src/test/resources/validationExamples/good/{dataset named graph method is instance.java => dataset named graph method is graph instance.java} (100%) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java index b3ea97f14..91e78239b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java @@ -21,10 +21,15 @@ package com.inrupt.rdf.wrapping.processor; import com.inrupt.rdf.wrapping.annotation.DefaultGraph; +import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.NamedGraph; +import java.lang.annotation.Annotation; +import java.util.function.Predicate; + import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import org.apache.jena.query.Dataset; @@ -45,6 +50,24 @@ protected void validateInternal() { requireNonMemberMethods(DefaultGraph.class, NamedGraph.class); - // TODO: Validate that member return type is annotated with @Graph + requireGraphMethods(DefaultGraph.class); + requireGraphMethods(NamedGraph.class); + } + + + protected void requireGraphMethods(final Class annotation) { + final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; + final Predicate isNotResource = method -> + env.getTypeUtils().asElement(method.getReturnType()).getAnnotation(Graph.class) == null; + + getMethods() + .filter(isAnnotated) + .filter(isNotResource) + .forEach(method -> errors.add(new ValidationError( + method, + "Method %s on interface %s annotated with @%s must return graph interface", + method.getSimpleName(), + element.getSimpleName(), + annotation.getSimpleName()))); } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 5b3b17962..dd22ca4c7 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -43,6 +43,7 @@ class ValidatorTest { private static final String CANNOT_BE_STATIC_OR_DEFAULT = "cannot be static or default"; private static final String MUST_BE_STATIC_OR_DEFAULT = "must be static or default"; private static final String MUST_RETURN_RESOURCE_INTERFACE = "must return resource interface"; + private static final String MUST_RETURN_GRAPH_INTERFACE = "must return graph interface"; private Compiler compiler; @@ -67,8 +68,10 @@ private static Stream compilationErrorOnInvalid() { arguments("dataset extends unacceptable", "can only extend org.apache.jena.query.Dataset"), arguments("dataset default graph method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("dataset default graph method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("dataset default graph method is not graph", MUST_RETURN_GRAPH_INTERFACE), arguments("dataset named graph method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("dataset named graph method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("dataset named graph method is not graph", MUST_RETURN_GRAPH_INTERFACE), arguments("dataset instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), arguments("graph is not an interface", MUST_BE_AN_INTERFACE), @@ -106,8 +109,8 @@ private static Stream compilationSucceeds() { return Stream.of( arguments("dataset extends nothing"), arguments("dataset extends Dataset"), - arguments("dataset default graph method is instance"), - arguments("dataset named graph method is instance"), + arguments("dataset default graph method is graph instance"), + arguments("dataset named graph method is graph instance"), arguments("dataset unannotated method is static"), arguments("dataset unannotated method is default"), diff --git a/processor/src/test/resources/validationExamples/bad/dataset default graph method is not graph.java b/processor/src/test/resources/validationExamples/bad/dataset default graph method is not graph.java new file mode 100644 index 000000000..8170e7ac2 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset default graph method is not graph.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.DefaultGraph; + +@Dataset +interface X { + @DefaultGraph + Object x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/dataset named graph method is not graph.java b/processor/src/test/resources/validationExamples/bad/dataset named graph method is not graph.java new file mode 100644 index 000000000..5acbdc370 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset named graph method is not graph.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.NamedGraph; + +@Dataset +interface X { + @NamedGraph("x") + Object x(); +} diff --git a/processor/src/test/resources/validationExamples/good/dataset default graph method is instance.java b/processor/src/test/resources/validationExamples/good/dataset default graph method is graph instance.java similarity index 100% rename from processor/src/test/resources/validationExamples/good/dataset default graph method is instance.java rename to processor/src/test/resources/validationExamples/good/dataset default graph method is graph instance.java diff --git a/processor/src/test/resources/validationExamples/good/dataset named graph method is instance.java b/processor/src/test/resources/validationExamples/good/dataset named graph method is graph instance.java similarity index 100% rename from processor/src/test/resources/validationExamples/good/dataset named graph method is instance.java rename to processor/src/test/resources/validationExamples/good/dataset named graph method is graph instance.java From 815c162482f5bfd506c77470238cd5e1dd8b465f Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Fri, 29 Sep 2023 21:26:15 +0100 Subject: [PATCH 048/141] Tidy validators --- .../wrapping/processor/DatasetValidator.java | 25 ++---------------- .../wrapping/processor/GraphValidator.java | 26 +++---------------- .../rdf/wrapping/processor/Validator.java | 20 ++++++++++++++ .../rdf/wrapping/processor/ValidatorTest.java | 4 +-- 4 files changed, 27 insertions(+), 48 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java index 91e78239b..fbea0c56b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java @@ -24,12 +24,8 @@ import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.NamedGraph; -import java.lang.annotation.Annotation; -import java.util.function.Predicate; - import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import org.apache.jena.query.Dataset; @@ -50,24 +46,7 @@ protected void validateInternal() { requireNonMemberMethods(DefaultGraph.class, NamedGraph.class); - requireGraphMethods(DefaultGraph.class); - requireGraphMethods(NamedGraph.class); - } - - - protected void requireGraphMethods(final Class annotation) { - final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; - final Predicate isNotResource = method -> - env.getTypeUtils().asElement(method.getReturnType()).getAnnotation(Graph.class) == null; - - getMethods() - .filter(isAnnotated) - .filter(isNotResource) - .forEach(method -> errors.add(new ValidationError( - method, - "Method %s on interface %s annotated with @%s must return graph interface", - method.getSimpleName(), - element.getSimpleName(), - annotation.getSimpleName()))); + requireAnnotatedReturnType(DefaultGraph.class, Graph.class); + requireAnnotatedReturnType(NamedGraph.class, Graph.class); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java index 4fa30a68d..0f8ff329a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java @@ -25,12 +25,8 @@ import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; import com.inrupt.rdf.wrapping.annotation.Resource; -import java.lang.annotation.Annotation; -import java.util.function.Predicate; - import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import org.apache.jena.rdf.model.Model; @@ -55,24 +51,8 @@ protected void validateInternal() { OptionalFirstObjectOfEither.class, OptionalFirstSubjectOfEither.class); - requireResourceMethods(OptionalFirstInstanceOfEither.class); - requireResourceMethods(OptionalFirstObjectOfEither.class); - requireResourceMethods(OptionalFirstSubjectOfEither.class); - } - - protected void requireResourceMethods(final Class annotation) { - final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; - final Predicate isNotResource = method -> - env.getTypeUtils().asElement(method.getReturnType()).getAnnotation(Resource.class) == null; - - getMethods() - .filter(isAnnotated) - .filter(isNotResource) - .forEach(method -> errors.add(new ValidationError( - method, - "Method %s on interface %s annotated with @%s must return resource interface", - method.getSimpleName(), - element.getSimpleName(), - annotation.getSimpleName()))); + requireAnnotatedReturnType(OptionalFirstInstanceOfEither.class, Resource.class); + requireAnnotatedReturnType(OptionalFirstObjectOfEither.class, Resource.class); + requireAnnotatedReturnType(OptionalFirstSubjectOfEither.class, Resource.class); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 8d501e584..e6c5bf82a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -142,6 +142,26 @@ protected void requireInterface() { element.getKind())); } + protected void requireAnnotatedReturnType( + final Class annotation, + final Class required) { + + final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; + final Predicate isNotResource = method -> + env.getTypeUtils().asElement(method.getReturnType()).getAnnotation(required) == null; + + getMethods() + .filter(isAnnotated) + .filter(isNotResource) + .forEach(method -> errors.add(new ValidationError( + method, + "Method %s on interface %s annotated with @%s must return @%s interface", + method.getSimpleName(), + element.getSimpleName(), + annotation.getSimpleName(), + required.getSimpleName()))); + } + protected Stream getMethods() { return methodsIn(element.getEnclosedElements()).stream(); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index dd22ca4c7..030b2d31c 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -42,8 +42,8 @@ class ValidatorTest { private static final String MUST_BE_AN_INTERFACE = "must be an interface"; private static final String CANNOT_BE_STATIC_OR_DEFAULT = "cannot be static or default"; private static final String MUST_BE_STATIC_OR_DEFAULT = "must be static or default"; - private static final String MUST_RETURN_RESOURCE_INTERFACE = "must return resource interface"; - private static final String MUST_RETURN_GRAPH_INTERFACE = "must return graph interface"; + private static final String MUST_RETURN_RESOURCE_INTERFACE = "must return @Resource interface"; + private static final String MUST_RETURN_GRAPH_INTERFACE = "must return @Graph interface"; private Compiler compiler; From 9bcbd88e6512d3732db5d6ea6bb403a9dbac20d9 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 30 Sep 2023 09:42:01 +0100 Subject: [PATCH 049/141] Reminder --- .../com/inrupt/rdf/wrapping/processor/GraphImplementor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 42aa0ea7f..eba22794f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -57,7 +57,7 @@ protected void implementInternal() { final JMethodDef myConstructor = createConstructor(myClass); - addImplementationsToPersonality(myConstructor); + addImplementationsToPersonality(myConstructor); // TODO: Also add return types of properties of resources createWrapMethod(myClass, myType); From 828e25726ac940777e98006b4cadf52192c82054 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 30 Sep 2023 11:11:34 +0100 Subject: [PATCH 050/141] Initial property in resource implementor --- .../rdf/wrapping/annotation/Property.java | 1 + .../processor/ResourceImplementor.java | 36 ++++++++++++++++--- .../rdf/wrapping/processor/ValidatorTest.java | 2 +- .../com/inrupt/rdf/wrapping/processor/X.java | 2 ++ .../inrupt/rdf/wrapping/processor/XTest.java | 16 +++++++++ .../resource property method is default.java | 2 +- .../resource property method is static.java | 2 +- .../resource property method is instance.java | 11 ++++++ 8 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/good/resource property method is instance.java diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java index 6c821daf0..454ac2f0a 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java @@ -31,4 +31,5 @@ @Retention(SOURCE) @Documented public @interface Property { + String value(); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 87eab86c7..24827b338 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -20,11 +20,15 @@ */ package com.inrupt.rdf.wrapping.processor; +import static org.jboss.jdeparser.JExpr.THIS; import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JExprs.str; import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; +import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; +import com.inrupt.rdf.wrapping.jena.ValueMappings; import com.inrupt.rdf.wrapping.jena.WrapperResource; import javax.annotation.Generated; @@ -34,9 +38,7 @@ import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.enhanced.Implementation; import org.apache.jena.graph.Node; -import org.jboss.jdeparser.JClassDef; -import org.jboss.jdeparser.JMethodDef; -import org.jboss.jdeparser.JType; +import org.jboss.jdeparser.*; class ResourceImplementor extends Implementor { static final String FACTORY = "factory"; @@ -55,6 +57,8 @@ protected void implementInternal() { createFactoryField(myClass, myType); createConstructor(myClass); + + createPropertyMethod(myClass); } private void addImports() { @@ -64,7 +68,8 @@ private void addImports() { ._import(Generated.class) ._import(EnhGraph.class) ._import(Implementation.class) - ._import(Node.class); + ._import(Node.class) + ._import(ValueMappings.class); } private static void createFactoryField(final JClassDef myClass, final JType myType) { @@ -81,4 +86,27 @@ private static void createConstructor(final JClassDef myClass) { myConstructor.param(FINAL, EnhGraph.class, "graph"); myConstructor.body().callSuper().arg($v("node")).arg($v("graph")); } + + private void createPropertyMethod(final JClassDef myClass) { + membersAnnotatedWithAny(Property.class).forEach(method -> { + final JType returnType = JTypes.typeOf(method.getReturnType()); + + final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); + myMethod.annotate(Override.class); + + final JExpr mapping = $t(ValueMappings.class).methodRef("iriAsString"); // TODO: Dynamic mapping + final String predicateFromAnnotation = method.getAnnotation(Property.class).value(); + final JCall predicate = THIS + .call("getModel") + .call("createProperty") + .arg(str(predicateFromAnnotation)); + + myMethod.body()._return( + THIS + .call("anyOrNull") // TODO: Dynamic cardniality + .arg(predicate) + .arg(mapping)); + }); + + } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 030b2d31c..7f52dbd7a 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -124,7 +124,7 @@ private static Stream compilationSucceeds() { arguments("resource extends nothing"), arguments("resource extends Resource"), - // arguments("resource property method is instance"), + arguments("resource property method is instance"), arguments("resource unannotated method is static"), arguments("resource unannotated method is default") diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java index 44a398dfe..a1b30a5c5 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java @@ -53,6 +53,8 @@ static Y wrap(final Model original) { @Resource interface Z { + @Property("urn:example:p") + String getProperty(); } } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java index e776daf9f..2b5bed986 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java @@ -87,6 +87,19 @@ void graphCanGetFirstObjectOf() { assertDoesNotThrow(y::getResource3); } + @Test + void resourceCanGetProperty() { + final Model model = modelFrom("PREFIX : \n" + + "\n" + + "[\n" + + " a :C ;\n" + + "] .\n"); + final X.Y y = X.Y.wrap(model); + final X.Y.Z z = y.getResource(); + + assertDoesNotThrow(z::getProperty); + } + @Test void e2e() { final Dataset dataset = datasetFrom("PREFIX : \n" + @@ -94,6 +107,7 @@ void e2e() { "GRAPH {\n" + " [\n" + " a :C ;\n" + + " :p :VALUE ;\n" + " ] .\n" + "\n" + " [ :p [] ] .\n" + @@ -104,10 +118,12 @@ void e2e() { final X.Y.Z z = y.getResource(); final X.Y.Z z2 = y.getResource2(); final X.Y.Z z3 = y.getResource3(); + final String p = z.getProperty(); System.out.println(z); System.out.println(z2); System.out.println(z3); + System.out.println(p); } private static Dataset datasetFrom(final String rdf) { diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is default.java b/processor/src/test/resources/validationExamples/bad/resource property method is default.java index 39e70dd34..7e3750aad 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is default.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is default.java @@ -6,7 +6,7 @@ @Resource interface X { - @Property + @Property("x") default Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is static.java b/processor/src/test/resources/validationExamples/bad/resource property method is static.java index 39e70dd34..7e3750aad 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is static.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is static.java @@ -6,7 +6,7 @@ @Resource interface X { - @Property + @Property("x") default Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/good/resource property method is instance.java b/processor/src/test/resources/validationExamples/good/resource property method is instance.java new file mode 100644 index 000000000..3fdaa66f9 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource property method is instance.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + @Property("x") + Object x(); +} From 7fd4b64497cc903c05838b11652768c17ae61d12 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 30 Sep 2023 11:11:50 +0100 Subject: [PATCH 051/141] Tidy --- .../test/java/com/inrupt/rdf/wrapping/processor/XTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java index 2b5bed986..28d589720 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java @@ -31,7 +31,6 @@ import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFDataMgr; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class XTest { @@ -39,7 +38,7 @@ class XTest { void datasetCanWrap() { final Dataset dataset = DatasetFactory.create(); - Assertions.assertDoesNotThrow(() -> X.wrap(dataset)); + assertDoesNotThrow(() -> X.wrap(dataset)); } @Test @@ -60,7 +59,7 @@ void datasetCanGetNamedGraph() { void graphCanWrap() { final Model model = ModelFactory.createDefaultModel(); - Assertions.assertDoesNotThrow(() -> X.Y.wrap(model)); + assertDoesNotThrow(() -> X.Y.wrap(model)); } @Test From 8e9237656646052fc9599f5404c420371c387748 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 1 Oct 2023 14:02:14 +0100 Subject: [PATCH 052/141] Support dynamic property mapping --- .../rdf/wrapping/annotation/Property.java | 19 ++++++++++++++++++- .../processor/ResourceImplementor.java | 9 +++++---- .../com/inrupt/rdf/wrapping/processor/X.java | 10 +++++++++- .../inrupt/rdf/wrapping/processor/XTest.java | 4 ++++ .../resource property method is default.java | 4 +++- .../resource property method is static.java | 4 +++- .../resource property method is instance.java | 4 +++- 7 files changed, 45 insertions(+), 9 deletions(-) diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java index 454ac2f0a..056b775db 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java @@ -31,5 +31,22 @@ @Retention(SOURCE) @Documented public @interface Property { - String value(); + String predicate(); + + Mapping mapping(); + + enum Mapping { + IRI_AS_STRING("iriAsString"), + IRI_AS_URI("iriAsUri"); + + private final String methodName; + + Mapping(final String methodName) { + this.methodName = methodName; + } + + public String getMethodName() { + return methodName; + } + } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 24827b338..76292be51 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -58,7 +58,7 @@ protected void implementInternal() { createConstructor(myClass); - createPropertyMethod(myClass); + createPropertyMethods(myClass); } private void addImports() { @@ -87,15 +87,16 @@ private static void createConstructor(final JClassDef myClass) { myConstructor.body().callSuper().arg($v("node")).arg($v("graph")); } - private void createPropertyMethod(final JClassDef myClass) { + private void createPropertyMethods(final JClassDef myClass) { membersAnnotatedWithAny(Property.class).forEach(method -> { final JType returnType = JTypes.typeOf(method.getReturnType()); final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); - final JExpr mapping = $t(ValueMappings.class).methodRef("iriAsString"); // TODO: Dynamic mapping - final String predicateFromAnnotation = method.getAnnotation(Property.class).value(); + final String methodName = method.getAnnotation(Property.class).mapping().getMethodName(); + final JExpr mapping = $t(ValueMappings.class).methodRef(methodName); // TODO: Validate return types match + final String predicateFromAnnotation = method.getAnnotation(Property.class).predicate(); final JCall predicate = THIS .call("getModel") .call("createProperty") diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java index a1b30a5c5..b3b1d9554 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java @@ -20,8 +20,13 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_URI; + import com.inrupt.rdf.wrapping.annotation.*; +import java.net.URI; + import org.apache.jena.rdf.model.Model; @Dataset @@ -53,8 +58,11 @@ static Y wrap(final Model original) { @Resource interface Z { - @Property("urn:example:p") + @Property(predicate = "urn:example:p", mapping = IRI_AS_STRING) String getProperty(); + + @Property(predicate = "urn:example:p", mapping = IRI_AS_URI) + URI getProperty2(); } } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java index 28d589720..7895e4e95 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java @@ -24,6 +24,8 @@ import com.github.jsonldjava.shaded.com.google.common.base.Charsets; +import java.net.URI; + import org.apache.commons.io.IOUtils; import org.apache.jena.query.Dataset; import org.apache.jena.query.DatasetFactory; @@ -118,11 +120,13 @@ void e2e() { final X.Y.Z z2 = y.getResource2(); final X.Y.Z z3 = y.getResource3(); final String p = z.getProperty(); + final URI p2 = z.getProperty2(); System.out.println(z); System.out.println(z2); System.out.println(z3); System.out.println(p); + System.out.println(p2); } private static Dataset datasetFrom(final String rdf) { diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is default.java b/processor/src/test/resources/validationExamples/bad/resource property method is default.java index 7e3750aad..edade6193 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is default.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is default.java @@ -1,12 +1,14 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; + import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property("x") + @Property(predicate = "x", mapping = IRI_AS_STRING) default Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is static.java b/processor/src/test/resources/validationExamples/bad/resource property method is static.java index 7e3750aad..edade6193 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is static.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is static.java @@ -1,12 +1,14 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; + import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property("x") + @Property(predicate = "x", mapping = IRI_AS_STRING) default Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/good/resource property method is instance.java b/processor/src/test/resources/validationExamples/good/resource property method is instance.java index 3fdaa66f9..8f0f40c09 100644 --- a/processor/src/test/resources/validationExamples/good/resource property method is instance.java +++ b/processor/src/test/resources/validationExamples/good/resource property method is instance.java @@ -1,11 +1,13 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; + import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property("x") + @Property(predicate = "x", mapping = IRI_AS_STRING) Object x(); } From 951996f8ae08497065c5a46f14120cbdffd1638f Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 1 Oct 2023 15:36:59 +0100 Subject: [PATCH 053/141] Validate resource property return matches mapper --- .../processor/ResourceImplementor.java | 2 +- .../wrapping/processor/ResourceValidator.java | 39 +++++++++++++++++++ .../rdf/wrapping/processor/ValidatorTest.java | 5 ++- ...rty method return type not assignable.java | 13 +++++++ ...operty method is assignable instance.java} | 0 5 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java rename processor/src/test/resources/validationExamples/good/{resource property method is instance.java => resource property method is assignable instance.java} (100%) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 76292be51..2d24189c0 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -95,7 +95,7 @@ private void createPropertyMethods(final JClassDef myClass) { myMethod.annotate(Override.class); final String methodName = method.getAnnotation(Property.class).mapping().getMethodName(); - final JExpr mapping = $t(ValueMappings.class).methodRef(methodName); // TODO: Validate return types match + final JExpr mapping = $t(ValueMappings.class).methodRef(methodName); final String predicateFromAnnotation = method.getAnnotation(Property.class).predicate(); final JCall predicate = THIS .call("getModel") diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 1143bcc72..ceaa97c28 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -20,11 +20,16 @@ */ package com.inrupt.rdf.wrapping.processor; +import static javax.lang.model.util.ElementFilter.methodsIn; + import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.jena.ValueMappings; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; import org.apache.jena.rdf.model.Resource; @@ -42,5 +47,39 @@ protected void validateInternal() { requireMemberMethods(Property.class); requireNonMemberMethods(Property.class); + + requireCompatibleReturnType(); + } + + private void requireCompatibleReturnType() { + for (final ExecutableElement method : methodsIn(element.getEnclosedElements())) { + final Property propertyAnnotation = method.getAnnotation(Property.class); + if (propertyAnnotation != null) { + final String mappingMethod = propertyAnnotation.mapping().getMethodName(); + final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); + + if (!env.getTypeUtils().isAssignable(mappingMethodReturnType, method.getReturnType())) { + errors.add(new ValidationError( + method, + "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", + method.getReturnType(), + method.getSimpleName(), + mappingMethodReturnType, + mappingMethod)); + } + } + } + } + + private TypeMirror returnTypeOfMapper(final String mappingMethod) { + final TypeElement valueMappings = env.getElementUtils().getTypeElement(ValueMappings.class.getCanonicalName()); + + for (final ExecutableElement m : methodsIn(valueMappings.getEnclosedElements())) { + if (m.getSimpleName().contentEquals(mappingMethod)) { + return m.getReturnType(); + } + } + + return null; } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 7f52dbd7a..682e18af8 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -91,7 +91,8 @@ private static Stream compilationErrorOnInvalid() { arguments("resource extends unacceptable", "can only extend org.apache.jena.rdf.model.Resource"), arguments("resource property method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("resource property method is default", CANNOT_BE_STATIC_OR_DEFAULT), - arguments("resource instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT) + arguments("resource instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), + arguments("resource property method return type not assignable", "must be assignable from return type") ); } @@ -124,7 +125,7 @@ private static Stream compilationSucceeds() { arguments("resource extends nothing"), arguments("resource extends Resource"), - arguments("resource property method is instance"), + arguments("resource property method is assignable instance"), arguments("resource unannotated method is static"), arguments("resource unannotated method is default") diff --git a/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java b/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java new file mode 100644 index 000000000..bf0f8774f --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + @Property(predicate = "x", mapping = IRI_AS_STRING) + int x(); +} diff --git a/processor/src/test/resources/validationExamples/good/resource property method is instance.java b/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java similarity index 100% rename from processor/src/test/resources/validationExamples/good/resource property method is instance.java rename to processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java From b152bc4ff3b76da892478b4d915a972e77cb8aba Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 8 Oct 2023 15:16:20 +0100 Subject: [PATCH 054/141] Extract a processing environment helper --- .../wrapping/processor/EnvironmentHelper.java | 88 +++++++++++++++++++ .../rdf/wrapping/processor/Implementor.java | 11 ++- .../processor/ResourceImplementor.java | 5 +- .../wrapping/processor/ResourceValidator.java | 8 +- .../rdf/wrapping/processor/Validator.java | 15 ++-- 5 files changed, 103 insertions(+), 24 deletions(-) create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java new file mode 100644 index 000000000..be5523fdc --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java @@ -0,0 +1,88 @@ +package com.inrupt.rdf.wrapping.processor; + +import com.inrupt.rdf.wrapping.jena.ValueMappings; + +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; + +class EnvironmentHelper implements ProcessingEnvironment { + TypeMirror mirror(final Class clazz) { + return type(clazz).asType(); + } + + TypeElement type(final Class clazz) { + return getElementUtils().getTypeElement(clazz.getCanonicalName()); + } + + boolean isVoid(final TypeMirror type) { + return isSameType(type, Void.class); + } + + boolean isSameType(final TypeMirror t1, final Class t2) { + return getTypeUtils().isSameType(t1, mirror(t2)); + } + + List methodsOf(final Element element) { + return ElementFilter.methodsIn(element.getEnclosedElements()); + } + + public List methodsOf(final Class clazz) { + return methodsOf(type(clazz)); + } + + // region pass-through + private final ProcessingEnvironment original; + + EnvironmentHelper(final ProcessingEnvironment original) { + this.original = original; + } + + @Override + public Map getOptions() { + return original.getOptions(); + } + + @Override + public Messager getMessager() { + return original.getMessager(); + } + + @Override + public Filer getFiler() { + return original.getFiler(); + } + + @Override + public Elements getElementUtils() { + return original.getElementUtils(); + } + + @Override + public Types getTypeUtils() { + return original.getTypeUtils(); + } + + @Override + public SourceVersion getSourceVersion() { + return original.getSourceVersion(); + } + + @Override + public Locale getLocale() { + return original.getLocale(); + } + // endregion +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 0ea154ed3..fc3ca93ef 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -40,7 +40,6 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; import org.jboss.jdeparser.*; @@ -48,16 +47,16 @@ abstract class Implementor { protected static final String ORIGINAL = "original"; protected static final String WRAP = "wrap"; - protected final ProcessingEnvironment environment; + protected final EnvironmentHelper environment; protected final TypeElement type; protected final JSources sources; protected final String originalInterface; - protected JSourceFile sourceFile; + protected final JSourceFile sourceFile; private final String implementationClass; protected Implementor(final ProcessingEnvironment environment, final Element element) { - this.environment = environment; + this.environment = new EnvironmentHelper(environment); type = (TypeElement) element; originalInterface = type.getQualifiedName().toString(); @@ -125,10 +124,10 @@ protected JClassDef createClass(final Class base) { protected final Stream membersAnnotatedWithAny( final Class... annotations) { - return ElementFilter.methodsIn(type.getEnclosedElements()).stream() + return environment.methodsOf(type).stream() .filter(method -> !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC) - && !method.getReturnType().equals($t(Void.class))) + && !environment.isVoid(method.getReturnType())) .filter(method -> Arrays.stream(annotations) .anyMatch(annotation -> method.getAnnotation(annotation) != null)); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 2d24189c0..4ff30ab86 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -94,8 +94,8 @@ private void createPropertyMethods(final JClassDef myClass) { final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); myMethod.annotate(Override.class); - final String methodName = method.getAnnotation(Property.class).mapping().getMethodName(); - final JExpr mapping = $t(ValueMappings.class).methodRef(methodName); + final String mappingMethodName = method.getAnnotation(Property.class).mapping().getMethodName(); + final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); final String predicateFromAnnotation = method.getAnnotation(Property.class).predicate(); final JCall predicate = THIS .call("getModel") @@ -108,6 +108,5 @@ private void createPropertyMethods(final JClassDef myClass) { .arg(predicate) .arg(mapping)); }); - } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index ceaa97c28..34a50373b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -20,8 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static javax.lang.model.util.ElementFilter.methodsIn; - import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.jena.ValueMappings; @@ -52,7 +50,7 @@ protected void validateInternal() { } private void requireCompatibleReturnType() { - for (final ExecutableElement method : methodsIn(element.getEnclosedElements())) { + for (final ExecutableElement method : env.methodsOf(element)) { final Property propertyAnnotation = method.getAnnotation(Property.class); if (propertyAnnotation != null) { final String mappingMethod = propertyAnnotation.mapping().getMethodName(); @@ -72,9 +70,7 @@ private void requireCompatibleReturnType() { } private TypeMirror returnTypeOfMapper(final String mappingMethod) { - final TypeElement valueMappings = env.getElementUtils().getTypeElement(ValueMappings.class.getCanonicalName()); - - for (final ExecutableElement m : methodsIn(valueMappings.getEnclosedElements())) { + for (final ExecutableElement m : env.methodsOf(ValueMappings.class)) { if (m.getSimpleName().contentEquals(mappingMethod)) { return m.getReturnType(); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index e6c5bf82a..cb2927609 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -20,8 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static javax.lang.model.util.ElementFilter.methodsIn; - import com.inrupt.rdf.wrapping.annotation.Dataset; import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.Resource; @@ -42,13 +40,13 @@ abstract class Validator { protected final TypeElement annotation; - protected final ProcessingEnvironment env; + protected final EnvironmentHelper env; protected final Element element; protected final Collection errors = new ArrayList<>(); protected Validator(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { this.annotation = annotation; - this.env = env; + this.env = new EnvironmentHelper(env); this.element = element; } @@ -107,16 +105,15 @@ protected final void requireNonMemberMethods(final Class.. element.getSimpleName()))); } - protected void limitBaseInterfaces(final Class clazz) { + protected void limitBaseInterfaces(final Class allowed) { if (!element.getKind().isInterface()) { return; } final TypeElement type = (TypeElement) element; - final TypeMirror allowed = env.getElementUtils().getTypeElement(clazz.getName()).asType(); for (final TypeMirror implemented : type.getInterfaces()) { - if (env.getTypeUtils().isSameType(implemented, allowed)) { + if (env.isSameType(implemented, allowed)) { continue; } @@ -125,7 +122,7 @@ protected void limitBaseInterfaces(final Class clazz) { "Interface %s annotated with @%s can only extend %s or nothing", element.getSimpleName(), annotation.getSimpleName(), - clazz.getName())); + allowed.getName())); } } @@ -163,6 +160,6 @@ protected void requireAnnotatedReturnType( } protected Stream getMethods() { - return methodsIn(element.getEnclosedElements()).stream(); + return env.methodsOf(element).stream(); } } From 28a40232956c44491860501210edcde855c92efd Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 8 Oct 2023 16:11:25 +0100 Subject: [PATCH 055/141] Don't generate explicit `this` --- .../wrapping/processor/DatasetImplementor.java | 6 +++--- .../wrapping/processor/GraphImplementor.java | 8 +++----- .../processor/ResourceImplementor.java | 18 +++++------------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 4c881416d..64900633d 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -20,8 +20,8 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JExpr.THIS; import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JExprs.call; import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; @@ -83,12 +83,12 @@ private void createWrapMethod(final JClassDef myClass, final JType myType) { } private static JExpr createDefaultGraphReturn(final JType implementation, final ExecutableElement ignored) { - return implementation.call(WRAP).arg(THIS.call("getDefaultModel")); + return implementation.call(WRAP).arg(call("getDefaultModel")); } private static JExpr createNamedGraphReturn(final JType implementation, final ExecutableElement element) { final JExpr graphName = JExprs.str(element.getAnnotation(NamedGraph.class).value()); - return implementation.call(WRAP).arg(THIS.call("getNamedModel").arg(graphName)); + return implementation.call(WRAP).arg(call("getNamedModel").arg(graphName)); } private void createGraphMethods( diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index eba22794f..2f083daf6 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -20,8 +20,8 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JExpr.THIS; import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JExprs.call; import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; @@ -112,7 +112,7 @@ private void addImplementationsToPersonality(final JMethodDef myConstructor) { myConstructor .body() - .call(THIS.call("getPersonality"), "add") + .call(call("getPersonality"), "add") .arg(implementationType._class()) .arg(implementationType.field(ResourceImplementor.FACTORY)); }); @@ -138,9 +138,7 @@ private void createMethods( myMethod.annotate(Override.class); // Call model wrapper convenience method passing projection class argument - final JCall wrapperConvenienceCall = THIS - .call(convenienceMethod) - .arg(implementationType._class()); + final JCall wrapperConvenienceCall = call(convenienceMethod).arg(implementationType._class()); // Pass each filter value from the annotation as additional argument for (final String s : annotationValueExtractor.apply(method)) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 4ff30ab86..df13151ff 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -20,9 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JExpr.THIS; -import static org.jboss.jdeparser.JExprs.$v; -import static org.jboss.jdeparser.JExprs.str; +import static org.jboss.jdeparser.JExprs.*; import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; @@ -97,16 +95,10 @@ private void createPropertyMethods(final JClassDef myClass) { final String mappingMethodName = method.getAnnotation(Property.class).mapping().getMethodName(); final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); final String predicateFromAnnotation = method.getAnnotation(Property.class).predicate(); - final JCall predicate = THIS - .call("getModel") - .call("createProperty") - .arg(str(predicateFromAnnotation)); - - myMethod.body()._return( - THIS - .call("anyOrNull") // TODO: Dynamic cardniality - .arg(predicate) - .arg(mapping)); + final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); + + // TODO: Dynamic cardniality + myMethod.body()._return(call("anyOrNull").arg(predicate).arg(mapping)); }); } } From 2983cb6336cc9333c26a841a00c2675cbaf1da5b Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 8 Oct 2023 16:24:53 +0100 Subject: [PATCH 056/141] Simplify --- .../java/com/inrupt/rdf/wrapping/processor/Implementor.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index fc3ca93ef..86326a3be 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -22,6 +22,7 @@ import static org.jboss.jdeparser.JMod.PUBLIC; import static org.jboss.jdeparser.JTypes.$t; +import static org.jboss.jdeparser.JTypes.typeOf; import com.inrupt.rdf.wrapping.annotation.Dataset; import com.inrupt.rdf.wrapping.annotation.Graph; @@ -50,7 +51,7 @@ abstract class Implementor { protected final EnvironmentHelper environment; protected final TypeElement type; protected final JSources sources; - protected final String originalInterface; + protected final JType originalInterface; protected final JSourceFile sourceFile; private final String implementationClass; @@ -59,7 +60,7 @@ protected Implementor(final ProcessingEnvironment environment, final Element ele this.environment = new EnvironmentHelper(environment); type = (TypeElement) element; - originalInterface = type.getQualifiedName().toString(); + originalInterface = typeOf(type.asType()); final String originalBinaryName = environment.getElementUtils().getBinaryName(type).toString(); final String qualifiedName = asImplementation(originalBinaryName); final int lastDot = originalBinaryName.lastIndexOf('.'); From ffe18fb1cf3ce93bdc26cefd66dd97128d7fbf11 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 14 Oct 2023 11:22:40 +0100 Subject: [PATCH 057/141] Separate representations for implementation and interface --- .../processor/DatasetImplementation.java | 88 ++++++++++ .../processor/DatasetImplementor.java | 94 +++-------- .../wrapping/processor/DatasetInterface.java | 43 +++++ .../processor/GraphImplementation.java | 106 ++++++++++++ .../wrapping/processor/GraphImplementor.java | 153 +++++------------- .../wrapping/processor/GraphInterface.java | 61 +++++++ .../rdf/wrapping/processor/Implementor.java | 44 +---- .../rdf/wrapping/processor/Interface.java | 52 ++++++ .../processor/ResourceImplementation.java | 97 +++++++++++ .../processor/ResourceImplementor.java | 86 +++------- .../wrapping/processor/ResourceInterface.java | 38 +++++ .../rdf/wrapping/processor/Validator.java | 1 + 12 files changed, 573 insertions(+), 290 deletions(-) create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java new file mode 100644 index 000000000..6c494b515 --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java @@ -0,0 +1,88 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static org.jboss.jdeparser.JExprs.*; +import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JTypes.$t; + +import java.time.Instant; + +import javax.annotation.Generated; + +import org.apache.jena.query.Dataset; +import org.apache.jena.sparql.core.DatasetGraph; +import org.apache.jena.sparql.core.DatasetImpl; +import org.jboss.jdeparser.JClassDef; +import org.jboss.jdeparser.JMethodDef; +import org.jboss.jdeparser.JSourceFile; +import org.jboss.jdeparser.JType; + +class DatasetImplementation { + private static final String ORIGINAL = "original"; + + static final String WRAP = "wrap"; // TODO: reuse in Manager + + private JClassDef target; + + void addImports(final JSourceFile source) { + source + ._import(Generated.class) + ._import(Dataset.class) + ._import(DatasetGraph.class) + ._import(DatasetImpl.class); + } + + void addClass(final JSourceFile source, final String name, final JType originalInterface) { + target = source._class(PUBLIC, name); + target._extends(DatasetImpl.class); + target._implements(originalInterface); + } + + void annotateAndDocument() { + target.docComment().text("Warning, this class consists of generated code."); + target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); + } + + void addConstructor() { + final JMethodDef myConstructor = target.constructor(PROTECTED); + myConstructor.param(FINAL, DatasetGraph.class, ORIGINAL); + myConstructor.body().callSuper().arg($v(ORIGINAL)); + } + + void addWrap(final JType originalInterface) { + final JMethodDef myWrap = target.method(PUBLIC | STATIC, originalInterface, WRAP); + myWrap.param(FINAL, Dataset.class, ORIGINAL); + myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("asDatasetGraph"))); + } + + void addDefaultGraph(final JType implementation, final String name, final JType returnType) { + final JMethodDef myMethod = target.method(PUBLIC, returnType, name); + myMethod.annotate(Override.class); + myMethod.body()._return(implementation.call(WRAP).arg(call("getDefaultModel"))); + } + + void addNamedGraph(final JType implementation, final String name, final String graph, final JType returnType) { + final JMethodDef myMethod = target.method(PUBLIC, returnType, name); + myMethod.annotate(Override.class); + myMethod.body()._return(implementation.call(WRAP).arg(call("getNamedModel").arg(str(graph)))); + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 64900633d..9746a2a66 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -20,26 +20,13 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JExprs.$v; -import static org.jboss.jdeparser.JExprs.call; -import static org.jboss.jdeparser.JMod.*; -import static org.jboss.jdeparser.JTypes.$t; - -import com.inrupt.rdf.wrapping.annotation.DefaultGraph; import com.inrupt.rdf.wrapping.annotation.NamedGraph; -import java.lang.annotation.Annotation; -import java.util.function.BiFunction; - -import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; -import org.apache.jena.query.Dataset; -import org.apache.jena.sparql.core.DatasetGraph; -import org.apache.jena.sparql.core.DatasetImpl; -import org.jboss.jdeparser.*; +import org.jboss.jdeparser.JTypes; class DatasetImplementor extends Implementor { DatasetImplementor(final ProcessingEnvironment environment, final Element element) { @@ -48,61 +35,28 @@ class DatasetImplementor extends Implementor { @Override protected void implementInternal() { - addImports(); - - final JClassDef myClass = createClass(DatasetImpl.class); - final JType myType = $t(myClass); - - createConstructor(myClass); - - createWrapMethod(myClass, myType); - - createGraphMethods(myClass, DefaultGraph.class, DatasetImplementor::createDefaultGraphReturn); - - createGraphMethods(myClass, NamedGraph.class, DatasetImplementor::createNamedGraphReturn); - } - - private void addImports() { - sourceFile - ._import(Generated.class) - ._import(Dataset.class) - ._import(DatasetGraph.class) - ._import(DatasetImpl.class); - } - - private static void createConstructor(final JClassDef myClass) { - final JMethodDef myConstructor = myClass.constructor(PROTECTED); - myConstructor.param(FINAL, DatasetGraph.class, ORIGINAL); - myConstructor.body().callSuper().arg($v(ORIGINAL)); - } - - private void createWrapMethod(final JClassDef myClass, final JType myType) { - final JMethodDef myWrap = myClass.method(PUBLIC | STATIC, originalInterface, WRAP); - myWrap.param(FINAL, Dataset.class, ORIGINAL); - myWrap.body()._return(myType._new().arg($v(ORIGINAL).call("asDatasetGraph"))); - } - - private static JExpr createDefaultGraphReturn(final JType implementation, final ExecutableElement ignored) { - return implementation.call(WRAP).arg(call("getDefaultModel")); - } - - private static JExpr createNamedGraphReturn(final JType implementation, final ExecutableElement element) { - final JExpr graphName = JExprs.str(element.getAnnotation(NamedGraph.class).value()); - return implementation.call(WRAP).arg(call("getNamedModel").arg(graphName)); - } - - private void createGraphMethods( - final JClassDef myClass, - final Class annotation, - final BiFunction returnCreator) { - - membersAnnotatedWithAny(annotation).forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final JType implementationType = asImplementation(method.getReturnType()); - final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); - - myMethod.annotate(Override.class); - myMethod.body()._return(returnCreator.apply(implementationType, method)); - }); + final DatasetInterface myInterface = new DatasetInterface(environment, type); + final DatasetImplementation myClass = new DatasetImplementation(); + + myClass.addImports(sourceFile); + myClass.addClass(sourceFile, implementationClass, originalInterface); + myClass.annotateAndDocument(); + myClass.addConstructor(); + myClass.addWrap(originalInterface); + + for (final ExecutableElement method : myInterface.defaultGraphMethods()) { + myClass.addDefaultGraph( + asImplementation(method.getReturnType()), + method.getSimpleName().toString(), + JTypes.typeOf(method.getReturnType())); + } + + for (ExecutableElement method : myInterface.namedGraphMethods()) { + myClass.addNamedGraph( + asImplementation(method.getReturnType()), + method.getSimpleName().toString(), + method.getAnnotation(NamedGraph.class).value(), + JTypes.typeOf(method.getReturnType())); + } } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java new file mode 100644 index 000000000..42de13b0a --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java @@ -0,0 +1,43 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import com.inrupt.rdf.wrapping.annotation.DefaultGraph; +import com.inrupt.rdf.wrapping.annotation.NamedGraph; + +import java.util.List; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; + +class DatasetInterface extends Interface { + DatasetInterface(EnvironmentHelper environment, TypeElement type) { + super(environment, type); + } + + List defaultGraphMethods() { + return membersAnnotatedWithAny(DefaultGraph.class); + } + + List namedGraphMethods() { + return membersAnnotatedWithAny(NamedGraph.class); + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java new file mode 100644 index 000000000..f37168e31 --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java @@ -0,0 +1,106 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JExprs.call; +import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JTypes.$t; + +import com.inrupt.rdf.wrapping.jena.WrapperModel; + +import java.time.Instant; + +import javax.annotation.Generated; + +import org.apache.jena.graph.Graph; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.impl.ModelCom; +import org.jboss.jdeparser.*; + +class GraphImplementation { + private static final String ORIGINAL = "original"; + private static final String WRAP = "wrap"; + + private JClassDef target; + private JMethodDef constructor; + + void addImports(final JSourceFile source) { + source + ._import(WrapperModel.class) + ._import(Generated.class) + ._import(Graph.class) + ._import(Model.class) + ._import(ModelCom.class); + } + + void addClass(final JSourceFile source, final String name, final JType originalInterface) { + target = source._class(PUBLIC, name); + target._extends(WrapperModel.class); + target._implements(originalInterface); + } + + void annotateAndDocument() { + target.docComment().text("Warning, this class consists of generated code."); + target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); + } + + void addConstructor() { + constructor = target.constructor(PROTECTED); + constructor.param(FINAL, Graph.class, ORIGINAL); + constructor.body().callSuper().arg($v(ORIGINAL)); + } + + void addWrap(final JType originalInterface) { + final JMethodDef myWrap = target.method(PUBLIC | STATIC, originalInterface, WRAP); + myWrap.param(FINAL, Model.class, ORIGINAL); + myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("getGraph"))); + } + + void addToPersonality(final JType implementationType) { + constructor + .body() + .call(call("getPersonality"), "add") + .arg(implementationType._class()) + .arg(implementationType.field(ResourceImplementation.FACTORY)); + } + + void addResourceMethod( + final JType returnType, + final String name, + final String convenience, + final JType implementationType, + final String[] values) { + + final JMethodDef myMethod = target.method(PUBLIC, returnType, name); + myMethod.annotate(Override.class); + + // Call model wrapper convenience method passing projection class argument + final JCall wrapperConvenienceCall = call(convenience).arg(implementationType._class()); + + // Pass each filter value from the annotation as additional argument + for (final String value : values) { + wrapperConvenienceCall.arg(JExprs.str(value)); + } + + myMethod.body()._return(wrapperConvenienceCall); + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 2f083daf6..c9402982b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -20,28 +20,16 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JExprs.$v; -import static org.jboss.jdeparser.JExprs.call; -import static org.jboss.jdeparser.JMod.*; -import static org.jboss.jdeparser.JTypes.$t; +import static org.jboss.jdeparser.JTypes.typeOf; import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; -import com.inrupt.rdf.wrapping.jena.WrapperModel; -import java.lang.annotation.Annotation; -import java.util.function.Function; - -import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; - -import org.apache.jena.graph.Graph; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.impl.ModelCom; -import org.jboss.jdeparser.*; +import javax.lang.model.type.TypeMirror; class GraphImplementor extends Implementor { GraphImplementor(final ProcessingEnvironment environment, final Element element) { @@ -50,102 +38,45 @@ class GraphImplementor extends Implementor { @Override protected void implementInternal() { - addImports(); - - final JClassDef myClass = createClass(WrapperModel.class); - final JType myType = $t(myClass); - - final JMethodDef myConstructor = createConstructor(myClass); - - addImplementationsToPersonality(myConstructor); // TODO: Also add return types of properties of resources - - createWrapMethod(myClass, myType); - - createMethods( - myClass, - OptionalFirstInstanceOfEither.class, - "optionalFirstInstanceOfEither", - m -> m.getAnnotation(OptionalFirstInstanceOfEither.class).value() - ); - - createMethods( - myClass, - OptionalFirstSubjectOfEither.class, - "optionalFirstSubjectOfEither", - m -> m.getAnnotation(OptionalFirstSubjectOfEither.class).value() - ); - - createMethods( - myClass, - OptionalFirstObjectOfEither.class, - "optionalFirstObjectOfEither", - m -> m.getAnnotation(OptionalFirstObjectOfEither.class).value() - ); - } - - private void addImports() { - sourceFile - ._import(WrapperModel.class) - ._import(Generated.class) - ._import(Graph.class) - ._import(Model.class) - ._import(ModelCom.class); - } - - private static JMethodDef createConstructor(final JClassDef myClass) { - final JMethodDef myConstructor = myClass.constructor(PROTECTED); - myConstructor.param(FINAL, Graph.class, ORIGINAL); - myConstructor.body().callSuper().arg($v(ORIGINAL)); - - return myConstructor; - } - - private void addImplementationsToPersonality(final JMethodDef myConstructor) { - membersAnnotatedWithAny( - OptionalFirstInstanceOfEither.class, - OptionalFirstSubjectOfEither.class, - OptionalFirstObjectOfEither.class) - .map(ExecutableElement::getReturnType) - .distinct() - .forEach(returnType -> { - final JType implementationType = asImplementation(returnType); - - myConstructor - .body() - .call(call("getPersonality"), "add") - .arg(implementationType._class()) - .arg(implementationType.field(ResourceImplementor.FACTORY)); - }); - } - - private void createWrapMethod(final JClassDef myClass, final JType myType) { - final JMethodDef myWrap = myClass.method(PUBLIC | STATIC, originalInterface, WRAP); - myWrap.param(FINAL, Model.class, ORIGINAL); - myWrap.body()._return(myType._new().arg($v(ORIGINAL).call("getGraph"))); - } - - private void createMethods( - final JClassDef myClass, - final Class annotation, - final String convenienceMethod, - final Function annotationValueExtractor) { - - membersAnnotatedWithAny(annotation).forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - final JType implementationType = asImplementation(method.getReturnType()); - - final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); - myMethod.annotate(Override.class); - - // Call model wrapper convenience method passing projection class argument - final JCall wrapperConvenienceCall = call(convenienceMethod).arg(implementationType._class()); - - // Pass each filter value from the annotation as additional argument - for (final String s : annotationValueExtractor.apply(method)) { - wrapperConvenienceCall.arg(JExprs.str(s)); - } - - myMethod.body()._return(wrapperConvenienceCall); - }); + final GraphInterface myInterface = new GraphInterface(environment, type); + final GraphImplementation myClass = new GraphImplementation(); + + myClass.addImports(sourceFile); + myClass.addClass(sourceFile, implementationClass, originalInterface); + myClass.annotateAndDocument(); + myClass.addConstructor(); + myClass.addWrap(originalInterface); + + // TODO: Also add return types of properties of resources + for (final TypeMirror type : myInterface.resourceMethodTypes()) { + myClass.addToPersonality(asImplementation(type)); + } + + for (final ExecutableElement method : myInterface.instanceMethods()) { + myClass.addResourceMethod( + typeOf(method.getReturnType()), + method.getSimpleName().toString(), + "optionalFirstInstanceOfEither", + asImplementation(method.getReturnType()), + method.getAnnotation(OptionalFirstInstanceOfEither.class).value()); + } + + for (final ExecutableElement method : myInterface.subjectMethods()) { + myClass.addResourceMethod( + typeOf(method.getReturnType()), + method.getSimpleName().toString(), + "optionalFirstSubjectOfEither", + asImplementation(method.getReturnType()), + method.getAnnotation(OptionalFirstSubjectOfEither.class).value()); + } + + for (final ExecutableElement method : myInterface.objectMethods()) { + myClass.addResourceMethod( + typeOf(method.getReturnType()), + method.getSimpleName().toString(), + "optionalFirstObjectOfEither", + asImplementation(method.getReturnType()), + method.getAnnotation(OptionalFirstObjectOfEither.class).value()); + } } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java new file mode 100644 index 000000000..a253274b5 --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java @@ -0,0 +1,61 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; + +import java.util.List; +import java.util.stream.Collectors; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +class GraphInterface extends Interface { + GraphInterface(final EnvironmentHelper environment, final TypeElement type) { + super(environment, type); + } + + List resourceMethodTypes() { + return membersAnnotatedWithAny( + OptionalFirstInstanceOfEither.class, + OptionalFirstSubjectOfEither.class, + OptionalFirstObjectOfEither.class) + .stream() + .map(ExecutableElement::getReturnType) + .distinct() + .collect(Collectors.toList()); + } + + List instanceMethods() { + return membersAnnotatedWithAny(OptionalFirstInstanceOfEither.class); + } + + List subjectMethods() { + return membersAnnotatedWithAny(OptionalFirstSubjectOfEither.class); + } + + List objectMethods() { + return membersAnnotatedWithAny(OptionalFirstObjectOfEither.class); + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 86326a3be..52c1eb182 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -20,7 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JMod.PUBLIC; import static org.jboss.jdeparser.JTypes.$t; import static org.jboss.jdeparser.JTypes.typeOf; @@ -29,24 +28,16 @@ import com.inrupt.rdf.wrapping.annotation.Resource; import java.io.IOException; -import java.lang.annotation.Annotation; -import java.time.Instant; -import java.util.Arrays; -import java.util.stream.Stream; -import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; import org.jboss.jdeparser.*; abstract class Implementor { - protected static final String ORIGINAL = "original"; - protected static final String WRAP = "wrap"; + protected static final String WRAP = "wrap"; // TODO: Sunset protected final EnvironmentHelper environment; protected final TypeElement type; @@ -54,7 +45,7 @@ abstract class Implementor { protected final JType originalInterface; protected final JSourceFile sourceFile; - private final String implementationClass; + protected final String implementationClass; protected Implementor(final ProcessingEnvironment environment, final Element element) { this.environment = new EnvironmentHelper(environment); @@ -109,35 +100,4 @@ protected JType asImplementation(final TypeMirror original) { return $t(asImplementation(originalBinaryName)); } - - protected JClassDef createClass(final Class base) { - final JClassDef myClass = sourceFile - ._class(PUBLIC, implementationClass) - ._extends(base) - ._implements(originalInterface); - - annotateAndDocumentAsGenerated(myClass); - - return myClass; - } - - @SafeVarargs - protected final Stream membersAnnotatedWithAny( - final Class... annotations) { - - return environment.methodsOf(type).stream() - .filter(method -> !method.isDefault() - && !method.getModifiers().contains(Modifier.STATIC) - && !environment.isVoid(method.getReturnType())) - .filter(method -> Arrays.stream(annotations) - .anyMatch(annotation -> method.getAnnotation(annotation) != null)); - } - - private void annotateAndDocumentAsGenerated(final JClassDef implementation) { - implementation.docComment().text("Warning, this class consists of generated code."); - - implementation - .annotate(Generated.class) - .value(this.getClass().getName()).value("date", Instant.now().toString()); - } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java new file mode 100644 index 000000000..d3a1a00d1 --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -0,0 +1,52 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import java.lang.annotation.Annotation; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; + +class Interface { + private final EnvironmentHelper environment; + private final TypeElement type; + + Interface(final EnvironmentHelper environment, final TypeElement type) { + this.environment = environment; + this.type = type; + } + + @SafeVarargs + protected final List membersAnnotatedWithAny( + final Class... annotations) { + + return environment.methodsOf(type).stream() + .filter(method -> !method.isDefault()) + .filter(method -> !method.getModifiers().contains(Modifier.STATIC)) + .filter(method -> !environment.isVoid(method.getReturnType())) + .filter(method -> Arrays.stream(annotations).anyMatch(a -> method.getAnnotation(a) != null)) + .collect(Collectors.toList()); + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java new file mode 100644 index 000000000..16a230ccb --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java @@ -0,0 +1,97 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static org.jboss.jdeparser.JExprs.*; +import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JTypes.$t; + +import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; +import com.inrupt.rdf.wrapping.jena.ValueMappings; +import com.inrupt.rdf.wrapping.jena.WrapperResource; + +import java.time.Instant; + +import javax.annotation.Generated; + +import org.apache.jena.enhanced.EnhGraph; +import org.apache.jena.enhanced.Implementation; +import org.apache.jena.graph.Node; +import org.jboss.jdeparser.*; + +class ResourceImplementation { + static final String FACTORY = "factory"; + + private JClassDef target; + + void addImports(final JSourceFile source) { + source + ._import(UriOrBlankFactory.class) + ._import(WrapperResource.class) + ._import(Generated.class) + ._import(EnhGraph.class) + ._import(Implementation.class) + ._import(Node.class) + ._import(ValueMappings.class); + } + + void addClass(final JSourceFile source, final String name, final JType originalInterface) { + target = source._class(PUBLIC, name); + target._extends(WrapperResource.class); + target._implements(originalInterface); + } + + void addFactoryField() { + target.field( + STATIC | FINAL, + Implementation.class, + FACTORY, + $t(UriOrBlankFactory.class)._new().arg($t(target).methodRef("new"))); + } + + void annotateAndDocument() { + target.docComment().text("Warning, this class consists of generated code."); + target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); + } + + void addConstructor() { + final JMethodDef myConstructor = target.constructor(PROTECTED); + myConstructor.param(FINAL, Node.class, "node"); + myConstructor.param(FINAL, EnhGraph.class, "graph"); + myConstructor.body().callSuper().arg($v("node")).arg($v("graph")); + } + + void addPropertyMethod( + final JType returnType, + final String name, + final String mappingMethodName, + final String predicateFromAnnotation) { + + final JMethodDef myMethod = target.method(PUBLIC, returnType, name); + myMethod.annotate(Override.class); + + final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); + final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); + + // TODO: Dynamic cardniality + myMethod.body()._return(call("anyOrNull").arg(predicate).arg(mapping)); + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index df13151ff..e21df9f1e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -20,85 +20,37 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JExprs.*; -import static org.jboss.jdeparser.JMod.*; -import static org.jboss.jdeparser.JTypes.$t; - import com.inrupt.rdf.wrapping.annotation.Property; -import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; -import com.inrupt.rdf.wrapping.jena.ValueMappings; -import com.inrupt.rdf.wrapping.jena.WrapperResource; -import javax.annotation.Generated; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; -import org.apache.jena.enhanced.EnhGraph; -import org.apache.jena.enhanced.Implementation; -import org.apache.jena.graph.Node; -import org.jboss.jdeparser.*; +import org.jboss.jdeparser.JTypes; class ResourceImplementor extends Implementor { - static final String FACTORY = "factory"; - ResourceImplementor(final ProcessingEnvironment environment, final Element element) { super(environment, element); } @Override protected void implementInternal() { - addImports(); - - final JClassDef myClass = createClass(WrapperResource.class); - final JType myType = $t(myClass); - - createFactoryField(myClass, myType); - - createConstructor(myClass); - - createPropertyMethods(myClass); - } - - private void addImports() { - sourceFile - ._import(UriOrBlankFactory.class) - ._import(WrapperResource.class) - ._import(Generated.class) - ._import(EnhGraph.class) - ._import(Implementation.class) - ._import(Node.class) - ._import(ValueMappings.class); - } - - private static void createFactoryField(final JClassDef myClass, final JType myType) { - myClass.field( - STATIC | FINAL, - Implementation.class, - FACTORY, - $t(UriOrBlankFactory.class)._new().arg(myType.methodRef("new"))); - } - - private static void createConstructor(final JClassDef myClass) { - final JMethodDef myConstructor = myClass.constructor(PROTECTED); - myConstructor.param(FINAL, Node.class, "node"); - myConstructor.param(FINAL, EnhGraph.class, "graph"); - myConstructor.body().callSuper().arg($v("node")).arg($v("graph")); - } - - private void createPropertyMethods(final JClassDef myClass) { - membersAnnotatedWithAny(Property.class).forEach(method -> { - final JType returnType = JTypes.typeOf(method.getReturnType()); - - final JMethodDef myMethod = myClass.method(PUBLIC, returnType, method.getSimpleName().toString()); - myMethod.annotate(Override.class); - - final String mappingMethodName = method.getAnnotation(Property.class).mapping().getMethodName(); - final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); - final String predicateFromAnnotation = method.getAnnotation(Property.class).predicate(); - final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); - - // TODO: Dynamic cardniality - myMethod.body()._return(call("anyOrNull").arg(predicate).arg(mapping)); - }); + final ResourceInterface myInterface = new ResourceInterface(environment, type); + final ResourceImplementation myClass = new ResourceImplementation(); + + myClass.addImports(sourceFile); + myClass.addClass(sourceFile, implementationClass, originalInterface); + myClass.addFactoryField(); + myClass.annotateAndDocument(); + myClass.addConstructor(); + + for (final ExecutableElement method : myInterface.propertyMethods()) { + myClass.addPropertyMethod( + JTypes.typeOf(method.getReturnType()), + method.getSimpleName().toString(), + method.getAnnotation(Property.class).mapping().getMethodName(), + method.getAnnotation(Property.class).predicate() + ); + } } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java new file mode 100644 index 000000000..f88b42cc7 --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java @@ -0,0 +1,38 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import com.inrupt.rdf.wrapping.annotation.Property; + +import java.util.List; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; + +class ResourceInterface extends Interface { + ResourceInterface(final EnvironmentHelper environment, final TypeElement type) { + super(environment, type); + } + + List propertyMethods() { + return membersAnnotatedWithAny(Property.class); + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index cb2927609..6ca1d9c25 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -38,6 +38,7 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; +// TODO: Use interfaces in validators abstract class Validator { protected final TypeElement annotation; protected final EnvironmentHelper env; From 2cda65abf8059893b5421fe01fd13417d4db687e Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 14 Oct 2023 12:33:48 +0100 Subject: [PATCH 058/141] Helper --- .../com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java | 4 ++++ .../java/com/inrupt/rdf/wrapping/processor/Implementor.java | 4 ++-- .../java/com/inrupt/rdf/wrapping/processor/Validator.java | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java index be5523fdc..5bdca40ee 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java @@ -27,6 +27,10 @@ TypeElement type(final Class clazz) { return getElementUtils().getTypeElement(clazz.getCanonicalName()); } + TypeElement type(final TypeMirror mirror) { + return (TypeElement) getTypeUtils().asElement(mirror); + } + boolean isVoid(final TypeMirror type) { return isSameType(type, Void.class); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 52c1eb182..4e520c6bb 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -92,10 +92,10 @@ static String asImplementation(final String original) { } protected JType asImplementation(final TypeMirror original) { - final Element returnType = environment.getTypeUtils().asElement(original); + final TypeElement returnType = environment.type(original); final String originalBinaryName = environment .getElementUtils() - .getBinaryName((TypeElement) returnType) + .getBinaryName(returnType) .toString(); return $t(asImplementation(originalBinaryName)); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 6ca1d9c25..c9d096766 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -146,7 +146,7 @@ protected void requireAnnotatedReturnType( final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; final Predicate isNotResource = method -> - env.getTypeUtils().asElement(method.getReturnType()).getAnnotation(required) == null; + env.type(method.getReturnType()).getAnnotation(required) == null; getMethods() .filter(isAnnotated) From 72ddc613101d9ef2b8ab29f6704aebf1a7a5a735 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 14 Oct 2023 12:34:52 +0100 Subject: [PATCH 059/141] First step to resource properties --- .../rdf/wrapping/annotation/Property.java | 3 +- .../rdf/wrapping/processor/Interface.java | 2 +- .../processor/ResourceImplementation.java | 31 +++++++++++++++++-- .../processor/ResourceImplementor.java | 19 +++++++++--- .../wrapping/processor/ResourceInterface.java | 19 ++++++++++-- .../wrapping/processor/ResourceValidator.java | 5 +++ .../com/inrupt/rdf/wrapping/processor/X.java | 10 ++++-- .../inrupt/rdf/wrapping/processor/XTest.java | 2 ++ 8 files changed, 77 insertions(+), 14 deletions(-) diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java index 056b775db..1f0a52f42 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java @@ -37,7 +37,8 @@ enum Mapping { IRI_AS_STRING("iriAsString"), - IRI_AS_URI("iriAsUri"); + IRI_AS_URI("iriAsUri"), + AS("as"); private final String methodName; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java index d3a1a00d1..25ba4e4b9 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -30,7 +30,7 @@ import javax.lang.model.element.TypeElement; class Interface { - private final EnvironmentHelper environment; + protected final EnvironmentHelper environment; private final TypeElement type; Interface(final EnvironmentHelper environment, final TypeElement type) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java index 16a230ccb..70dcc84cc 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java @@ -79,16 +79,41 @@ void addConstructor() { myConstructor.body().callSuper().arg($v("node")).arg($v("graph")); } - void addPropertyMethod( + void addPrimitivePropertyMethod( final JType returnType, final String name, final String mappingMethodName, - final String predicateFromAnnotation) { + final String predicate) { + + addPropertyMethod( + returnType, + name, + predicate, + $t(ValueMappings.class).methodRef(mappingMethodName)); + } + + void addResourcePropertyMethod( + final JType returnType, + final String name, + final String predicate, + final JType implementation) { + + addPropertyMethod( + returnType, + name, + predicate, + $t(ValueMappings.class).call("as").arg(implementation._class())); + } + + private void addPropertyMethod( + final JType returnType, + final String name, + final String predicateFromAnnotation, + final JExpr mapping) { final JMethodDef myMethod = target.method(PUBLIC, returnType, name); myMethod.annotate(Override.class); - final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); // TODO: Dynamic cardniality diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index e21df9f1e..40cf5443b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -20,14 +20,14 @@ */ package com.inrupt.rdf.wrapping.processor; +import static org.jboss.jdeparser.JTypes.typeOf; + import com.inrupt.rdf.wrapping.annotation.Property; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; -import org.jboss.jdeparser.JTypes; - class ResourceImplementor extends Implementor { ResourceImplementor(final ProcessingEnvironment environment, final Element element) { super(environment, element); @@ -44,13 +44,22 @@ protected void implementInternal() { myClass.annotateAndDocument(); myClass.addConstructor(); - for (final ExecutableElement method : myInterface.propertyMethods()) { - myClass.addPropertyMethod( - JTypes.typeOf(method.getReturnType()), + for (final ExecutableElement method : myInterface.primitivePropertyMethods()) { + myClass.addPrimitivePropertyMethod( + typeOf(method.getReturnType()), method.getSimpleName().toString(), method.getAnnotation(Property.class).mapping().getMethodName(), method.getAnnotation(Property.class).predicate() ); } + + for (final ExecutableElement method : myInterface.resourcePropertyMethods()) { + myClass.addResourcePropertyMethod( + typeOf(method.getReturnType()), + method.getSimpleName().toString(), + method.getAnnotation(Property.class).predicate(), + asImplementation(method.getReturnType()) + ); + } } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java index f88b42cc7..97f727300 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java @@ -21,8 +21,11 @@ package com.inrupt.rdf.wrapping.processor; import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; @@ -32,7 +35,19 @@ class ResourceInterface extends Interface { super(environment, type); } - List propertyMethods() { - return membersAnnotatedWithAny(Property.class); + List primitivePropertyMethods() { + return membersAnnotatedWithAny(Property.class).stream() + .filter(returnTypeIsResource().negate()) + .collect(Collectors.toList()); + } + + List resourcePropertyMethods() { + return membersAnnotatedWithAny(Property.class).stream() + .filter(returnTypeIsResource()) + .collect(Collectors.toList()); + } + + private Predicate returnTypeIsResource() { + return method -> environment.type(method.getReturnType()).getAnnotation(Resource.class) != null; } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 34a50373b..6bb11b2f8 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -53,6 +53,11 @@ private void requireCompatibleReturnType() { for (final ExecutableElement method : env.methodsOf(element)) { final Property propertyAnnotation = method.getAnnotation(Property.class); if (propertyAnnotation != null) { + // TODO: Validate otherwise + if (propertyAnnotation.mapping() == Property.Mapping.AS){ + continue; + } + final String mappingMethod = propertyAnnotation.mapping().getMethodName(); final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java index b3b1d9554..29a6fe737 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java @@ -20,8 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_URI; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.*; import com.inrupt.rdf.wrapping.annotation.*; @@ -63,6 +62,13 @@ interface Z { @Property(predicate = "urn:example:p", mapping = IRI_AS_URI) URI getProperty2(); + + @Property(predicate = "urn:example:p", mapping = AS) + Z2 getProperty3(); + } + + @Resource + interface Z2 { } } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java index 7895e4e95..3013c3e5b 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java @@ -121,12 +121,14 @@ void e2e() { final X.Y.Z z3 = y.getResource3(); final String p = z.getProperty(); final URI p2 = z.getProperty2(); + final X.Y.Z2 p3 = z.getProperty3(); System.out.println(z); System.out.println(z2); System.out.println(z3); System.out.println(p); System.out.println(p2); + System.out.println(p3); } private static Dataset datasetFrom(final String rdf) { From 206f71b4b769e6a9d59d3c68b5a5761089f7dd5d Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 14 Oct 2023 20:06:15 +0100 Subject: [PATCH 060/141] Transitive personality --- .../wrapping/processor/GraphImplementor.java | 6 +--- .../wrapping/processor/GraphInterface.java | 32 +++++++++++++------ .../wrapping/processor/ResourceInterface.java | 17 ++++++++++ .../com/inrupt/rdf/wrapping/processor/X.java | 6 ++++ .../inrupt/rdf/wrapping/processor/XTest.java | 2 ++ 5 files changed, 48 insertions(+), 15 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index c9402982b..d7f9fb1e5 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -29,7 +29,6 @@ import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.type.TypeMirror; class GraphImplementor extends Implementor { GraphImplementor(final ProcessingEnvironment environment, final Element element) { @@ -47,10 +46,7 @@ protected void implementInternal() { myClass.addConstructor(); myClass.addWrap(originalInterface); - // TODO: Also add return types of properties of resources - for (final TypeMirror type : myInterface.resourceMethodTypes()) { - myClass.addToPersonality(asImplementation(type)); - } + myInterface.transitiveResourceTypes().map(this::asImplementation).forEach(myClass::addToPersonality); for (final ExecutableElement method : myInterface.instanceMethods()) { myClass.addResourceMethod( diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java index a253274b5..c53354f23 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java @@ -20,12 +20,14 @@ */ package com.inrupt.rdf.wrapping.processor; +import static java.util.stream.Stream.concat; + import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; import java.util.List; -import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; @@ -36,15 +38,15 @@ class GraphInterface extends Interface { super(environment, type); } - List resourceMethodTypes() { - return membersAnnotatedWithAny( - OptionalFirstInstanceOfEither.class, - OptionalFirstSubjectOfEither.class, - OptionalFirstObjectOfEither.class) - .stream() - .map(ExecutableElement::getReturnType) - .distinct() - .collect(Collectors.toList()); + Stream transitiveResourceTypes() { + final Stream children = resourceMethodTypes(); + final Stream descendants = resourceMethodTypes() + .map(environment::type) + .map(type -> new ResourceInterface(environment, type)) + .flatMap(ResourceInterface::transitiveResourceTypes); + + return concat(children, descendants) + .distinct(); } List instanceMethods() { @@ -58,4 +60,14 @@ List subjectMethods() { List objectMethods() { return membersAnnotatedWithAny(OptionalFirstObjectOfEither.class); } + + private Stream resourceMethodTypes() { + return membersAnnotatedWithAny( + OptionalFirstInstanceOfEither.class, + OptionalFirstSubjectOfEither.class, + OptionalFirstObjectOfEither.class) + .stream() + .map(ExecutableElement::getReturnType) + .distinct(); + } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java index 97f727300..17b114f08 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java @@ -20,15 +20,19 @@ */ package com.inrupt.rdf.wrapping.processor; +import static java.util.stream.Stream.concat; + import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; class ResourceInterface extends Interface { ResourceInterface(final EnvironmentHelper environment, final TypeElement type) { @@ -47,6 +51,19 @@ List resourcePropertyMethods() { .collect(Collectors.toList()); } + Stream transitiveResourceTypes() { + final Stream children = resourcePropertyMethods().stream() + .map(ExecutableElement::getReturnType); + + final Stream descendants = resourcePropertyMethods().stream() + .map(ExecutableElement::getReturnType) + .map(environment::type) + .map(type -> new ResourceInterface(environment, type)) + .flatMap(ResourceInterface::transitiveResourceTypes); + + return concat(children, descendants).distinct(); + } + private Predicate returnTypeIsResource() { return method -> environment.type(method.getReturnType()).getAnnotation(Resource.class) != null; } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java index 29a6fe737..9467a6853 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java @@ -69,6 +69,12 @@ interface Z { @Resource interface Z2 { + @Property(predicate = "urn:example:p", mapping = AS) + Z3 getProperty(); + } + + @Resource + interface Z3 { } } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java index 3013c3e5b..fc8bd85f1 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java @@ -122,6 +122,7 @@ void e2e() { final String p = z.getProperty(); final URI p2 = z.getProperty2(); final X.Y.Z2 p3 = z.getProperty3(); + final X.Y.Z3 p4 = p3.getProperty(); System.out.println(z); System.out.println(z2); @@ -129,6 +130,7 @@ void e2e() { System.out.println(p); System.out.println(p2); System.out.println(p3); + System.out.println(p4); } private static Dataset datasetFrom(final String rdf) { From eba597ef0cc860efcf727c7b32615bc32d84564d Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 14 Oct 2023 21:16:57 +0100 Subject: [PATCH 061/141] Style --- .../wrapping/processor/DatasetInterface.java | 2 +- .../wrapping/processor/EnvironmentHelper.java | 20 +++++++++++++++++++ .../wrapping/processor/ResourceValidator.java | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java index 42de13b0a..91c67df76 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java @@ -29,7 +29,7 @@ import javax.lang.model.element.TypeElement; class DatasetInterface extends Interface { - DatasetInterface(EnvironmentHelper environment, TypeElement type) { + DatasetInterface(final EnvironmentHelper environment, final TypeElement type) { super(environment, type); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java index 5bdca40ee..2795eb265 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java @@ -1,3 +1,23 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ package com.inrupt.rdf.wrapping.processor; import com.inrupt.rdf.wrapping.jena.ValueMappings; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 6bb11b2f8..a252c48de 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -54,7 +54,7 @@ private void requireCompatibleReturnType() { final Property propertyAnnotation = method.getAnnotation(Property.class); if (propertyAnnotation != null) { // TODO: Validate otherwise - if (propertyAnnotation.mapping() == Property.Mapping.AS){ + if (propertyAnnotation.mapping() == Property.Mapping.AS) { continue; } From 7ec470707ff605ca849c8ab8c42dd5d172c8ef76 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 15 Oct 2023 14:18:42 +0100 Subject: [PATCH 062/141] Simplify interface representations --- .../processor/DatasetImplementor.java | 25 +++++------ .../wrapping/processor/DatasetInterface.java | 10 ++--- .../wrapping/processor/GraphImplementor.java | 43 ++++++++----------- .../wrapping/processor/GraphInterface.java | 19 +++----- .../rdf/wrapping/processor/Interface.java | 12 ++---- .../processor/ResourceImplementor.java | 29 +++++-------- .../wrapping/processor/ResourceInterface.java | 19 +++----- 7 files changed, 60 insertions(+), 97 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 9746a2a66..daf1b5fb9 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -24,7 +24,6 @@ import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; import org.jboss.jdeparser.JTypes; @@ -44,19 +43,15 @@ protected void implementInternal() { myClass.addConstructor(); myClass.addWrap(originalInterface); - for (final ExecutableElement method : myInterface.defaultGraphMethods()) { - myClass.addDefaultGraph( - asImplementation(method.getReturnType()), - method.getSimpleName().toString(), - JTypes.typeOf(method.getReturnType())); - } - - for (ExecutableElement method : myInterface.namedGraphMethods()) { - myClass.addNamedGraph( - asImplementation(method.getReturnType()), - method.getSimpleName().toString(), - method.getAnnotation(NamedGraph.class).value(), - JTypes.typeOf(method.getReturnType())); - } + myInterface.defaultGraphMethods().forEach(method -> myClass.addDefaultGraph( + asImplementation(method.getReturnType()), + method.getSimpleName().toString(), + JTypes.typeOf(method.getReturnType()))); + + myInterface.namedGraphMethods().forEach(method -> myClass.addNamedGraph( + asImplementation(method.getReturnType()), + method.getSimpleName().toString(), + method.getAnnotation(NamedGraph.class).value(), + JTypes.typeOf(method.getReturnType()))); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java index 91c67df76..0cfd682af 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java @@ -23,7 +23,7 @@ import com.inrupt.rdf.wrapping.annotation.DefaultGraph; import com.inrupt.rdf.wrapping.annotation.NamedGraph; -import java.util.List; +import java.util.stream.Stream; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; @@ -33,11 +33,11 @@ class DatasetInterface extends Interface { super(environment, type); } - List defaultGraphMethods() { - return membersAnnotatedWithAny(DefaultGraph.class); + Stream defaultGraphMethods() { + return membersAnnotatedWith(DefaultGraph.class); } - List namedGraphMethods() { - return membersAnnotatedWithAny(NamedGraph.class); + Stream namedGraphMethods() { + return membersAnnotatedWith(NamedGraph.class); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index d7f9fb1e5..f9a2ff6b4 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -28,7 +28,6 @@ import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; class GraphImplementor extends Implementor { GraphImplementor(final ProcessingEnvironment environment, final Element element) { @@ -48,31 +47,25 @@ protected void implementInternal() { myInterface.transitiveResourceTypes().map(this::asImplementation).forEach(myClass::addToPersonality); - for (final ExecutableElement method : myInterface.instanceMethods()) { - myClass.addResourceMethod( - typeOf(method.getReturnType()), - method.getSimpleName().toString(), - "optionalFirstInstanceOfEither", - asImplementation(method.getReturnType()), - method.getAnnotation(OptionalFirstInstanceOfEither.class).value()); - } + myInterface.instanceMethods().forEach(method -> myClass.addResourceMethod( + typeOf(method.getReturnType()), + method.getSimpleName().toString(), + "optionalFirstInstanceOfEither", + asImplementation(method.getReturnType()), + method.getAnnotation(OptionalFirstInstanceOfEither.class).value())); - for (final ExecutableElement method : myInterface.subjectMethods()) { - myClass.addResourceMethod( - typeOf(method.getReturnType()), - method.getSimpleName().toString(), - "optionalFirstSubjectOfEither", - asImplementation(method.getReturnType()), - method.getAnnotation(OptionalFirstSubjectOfEither.class).value()); - } + myInterface.subjectMethods().forEach(method -> myClass.addResourceMethod( + typeOf(method.getReturnType()), + method.getSimpleName().toString(), + "optionalFirstSubjectOfEither", + asImplementation(method.getReturnType()), + method.getAnnotation(OptionalFirstSubjectOfEither.class).value())); - for (final ExecutableElement method : myInterface.objectMethods()) { - myClass.addResourceMethod( - typeOf(method.getReturnType()), - method.getSimpleName().toString(), - "optionalFirstObjectOfEither", - asImplementation(method.getReturnType()), - method.getAnnotation(OptionalFirstObjectOfEither.class).value()); - } + myInterface.objectMethods().forEach(method -> myClass.addResourceMethod( + typeOf(method.getReturnType()), + method.getSimpleName().toString(), + "optionalFirstObjectOfEither", + asImplementation(method.getReturnType()), + method.getAnnotation(OptionalFirstObjectOfEither.class).value())); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java index c53354f23..f09c986e8 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java @@ -26,7 +26,6 @@ import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; -import java.util.List; import java.util.stream.Stream; import javax.lang.model.element.ExecutableElement; @@ -49,24 +48,20 @@ Stream transitiveResourceTypes() { .distinct(); } - List instanceMethods() { - return membersAnnotatedWithAny(OptionalFirstInstanceOfEither.class); + Stream instanceMethods() { + return membersAnnotatedWith(OptionalFirstInstanceOfEither.class); } - List subjectMethods() { - return membersAnnotatedWithAny(OptionalFirstSubjectOfEither.class); + Stream subjectMethods() { + return membersAnnotatedWith(OptionalFirstSubjectOfEither.class); } - List objectMethods() { - return membersAnnotatedWithAny(OptionalFirstObjectOfEither.class); + Stream objectMethods() { + return membersAnnotatedWith(OptionalFirstObjectOfEither.class); } private Stream resourceMethodTypes() { - return membersAnnotatedWithAny( - OptionalFirstInstanceOfEither.class, - OptionalFirstSubjectOfEither.class, - OptionalFirstObjectOfEither.class) - .stream() + return concat(concat(instanceMethods(), subjectMethods()), objectMethods()) .map(ExecutableElement::getReturnType) .distinct(); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java index 25ba4e4b9..fd0205389 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -21,9 +21,7 @@ package com.inrupt.rdf.wrapping.processor; import java.lang.annotation.Annotation; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; @@ -38,15 +36,11 @@ class Interface { this.type = type; } - @SafeVarargs - protected final List membersAnnotatedWithAny( - final Class... annotations) { - + protected final Stream membersAnnotatedWith(final Class annotation) { return environment.methodsOf(type).stream() .filter(method -> !method.isDefault()) .filter(method -> !method.getModifiers().contains(Modifier.STATIC)) .filter(method -> !environment.isVoid(method.getReturnType())) - .filter(method -> Arrays.stream(annotations).anyMatch(a -> method.getAnnotation(a) != null)) - .collect(Collectors.toList()); + .filter(method -> method.getAnnotation(annotation) != null); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 40cf5443b..beae5b9f3 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -26,7 +26,6 @@ import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; class ResourceImplementor extends Implementor { ResourceImplementor(final ProcessingEnvironment environment, final Element element) { @@ -44,22 +43,16 @@ protected void implementInternal() { myClass.annotateAndDocument(); myClass.addConstructor(); - for (final ExecutableElement method : myInterface.primitivePropertyMethods()) { - myClass.addPrimitivePropertyMethod( - typeOf(method.getReturnType()), - method.getSimpleName().toString(), - method.getAnnotation(Property.class).mapping().getMethodName(), - method.getAnnotation(Property.class).predicate() - ); - } - - for (final ExecutableElement method : myInterface.resourcePropertyMethods()) { - myClass.addResourcePropertyMethod( - typeOf(method.getReturnType()), - method.getSimpleName().toString(), - method.getAnnotation(Property.class).predicate(), - asImplementation(method.getReturnType()) - ); - } + myInterface.primitivePropertyMethods().forEach(method -> myClass.addPrimitivePropertyMethod( + typeOf(method.getReturnType()), + method.getSimpleName().toString(), + method.getAnnotation(Property.class).mapping().getMethodName(), + method.getAnnotation(Property.class).predicate())); + + myInterface.resourcePropertyMethods().forEach(method -> myClass.addResourcePropertyMethod( + typeOf(method.getReturnType()), + method.getSimpleName().toString(), + method.getAnnotation(Property.class).predicate(), + asImplementation(method.getReturnType()))); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java index 17b114f08..30c78edbd 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java @@ -25,9 +25,7 @@ import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; -import java.util.List; import java.util.function.Predicate; -import java.util.stream.Collectors; import java.util.stream.Stream; import javax.lang.model.element.ExecutableElement; @@ -39,23 +37,18 @@ class ResourceInterface extends Interface { super(environment, type); } - List primitivePropertyMethods() { - return membersAnnotatedWithAny(Property.class).stream() - .filter(returnTypeIsResource().negate()) - .collect(Collectors.toList()); + Stream primitivePropertyMethods() { + return membersAnnotatedWith(Property.class).filter(returnTypeIsResource().negate()); } - List resourcePropertyMethods() { - return membersAnnotatedWithAny(Property.class).stream() - .filter(returnTypeIsResource()) - .collect(Collectors.toList()); + Stream resourcePropertyMethods() { + return membersAnnotatedWith(Property.class).filter(returnTypeIsResource()); } Stream transitiveResourceTypes() { - final Stream children = resourcePropertyMethods().stream() - .map(ExecutableElement::getReturnType); + final Stream children = resourcePropertyMethods().map(ExecutableElement::getReturnType); - final Stream descendants = resourcePropertyMethods().stream() + final Stream descendants = resourcePropertyMethods() .map(ExecutableElement::getReturnType) .map(environment::type) .map(type -> new ResourceInterface(environment, type)) From 0040216a18b721b5177adf81e80231df555d10ea Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 15 Oct 2023 16:08:55 +0100 Subject: [PATCH 063/141] Tidy implementation --- .../processor/DatasetImplementation.java | 42 +++++---- .../processor/DatasetImplementor.java | 19 +---- .../processor/GraphImplementation.java | 47 +++++----- .../wrapping/processor/GraphImplementor.java | 19 ++--- .../wrapping/processor/Implementation.java | 85 +++++++++++++++++++ .../rdf/wrapping/processor/Implementor.java | 19 +---- .../rdf/wrapping/processor/Manager.java | 4 +- .../processor/ResourceImplementation.java | 71 ++++++---------- .../processor/ResourceImplementor.java | 20 +---- 9 files changed, 163 insertions(+), 163 deletions(-) create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java index 6c494b515..0e2299287 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java @@ -24,24 +24,25 @@ import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; -import java.time.Instant; +import com.inrupt.rdf.wrapping.annotation.NamedGraph; import javax.annotation.Generated; +import javax.lang.model.element.ExecutableElement; import org.apache.jena.query.Dataset; import org.apache.jena.sparql.core.DatasetGraph; import org.apache.jena.sparql.core.DatasetImpl; -import org.jboss.jdeparser.JClassDef; +import org.jboss.jdeparser.JExpr; import org.jboss.jdeparser.JMethodDef; import org.jboss.jdeparser.JSourceFile; import org.jboss.jdeparser.JType; -class DatasetImplementation { +class DatasetImplementation extends Implementation { private static final String ORIGINAL = "original"; - static final String WRAP = "wrap"; // TODO: reuse in Manager - - private JClassDef target; + public DatasetImplementation(final EnvironmentHelper environment) { + super(environment); + } void addImports(final JSourceFile source) { source @@ -52,14 +53,7 @@ void addImports(final JSourceFile source) { } void addClass(final JSourceFile source, final String name, final JType originalInterface) { - target = source._class(PUBLIC, name); - target._extends(DatasetImpl.class); - target._implements(originalInterface); - } - - void annotateAndDocument() { - target.docComment().text("Warning, this class consists of generated code."); - target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); + addClass(source, name, originalInterface, DatasetImpl.class); } void addConstructor() { @@ -74,15 +68,19 @@ void addWrap(final JType originalInterface) { myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("asDatasetGraph"))); } - void addDefaultGraph(final JType implementation, final String name, final JType returnType) { - final JMethodDef myMethod = target.method(PUBLIC, returnType, name); - myMethod.annotate(Override.class); - myMethod.body()._return(implementation.call(WRAP).arg(call("getDefaultModel"))); + void addDefaultGraph(final ExecutableElement method) { + addGraph(method, call("getDefaultModel")); } - void addNamedGraph(final JType implementation, final String name, final String graph, final JType returnType) { - final JMethodDef myMethod = target.method(PUBLIC, returnType, name); - myMethod.annotate(Override.class); - myMethod.body()._return(implementation.call(WRAP).arg(call("getNamedModel").arg(str(graph)))); + void addNamedGraph(final ExecutableElement method) { + final String graph = method.getAnnotation(NamedGraph.class).value(); + + addGraph(method, call("getNamedModel").arg(str(graph))); + } + + private void addGraph(final ExecutableElement method, final JExpr expr) { + final JType implementation = asImplementation(method.getReturnType()); + + addMethod(method).body()._return(implementation.call(WRAP).arg(expr)); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index daf1b5fb9..c10e27741 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -20,13 +20,9 @@ */ package com.inrupt.rdf.wrapping.processor; -import com.inrupt.rdf.wrapping.annotation.NamedGraph; - import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; -import org.jboss.jdeparser.JTypes; - class DatasetImplementor extends Implementor { DatasetImplementor(final ProcessingEnvironment environment, final Element element) { super(environment, element); @@ -35,23 +31,14 @@ class DatasetImplementor extends Implementor { @Override protected void implementInternal() { final DatasetInterface myInterface = new DatasetInterface(environment, type); - final DatasetImplementation myClass = new DatasetImplementation(); + final DatasetImplementation myClass = new DatasetImplementation(environment); myClass.addImports(sourceFile); myClass.addClass(sourceFile, implementationClass, originalInterface); - myClass.annotateAndDocument(); myClass.addConstructor(); myClass.addWrap(originalInterface); - myInterface.defaultGraphMethods().forEach(method -> myClass.addDefaultGraph( - asImplementation(method.getReturnType()), - method.getSimpleName().toString(), - JTypes.typeOf(method.getReturnType()))); - - myInterface.namedGraphMethods().forEach(method -> myClass.addNamedGraph( - asImplementation(method.getReturnType()), - method.getSimpleName().toString(), - method.getAnnotation(NamedGraph.class).value(), - JTypes.typeOf(method.getReturnType()))); + myInterface.defaultGraphMethods().forEach(myClass::addDefaultGraph); + myInterface.namedGraphMethods().forEach(myClass::addNamedGraph); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java index f37168e31..6505a867b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.processor.ResourceImplementation.FACTORY; import static org.jboss.jdeparser.JExprs.$v; import static org.jboss.jdeparser.JExprs.call; import static org.jboss.jdeparser.JMod.*; @@ -27,22 +28,24 @@ import com.inrupt.rdf.wrapping.jena.WrapperModel; -import java.time.Instant; - import javax.annotation.Generated; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.type.TypeMirror; import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.impl.ModelCom; import org.jboss.jdeparser.*; -class GraphImplementation { +class GraphImplementation extends Implementation { private static final String ORIGINAL = "original"; - private static final String WRAP = "wrap"; - private JClassDef target; private JMethodDef constructor; + GraphImplementation(final EnvironmentHelper environment) { + super(environment); + } + void addImports(final JSourceFile source) { source ._import(WrapperModel.class) @@ -53,14 +56,7 @@ void addImports(final JSourceFile source) { } void addClass(final JSourceFile source, final String name, final JType originalInterface) { - target = source._class(PUBLIC, name); - target._extends(WrapperModel.class); - target._implements(originalInterface); - } - - void annotateAndDocument() { - target.docComment().text("Warning, this class consists of generated code."); - target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); + addClass(source, name, originalInterface, WrapperModel.class); } void addConstructor() { @@ -75,32 +71,27 @@ void addWrap(final JType originalInterface) { myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("getGraph"))); } - void addToPersonality(final JType implementationType) { + void addToPersonality(final TypeMirror type) { + final JType implementation = asImplementation(type); + constructor .body() .call(call("getPersonality"), "add") - .arg(implementationType._class()) - .arg(implementationType.field(ResourceImplementation.FACTORY)); + .arg(implementation._class()) + .arg(implementation.field(FACTORY)); } - void addResourceMethod( - final JType returnType, - final String name, - final String convenience, - final JType implementationType, - final String[] values) { - - final JMethodDef myMethod = target.method(PUBLIC, returnType, name); - myMethod.annotate(Override.class); + void addResourceMethod(final ExecutableElement method, final String convenience, final String[] values) { + final JType implementation = asImplementation(method.getReturnType()); // Call model wrapper convenience method passing projection class argument - final JCall wrapperConvenienceCall = call(convenience).arg(implementationType._class()); + final JCall convenienceCall = call(convenience).arg(implementation._class()); // Pass each filter value from the annotation as additional argument for (final String value : values) { - wrapperConvenienceCall.arg(JExprs.str(value)); + convenienceCall.arg(JExprs.str(value)); } - myMethod.body()._return(wrapperConvenienceCall); + addMethod(method).body()._return(convenienceCall); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index f9a2ff6b4..f68b14596 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -20,8 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JTypes.typeOf; - import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; @@ -37,35 +35,28 @@ class GraphImplementor extends Implementor { @Override protected void implementInternal() { final GraphInterface myInterface = new GraphInterface(environment, type); - final GraphImplementation myClass = new GraphImplementation(); + final GraphImplementation myClass = new GraphImplementation(environment); myClass.addImports(sourceFile); myClass.addClass(sourceFile, implementationClass, originalInterface); - myClass.annotateAndDocument(); myClass.addConstructor(); myClass.addWrap(originalInterface); - myInterface.transitiveResourceTypes().map(this::asImplementation).forEach(myClass::addToPersonality); + myInterface.transitiveResourceTypes().forEach(myClass::addToPersonality); myInterface.instanceMethods().forEach(method -> myClass.addResourceMethod( - typeOf(method.getReturnType()), - method.getSimpleName().toString(), + method, "optionalFirstInstanceOfEither", - asImplementation(method.getReturnType()), method.getAnnotation(OptionalFirstInstanceOfEither.class).value())); myInterface.subjectMethods().forEach(method -> myClass.addResourceMethod( - typeOf(method.getReturnType()), - method.getSimpleName().toString(), + method, "optionalFirstSubjectOfEither", - asImplementation(method.getReturnType()), method.getAnnotation(OptionalFirstSubjectOfEither.class).value())); myInterface.objectMethods().forEach(method -> myClass.addResourceMethod( - typeOf(method.getReturnType()), - method.getSimpleName().toString(), + method, "optionalFirstObjectOfEither", - asImplementation(method.getReturnType()), method.getAnnotation(OptionalFirstObjectOfEither.class).value())); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java new file mode 100644 index 000000000..6e7569d23 --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java @@ -0,0 +1,85 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static org.jboss.jdeparser.JMod.PUBLIC; +import static org.jboss.jdeparser.JTypes.$t; +import static org.jboss.jdeparser.JTypes.typeOf; + +import java.time.Instant; + +import javax.annotation.Generated; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +import org.jboss.jdeparser.JClassDef; +import org.jboss.jdeparser.JMethodDef; +import org.jboss.jdeparser.JSourceFile; +import org.jboss.jdeparser.JType; + +abstract class Implementation { + static final String WRAP = "wrap"; + + private final EnvironmentHelper environment; + protected JClassDef target; + + Implementation(final EnvironmentHelper environment) { + this.environment = environment; + } + + protected void annotateAndDocument() { + target.docComment().text("Warning, this class consists of generated code."); + target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); + } + + protected void addClass(final JSourceFile source, final String name, final JType original, final Class clazz) { + target = source._class(PUBLIC, name); + target._extends(clazz); + target._implements(original); + + annotateAndDocument(); + } + + protected JMethodDef addMethod(final ExecutableElement method) { + final String myName = method.getSimpleName().toString(); + final JType myType = typeOf(method.getReturnType()); + + final JMethodDef myMethod = target.method(PUBLIC, myType, myName); + myMethod.annotate(Override.class); + + return myMethod; + } + + protected JType asImplementation(final TypeMirror original) { + final TypeElement returnType = environment.type(original); + final String originalBinaryName = environment + .getElementUtils() + .getBinaryName(returnType) + .toString(); + + return $t(asImplementation(originalBinaryName)); + } + + static String asImplementation(final String original) { + return original + "_$impl"; + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 4e520c6bb..652ea36e4 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JTypes.$t; +import static com.inrupt.rdf.wrapping.processor.Implementation.asImplementation; import static org.jboss.jdeparser.JTypes.typeOf; import com.inrupt.rdf.wrapping.annotation.Dataset; @@ -32,13 +32,10 @@ import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; import org.jboss.jdeparser.*; abstract class Implementor { - protected static final String WRAP = "wrap"; // TODO: Sunset - protected final EnvironmentHelper environment; protected final TypeElement type; protected final JSources sources; @@ -86,18 +83,4 @@ static Implementor get(final ProcessingEnvironment env, final Element element) { throw new RuntimeException("unknown annotation type"); } } - - static String asImplementation(final String original) { - return original + "_$impl"; - } - - protected JType asImplementation(final TypeMirror original) { - final TypeElement returnType = environment.type(original); - final String originalBinaryName = environment - .getElementUtils() - .getBinaryName(returnType) - .toString(); - - return $t(asImplementation(originalBinaryName)); - } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java index 67c917016..41572485f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java @@ -20,8 +20,8 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.processor.Implementor.WRAP; -import static com.inrupt.rdf.wrapping.processor.Implementor.asImplementation; +import static com.inrupt.rdf.wrapping.processor.Implementation.WRAP; +import static com.inrupt.rdf.wrapping.processor.Implementation.asImplementation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java index 70dcc84cc..3b1d5b434 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java @@ -24,23 +24,25 @@ import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; +import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; import com.inrupt.rdf.wrapping.jena.ValueMappings; import com.inrupt.rdf.wrapping.jena.WrapperResource; -import java.time.Instant; - import javax.annotation.Generated; +import javax.lang.model.element.ExecutableElement; import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.enhanced.Implementation; import org.apache.jena.graph.Node; import org.jboss.jdeparser.*; -class ResourceImplementation { +class ResourceImplementation extends com.inrupt.rdf.wrapping.processor.Implementation { static final String FACTORY = "factory"; - private JClassDef target; + ResourceImplementation(final EnvironmentHelper environment) { + super(environment); + } void addImports(final JSourceFile source) { source @@ -54,9 +56,7 @@ void addImports(final JSourceFile source) { } void addClass(final JSourceFile source, final String name, final JType originalInterface) { - target = source._class(PUBLIC, name); - target._extends(WrapperResource.class); - target._implements(originalInterface); + addClass(source, name, originalInterface, WrapperResource.class); } void addFactoryField() { @@ -67,56 +67,35 @@ void addFactoryField() { $t(UriOrBlankFactory.class)._new().arg($t(target).methodRef("new"))); } - void annotateAndDocument() { - target.docComment().text("Warning, this class consists of generated code."); - target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); - } - void addConstructor() { + final String node = "node"; + final String graph = "graph"; + final JMethodDef myConstructor = target.constructor(PROTECTED); - myConstructor.param(FINAL, Node.class, "node"); - myConstructor.param(FINAL, EnhGraph.class, "graph"); - myConstructor.body().callSuper().arg($v("node")).arg($v("graph")); + myConstructor.param(FINAL, Node.class, node); + myConstructor.param(FINAL, EnhGraph.class, graph); + myConstructor.body().callSuper().arg($v(node)).arg($v(graph)); } - void addPrimitivePropertyMethod( - final JType returnType, - final String name, - final String mappingMethodName, - final String predicate) { - - addPropertyMethod( - returnType, - name, - predicate, - $t(ValueMappings.class).methodRef(mappingMethodName)); - } + void addPrimitivePropertyMethod(final ExecutableElement method) { + final String mappingMethodName = method.getAnnotation(Property.class).mapping().getMethodName(); + final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); - void addResourcePropertyMethod( - final JType returnType, - final String name, - final String predicate, - final JType implementation) { - - addPropertyMethod( - returnType, - name, - predicate, - $t(ValueMappings.class).call("as").arg(implementation._class())); + addPropertyMethod(method, mapping); } - private void addPropertyMethod( - final JType returnType, - final String name, - final String predicateFromAnnotation, - final JExpr mapping) { + void addResourcePropertyMethod(final ExecutableElement method) { + final JType implementation = asImplementation(method.getReturnType()); + final JCall mapping = $t(ValueMappings.class).call("as").arg(implementation._class()); - final JMethodDef myMethod = target.method(PUBLIC, returnType, name); - myMethod.annotate(Override.class); + addPropertyMethod(method, mapping); + } + private void addPropertyMethod(final ExecutableElement method, final JExpr mapping) { + final String predicateFromAnnotation = method.getAnnotation(Property.class).predicate(); final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); // TODO: Dynamic cardniality - myMethod.body()._return(call("anyOrNull").arg(predicate).arg(mapping)); + addMethod(method).body()._return(call("anyOrNull").arg(predicate).arg(mapping)); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index beae5b9f3..8626c0012 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -20,10 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JTypes.typeOf; - -import com.inrupt.rdf.wrapping.annotation.Property; - import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; @@ -35,24 +31,14 @@ class ResourceImplementor extends Implementor { @Override protected void implementInternal() { final ResourceInterface myInterface = new ResourceInterface(environment, type); - final ResourceImplementation myClass = new ResourceImplementation(); + final ResourceImplementation myClass = new ResourceImplementation(environment); myClass.addImports(sourceFile); myClass.addClass(sourceFile, implementationClass, originalInterface); myClass.addFactoryField(); - myClass.annotateAndDocument(); myClass.addConstructor(); - myInterface.primitivePropertyMethods().forEach(method -> myClass.addPrimitivePropertyMethod( - typeOf(method.getReturnType()), - method.getSimpleName().toString(), - method.getAnnotation(Property.class).mapping().getMethodName(), - method.getAnnotation(Property.class).predicate())); - - myInterface.resourcePropertyMethods().forEach(method -> myClass.addResourcePropertyMethod( - typeOf(method.getReturnType()), - method.getSimpleName().toString(), - method.getAnnotation(Property.class).predicate(), - asImplementation(method.getReturnType()))); + myInterface.primitivePropertyMethods().forEach(myClass::addPrimitivePropertyMethod); + myInterface.resourcePropertyMethods().forEach(myClass::addResourcePropertyMethod); } } From 7fca8f0bced85cf35dda6546c88b56184fb070cc Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 21 Oct 2023 14:28:34 +0100 Subject: [PATCH 064/141] Cover Mapping->ValueMappings equivalence --- annotation/pom.xml | 25 +++++++ .../rdf/wrapping/annotation/MappingTest.java | 70 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java diff --git a/annotation/pom.xml b/annotation/pom.xml index f85aab6bd..d67ae2f8d 100644 --- a/annotation/pom.xml +++ b/annotation/pom.xml @@ -15,6 +15,31 @@ 1.8 + + + com.inrupt.rdf + inrupt-rdf-wrapping-jena + ${project.version} + test + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.hamcrest + hamcrest + test + + + diff --git a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java new file mode 100644 index 000000000..e4dae4a5c --- /dev/null +++ b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java @@ -0,0 +1,70 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.annotation; + +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping; +import static java.lang.reflect.Modifier.isPublic; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.toList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.in; +import static org.hamcrest.Matchers.is; + +import com.inrupt.rdf.wrapping.jena.ValueMappings; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.MethodSource; + +@DisplayName("Mapping") +class MappingTest { + private static final Collection MAPPING_METHODS = mappingMethods().collect(toList()); + private static final Collection ENUM_CONSTANTS = stream(Mapping.class.getEnumConstants()) + .map(Mapping::getMethodName) + .collect(toList()); + + @DisplayName("has equivalent ValueMappings method for enum constant") + @ParameterizedTest(name = "{0}") + @EnumSource(Mapping.class) + void constantHasEquivalentMethod(final Mapping mapping) { + assertThat(mapping.getMethodName(), is(in(MAPPING_METHODS))); + } + + @Disabled("not ready yet") // TODO: Enable when ready + @DisplayName("has enum constant equivalent to ValueMappings method") + @ParameterizedTest(name = "{0}") + @MethodSource("mappingMethods") + void methodHasEquivalentConstant(final String method) { + assertThat(method, is(in(ENUM_CONSTANTS))); + } + + private static Stream mappingMethods() { + return stream(ValueMappings.class.getDeclaredMethods()) + .filter(method -> isPublic(method.getModifiers())) + .map(Method::getName); + } +} From ccbb2f8367e712efeb6846c506a811bc0516fa62 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 21 Oct 2023 15:04:08 +0100 Subject: [PATCH 065/141] Typo --- .../bad/resource property method is static.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is static.java b/processor/src/test/resources/validationExamples/bad/resource property method is static.java index edade6193..de6b44177 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is static.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is static.java @@ -9,7 +9,7 @@ @Resource interface X { @Property(predicate = "x", mapping = IRI_AS_STRING) - default Object x() { + static Object x() { return null; } } From 94d5a617668f3bd1179afa843463798f546f330f Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 21 Oct 2023 15:13:39 +0100 Subject: [PATCH 066/141] Leaner validation error --- .../wrapping/processor/ValidationError.java | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java index 900fcb9a5..09655e605 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java @@ -21,36 +21,19 @@ package com.inrupt.rdf.wrapping.processor; import javax.annotation.processing.Messager; -import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.tools.Diagnostic; class ValidationError { private final Element element; - private final AnnotationMirror annotation; private final String msg; - ValidationError(final Element element, final AnnotationMirror annotation, final String msg, final Object... args) { + ValidationError(final Element element, final String msg, final Object... args) { this.element = element; - this.annotation = annotation; this.msg = String.format(msg, args); } - ValidationError(final Element element, final String msg, final Object... args) { - this(element, null, msg, args); - } - void printMessage(final Messager messager) { - if (element == null) { - messager.printMessage(Diagnostic.Kind.ERROR, msg); - return; - } - - if (annotation == null) { - messager.printMessage(Diagnostic.Kind.ERROR, msg, element); - return; - } - - messager.printMessage(Diagnostic.Kind.ERROR, msg, element, annotation); + messager.printMessage(Diagnostic.Kind.ERROR, msg, element); } } From e9190ebd6cb105d0e8259703d70f6db14f876b1b Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 21 Oct 2023 15:15:54 +0100 Subject: [PATCH 067/141] Validate that complex property methods of resource interfaces return resource interfaces --- .../wrapping/processor/ResourceValidator.java | 39 +++++++++++++------ .../rdf/wrapping/processor/ValidatorTest.java | 6 ++- ...mplex property method is not resource.java | 13 +++++++ ... property method is resource instance.java | 13 +++++++ 4 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java create mode 100644 processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index a252c48de..a589afc83 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -21,6 +21,7 @@ package com.inrupt.rdf.wrapping.processor; import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.jena.ValueMappings; import javax.annotation.processing.ProcessingEnvironment; @@ -29,8 +30,6 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -import org.apache.jena.rdf.model.Resource; - class ResourceValidator extends Validator { ResourceValidator(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { super(annotation, env, element); @@ -40,20 +39,20 @@ class ResourceValidator extends Validator { protected void validateInternal() { requireInterface(); - limitBaseInterfaces(Resource.class); + limitBaseInterfaces(org.apache.jena.rdf.model.Resource.class); requireMemberMethods(Property.class); requireNonMemberMethods(Property.class); - requireCompatibleReturnType(); + requireCompatiblePrimitiveReturnType(); + requireCompatibleComplexReturnType(); } - private void requireCompatibleReturnType() { + private void requireCompatiblePrimitiveReturnType() { for (final ExecutableElement method : env.methodsOf(element)) { final Property propertyAnnotation = method.getAnnotation(Property.class); if (propertyAnnotation != null) { - // TODO: Validate otherwise if (propertyAnnotation.mapping() == Property.Mapping.AS) { continue; } @@ -74,13 +73,31 @@ private void requireCompatibleReturnType() { } } - private TypeMirror returnTypeOfMapper(final String mappingMethod) { - for (final ExecutableElement m : env.methodsOf(ValueMappings.class)) { - if (m.getSimpleName().contentEquals(mappingMethod)) { - return m.getReturnType(); + private void requireCompatibleComplexReturnType() { + for (final ExecutableElement method : env.methodsOf(element)) { + final Property propertyAnnotation = method.getAnnotation(Property.class); + if (propertyAnnotation != null) { + if (propertyAnnotation.mapping() != Property.Mapping.AS) { + continue; + } + + if (env.type(method.getReturnType()).getAnnotation(Resource.class) == null) { + errors.add(new ValidationError( + method, + "Method %s on interface %s annotated with @%s must return @Resource interface", + method.getSimpleName(), + element.getSimpleName(), + annotation.getSimpleName())); + } } } + } - return null; + private TypeMirror returnTypeOfMapper(final String mappingMethod) { + return env.methodsOf(ValueMappings.class).stream() + .filter(method -> method.getSimpleName().contentEquals(mappingMethod)) + .map(ExecutableElement::getReturnType) + .findFirst() + .orElse(null); } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 682e18af8..e358722de 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -92,7 +92,8 @@ private static Stream compilationErrorOnInvalid() { arguments("resource property method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("resource property method is default", CANNOT_BE_STATIC_OR_DEFAULT), arguments("resource instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), - arguments("resource property method return type not assignable", "must be assignable from return type") + arguments("resource property method return type not assignable", "must be assignable from return type"), + arguments("resource complex property method is not resource", MUST_RETURN_RESOURCE_INTERFACE) ); } @@ -127,7 +128,8 @@ private static Stream compilationSucceeds() { arguments("resource extends Resource"), arguments("resource property method is assignable instance"), arguments("resource unannotated method is static"), - arguments("resource unannotated method is default") + arguments("resource unannotated method is default"), + arguments("resource complex property method is resource instance") ); } diff --git a/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java b/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java new file mode 100644 index 000000000..aa8f7cfe4 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + @Property(predicate = "x", mapping = AS) + Object x(); +} diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java b/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java new file mode 100644 index 000000000..3c4f51331 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + @Property(predicate = "x", mapping = AS) + X x(); +} From d0b350035754ca4e18c92cae971ff48800977186 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 21 Oct 2023 15:20:03 +0100 Subject: [PATCH 068/141] Cleanup --- .../inrupt/rdf/wrapping/processor/DatasetImplementation.java | 2 +- .../com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java | 2 +- .../src/test/java/com/inrupt/rdf/wrapping/processor/X.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java index 0e2299287..607e1e693 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java @@ -40,7 +40,7 @@ class DatasetImplementation extends Implementation { private static final String ORIGINAL = "original"; - public DatasetImplementation(final EnvironmentHelper environment) { + DatasetImplementation(final EnvironmentHelper environment) { super(environment); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java index 2795eb265..50ff6d9a3 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java @@ -63,7 +63,7 @@ List methodsOf(final Element element) { return ElementFilter.methodsIn(element.getEnclosedElements()); } - public List methodsOf(final Class clazz) { + List methodsOf(final Class clazz) { return methodsOf(type(clazz)); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java index 9467a6853..16292bf1c 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java @@ -29,7 +29,7 @@ import org.apache.jena.rdf.model.Model; @Dataset -public interface X { +interface X { static X wrap(final org.apache.jena.query.Dataset original) { return Manager.wrap(original, X.class); } From 645f938540a4668cd0bab7fd0f458a59e0a1f877 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 21 Oct 2023 16:45:25 +0100 Subject: [PATCH 069/141] Tidy --- .../wrapping/processor/EnvironmentHelper.java | 8 +-- .../rdf/wrapping/processor/Interface.java | 2 +- .../wrapping/processor/ResourceValidator.java | 68 ++++++++----------- .../rdf/wrapping/processor/Validator.java | 11 +-- 4 files changed, 38 insertions(+), 51 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java index 50ff6d9a3..bedfebd5c 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java @@ -22,9 +22,9 @@ import com.inrupt.rdf.wrapping.jena.ValueMappings; -import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.stream.Stream; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; @@ -59,11 +59,11 @@ boolean isSameType(final TypeMirror t1, final Class t2) { return getTypeUtils().isSameType(t1, mirror(t2)); } - List methodsOf(final Element element) { - return ElementFilter.methodsIn(element.getEnclosedElements()); + Stream methodsOf(final Element element) { + return ElementFilter.methodsIn(element.getEnclosedElements()).stream(); } - List methodsOf(final Class clazz) { + Stream methodsOf(final Class clazz) { return methodsOf(type(clazz)); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java index fd0205389..86afe50e6 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -37,7 +37,7 @@ class Interface { } protected final Stream membersAnnotatedWith(final Class annotation) { - return environment.methodsOf(type).stream() + return environment.methodsOf(type) .filter(method -> !method.isDefault()) .filter(method -> !method.getModifiers().contains(Modifier.STATIC)) .filter(method -> !environment.isVoid(method.getReturnType())) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index a589afc83..3b59da662 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -50,51 +50,43 @@ protected void validateInternal() { } private void requireCompatiblePrimitiveReturnType() { - for (final ExecutableElement method : env.methodsOf(element)) { - final Property propertyAnnotation = method.getAnnotation(Property.class); - if (propertyAnnotation != null) { - if (propertyAnnotation.mapping() == Property.Mapping.AS) { - continue; - } + env.methodsOf(element) + .filter(method -> method.getAnnotation(Property.class) != null) + .filter(method -> method.getAnnotation(Property.class).mapping() != Property.Mapping.AS) + .forEach(method -> { + final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); + final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); - final String mappingMethod = propertyAnnotation.mapping().getMethodName(); - final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); - - if (!env.getTypeUtils().isAssignable(mappingMethodReturnType, method.getReturnType())) { - errors.add(new ValidationError( - method, - "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", - method.getReturnType(), - method.getSimpleName(), - mappingMethodReturnType, - mappingMethod)); - } - } - } + if (!env.getTypeUtils().isAssignable(mappingMethodReturnType, method.getReturnType())) { + errors.add(new ValidationError( + method, + "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", + method.getReturnType(), + method.getSimpleName(), + mappingMethodReturnType, + mappingMethod)); + } + }); } private void requireCompatibleComplexReturnType() { - for (final ExecutableElement method : env.methodsOf(element)) { - final Property propertyAnnotation = method.getAnnotation(Property.class); - if (propertyAnnotation != null) { - if (propertyAnnotation.mapping() != Property.Mapping.AS) { - continue; - } - - if (env.type(method.getReturnType()).getAnnotation(Resource.class) == null) { - errors.add(new ValidationError( - method, - "Method %s on interface %s annotated with @%s must return @Resource interface", - method.getSimpleName(), - element.getSimpleName(), - annotation.getSimpleName())); - } - } - } + env.methodsOf(element) + .filter(method -> method.getAnnotation(Property.class) != null) + .filter(method -> method.getAnnotation(Property.class).mapping() == Property.Mapping.AS) + .forEach(method -> { + if (env.type(method.getReturnType()).getAnnotation(Resource.class) == null) { + errors.add(new ValidationError( + method, + "Method %s on interface %s annotated with @%s must return @Resource interface", + method.getSimpleName(), + element.getSimpleName(), + annotation.getSimpleName())); + } + }); } private TypeMirror returnTypeOfMapper(final String mappingMethod) { - return env.methodsOf(ValueMappings.class).stream() + return env.methodsOf(ValueMappings.class) .filter(method -> method.getSimpleName().contentEquals(mappingMethod)) .map(ExecutableElement::getReturnType) .findFirst() diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index c9d096766..12ef9d49a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -29,7 +29,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.function.Predicate; -import java.util.stream.Stream; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; @@ -77,7 +76,7 @@ protected void requireMemberMethods(final Class annotation final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; - getMethods() + env.methodsOf(element) .filter(isNotMember) .filter(isAnnotated) .forEach(method -> errors.add(new ValidationError( @@ -96,7 +95,7 @@ protected final void requireNonMemberMethods(final Class.. final Predicate isUnannotated = method -> Arrays.stream(annotations).noneMatch(a -> method.getAnnotation(a) != null); - getMethods() + env.methodsOf(element) .filter(isMember) .filter(isUnannotated) .forEach(method -> errors.add(new ValidationError( @@ -148,7 +147,7 @@ protected void requireAnnotatedReturnType( final Predicate isNotResource = method -> env.type(method.getReturnType()).getAnnotation(required) == null; - getMethods() + env.methodsOf(element) .filter(isAnnotated) .filter(isNotResource) .forEach(method -> errors.add(new ValidationError( @@ -159,8 +158,4 @@ protected void requireAnnotatedReturnType( annotation.getSimpleName(), required.getSimpleName()))); } - - protected Stream getMethods() { - return env.methodsOf(element).stream(); - } } From c98f01bc82169bebe19229f32ba4cc65c73a6066 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 17 Feb 2024 12:40:11 +0000 Subject: [PATCH 070/141] This was so long ago that I don't remember Implementor became generic, which sounds reasonable. Validation pipeline has become simpler. New test probably improves coverage. --- processor/pom.xml | 5 ++ .../processor/DatasetImplementation.java | 4 +- .../processor/DatasetImplementor.java | 12 +-- .../wrapping/processor/DatasetInterface.java | 4 +- .../wrapping/processor/DatasetValidator.java | 6 +- ...nvironmentHelper.java => Environment.java} | 22 +++--- .../processor/GraphImplementation.java | 4 +- .../wrapping/processor/GraphImplementor.java | 12 +-- .../wrapping/processor/GraphInterface.java | 8 +- .../wrapping/processor/GraphValidator.java | 6 +- .../wrapping/processor/Implementation.java | 10 +-- .../rdf/wrapping/processor/Implementor.java | 41 +++++----- .../rdf/wrapping/processor/Interface.java | 10 +-- .../rdf/wrapping/processor/Processor.java | 38 +++++----- .../processor/ResourceImplementation.java | 4 +- .../processor/ResourceImplementor.java | 12 +-- .../wrapping/processor/ResourceInterface.java | 10 +-- .../wrapping/processor/ResourceValidator.java | 15 ++-- .../wrapping/processor/ValidationError.java | 5 +- .../rdf/wrapping/processor/Validator.java | 74 +++++++++---------- .../wrapping/processor/ImplementorTest.java | 69 +++++++++++++++++ 21 files changed, 211 insertions(+), 160 deletions(-) rename processor/src/main/java/com/inrupt/rdf/wrapping/processor/{EnvironmentHelper.java => Environment.java} (86%) create mode 100644 processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java diff --git a/processor/pom.xml b/processor/pom.xml index 38f8028c9..bcfd6a8d6 100644 --- a/processor/pom.xml +++ b/processor/pom.xml @@ -53,6 +53,11 @@ compile-testing test + + org.mockito + mockito-core + test + diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java index 607e1e693..5b1d35eb4 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java @@ -40,8 +40,8 @@ class DatasetImplementation extends Implementation { private static final String ORIGINAL = "original"; - DatasetImplementation(final EnvironmentHelper environment) { - super(environment); + DatasetImplementation(final Environment env) { + super(env); } void addImports(final JSourceFile source) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index c10e27741..8fa9c9dd8 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -20,19 +20,15 @@ */ package com.inrupt.rdf.wrapping.processor; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; -class DatasetImplementor extends Implementor { - DatasetImplementor(final ProcessingEnvironment environment, final Element element) { - super(environment, element); +class DatasetImplementor extends Implementor { + DatasetImplementor(final TypeElement type, final Environment env) { + super(type, new DatasetInterface(type, env), new DatasetImplementation(env), env); } @Override protected void implementInternal() { - final DatasetInterface myInterface = new DatasetInterface(environment, type); - final DatasetImplementation myClass = new DatasetImplementation(environment); - myClass.addImports(sourceFile); myClass.addClass(sourceFile, implementationClass, originalInterface); myClass.addConstructor(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java index 0cfd682af..e1a6b0b87 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java @@ -29,8 +29,8 @@ import javax.lang.model.element.TypeElement; class DatasetInterface extends Interface { - DatasetInterface(final EnvironmentHelper environment, final TypeElement type) { - super(environment, type); + DatasetInterface(final TypeElement type, final Environment env) { + super(type, env); } Stream defaultGraphMethods() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java index fbea0c56b..63235836f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java @@ -24,15 +24,13 @@ import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.NamedGraph; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import org.apache.jena.query.Dataset; class DatasetValidator extends Validator { - DatasetValidator(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { - super(annotation, env, element); + DatasetValidator(final TypeElement type, final Environment env) { + super(type, env); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java similarity index 86% rename from processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java index bedfebd5c..f2adff8e7 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/EnvironmentHelper.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java @@ -38,7 +38,7 @@ import javax.lang.model.util.Elements; import javax.lang.model.util.Types; -class EnvironmentHelper implements ProcessingEnvironment { +class Environment implements ProcessingEnvironment { TypeMirror mirror(final Class clazz) { return type(clazz).asType(); } @@ -68,45 +68,45 @@ Stream methodsOf(final Class clazz) { } // region pass-through - private final ProcessingEnvironment original; + private final ProcessingEnvironment env; - EnvironmentHelper(final ProcessingEnvironment original) { - this.original = original; + Environment(final ProcessingEnvironment env) { + this.env = env; } @Override public Map getOptions() { - return original.getOptions(); + return env.getOptions(); } @Override public Messager getMessager() { - return original.getMessager(); + return env.getMessager(); } @Override public Filer getFiler() { - return original.getFiler(); + return env.getFiler(); } @Override public Elements getElementUtils() { - return original.getElementUtils(); + return env.getElementUtils(); } @Override public Types getTypeUtils() { - return original.getTypeUtils(); + return env.getTypeUtils(); } @Override public SourceVersion getSourceVersion() { - return original.getSourceVersion(); + return env.getSourceVersion(); } @Override public Locale getLocale() { - return original.getLocale(); + return env.getLocale(); } // endregion } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java index 6505a867b..17fdab88c 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java @@ -42,8 +42,8 @@ class GraphImplementation extends Implementation { private JMethodDef constructor; - GraphImplementation(final EnvironmentHelper environment) { - super(environment); + GraphImplementation(final Environment env) { + super(env); } void addImports(final JSourceFile source) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index f68b14596..c42cddef6 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -24,19 +24,15 @@ import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; -class GraphImplementor extends Implementor { - GraphImplementor(final ProcessingEnvironment environment, final Element element) { - super(environment, element); +class GraphImplementor extends Implementor { + GraphImplementor(final TypeElement type, final Environment env) { + super(type, new GraphInterface(type, env), new GraphImplementation(env), env); } @Override protected void implementInternal() { - final GraphInterface myInterface = new GraphInterface(environment, type); - final GraphImplementation myClass = new GraphImplementation(environment); - myClass.addImports(sourceFile); myClass.addClass(sourceFile, implementationClass, originalInterface); myClass.addConstructor(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java index f09c986e8..c85b20d13 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java @@ -33,15 +33,15 @@ import javax.lang.model.type.TypeMirror; class GraphInterface extends Interface { - GraphInterface(final EnvironmentHelper environment, final TypeElement type) { - super(environment, type); + GraphInterface(final TypeElement type, final Environment env) { + super(type, env); } Stream transitiveResourceTypes() { final Stream children = resourceMethodTypes(); final Stream descendants = resourceMethodTypes() - .map(environment::type) - .map(type -> new ResourceInterface(environment, type)) + .map(env::type) + .map(type -> new ResourceInterface(type, env)) .flatMap(ResourceInterface::transitiveResourceTypes); return concat(children, descendants) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java index 0f8ff329a..bd6185cb6 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java @@ -25,15 +25,13 @@ import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; import com.inrupt.rdf.wrapping.annotation.Resource; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import org.apache.jena.rdf.model.Model; class GraphValidator extends Validator { - GraphValidator(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { - super(annotation, env, element); + GraphValidator(final TypeElement type, final Environment env) { + super(type, env); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java index 6e7569d23..898c4c8f0 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java @@ -39,11 +39,11 @@ abstract class Implementation { static final String WRAP = "wrap"; - private final EnvironmentHelper environment; + private final Environment env; protected JClassDef target; - Implementation(final EnvironmentHelper environment) { - this.environment = environment; + Implementation(final Environment env) { + this.env = env; } protected void annotateAndDocument() { @@ -70,8 +70,8 @@ protected JMethodDef addMethod(final ExecutableElement method) { } protected JType asImplementation(final TypeMirror original) { - final TypeElement returnType = environment.type(original); - final String originalBinaryName = environment + final TypeElement returnType = env.type(original); + final String originalBinaryName = env .getElementUtils() .getBinaryName(returnType) .toString(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 652ea36e4..fcb8c7433 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -25,37 +25,33 @@ import com.inrupt.rdf.wrapping.annotation.Dataset; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.Resource; import java.io.IOException; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import org.jboss.jdeparser.*; -abstract class Implementor { - protected final EnvironmentHelper environment; - protected final TypeElement type; +abstract class Implementor { protected final JSources sources; protected final JType originalInterface; protected final JSourceFile sourceFile; - protected final String implementationClass; + protected final T myInterface; + protected final U myClass; - protected Implementor(final ProcessingEnvironment environment, final Element element) { - this.environment = new EnvironmentHelper(environment); - type = (TypeElement) element; + protected Implementor(final TypeElement type, final T myInterface, final U myClass, final Environment env) { + this.myInterface = myInterface; + this.myClass = myClass; originalInterface = typeOf(type.asType()); - final String originalBinaryName = environment.getElementUtils().getBinaryName(type).toString(); + final String originalBinaryName = env.getElementUtils().getBinaryName(type).toString(); final String qualifiedName = asImplementation(originalBinaryName); final int lastDot = originalBinaryName.lastIndexOf('.'); implementationClass = qualifiedName.substring(lastDot + 1); - final String packageName = environment.getElementUtils().getPackageOf(element).getQualifiedName().toString(); + final String packageName = env.getElementUtils().getPackageOf(type).getQualifiedName().toString(); - final JFiler filer = JFiler.newInstance(environment.getFiler()); + final JFiler filer = JFiler.newInstance(env.getFiler()); sources = JDeparser.createSources(filer, new FormatPreferences()); sourceFile = sources.createSourceFile(packageName, implementationClass); } @@ -72,15 +68,16 @@ void implement() { protected abstract void implementInternal(); - static Implementor get(final ProcessingEnvironment env, final Element element) { - if (element.getAnnotation(Dataset.class) != null) { - return new DatasetImplementor(env, element); - } else if (element.getAnnotation(Graph.class) != null) { - return new GraphImplementor(env, element); - } else if (element.getAnnotation(Resource.class) != null) { - return new ResourceImplementor(env, element); - } else { - throw new RuntimeException("unknown annotation type"); + static Implementor implementor(final Environment env, final TypeElement e) { + if (e.getAnnotation(Dataset.class) != null) { + return new DatasetImplementor(e, env); + + } else if (e.getAnnotation(Graph.class) != null) { + return new GraphImplementor(e, env); + + } else { // Resource + // Processor's supported annotations are finite + return new ResourceImplementor(e, env); } } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java index 86afe50e6..602be2a86 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -28,19 +28,19 @@ import javax.lang.model.element.TypeElement; class Interface { - protected final EnvironmentHelper environment; private final TypeElement type; + protected final Environment env; - Interface(final EnvironmentHelper environment, final TypeElement type) { - this.environment = environment; + Interface(final TypeElement type, final Environment env) { + this.env = env; this.type = type; } protected final Stream membersAnnotatedWith(final Class annotation) { - return environment.methodsOf(type) + return env.methodsOf(type) .filter(method -> !method.isDefault()) .filter(method -> !method.getModifiers().contains(Modifier.STATIC)) - .filter(method -> !environment.isVoid(method.getReturnType())) + .filter(method -> !env.isVoid(method.getReturnType())) .filter(method -> method.getAnnotation(annotation) != null); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java index cc51f00b0..9e2614e13 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java @@ -20,48 +20,52 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.processor.Implementor.implementor; +import static com.inrupt.rdf.wrapping.processor.Validator.validator; +import static java.util.stream.Collectors.toSet; +import static javax.lang.model.SourceVersion.RELEASE_8; +import static javax.tools.Diagnostic.Kind.NOTE; + import com.inrupt.rdf.wrapping.annotation.Dataset; import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.Resource; import java.util.ArrayList; -import java.util.HashSet; +import java.util.Collection; import java.util.Set; +import java.util.stream.Stream; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedSourceVersion; -import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; -@SupportedSourceVersion(SourceVersion.RELEASE_8) +@SupportedSourceVersion(RELEASE_8) public class Processor extends AbstractProcessor { @Override public Set getSupportedAnnotationTypes() { - final Set annotations = new HashSet<>(); - - annotations.add(Dataset.class.getName()); - annotations.add(Graph.class.getName()); - annotations.add(Resource.class.getName()); - - return annotations; + return Stream.of(Dataset.class, Graph.class, Resource.class).map(Class::getName).collect(toSet()); } @Override public boolean process(final Set annotations, final RoundEnvironment roundEnv) { if (roundEnv.processingOver()) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "processing over"); + processingEnv.getMessager().printMessage(NOTE, "processing over"); return false; } - final ArrayList implementors = new ArrayList<>(); - final ArrayList validationErrors = new ArrayList<>(); + final Collection> implementors = new ArrayList<>(); + final Collection validationErrors = new ArrayList<>(); + final Environment env = new Environment(processingEnv); + for (final TypeElement annotation : annotations) { - for (final Element annotatedElement : roundEnv.getElementsAnnotatedWith(annotation)) { - implementors.add(Implementor.get(processingEnv, annotatedElement)); - validationErrors.addAll(Validator.get(annotation, processingEnv, annotatedElement).validate()); + for (final Element element : roundEnv.getElementsAnnotatedWith(annotation)) { + // All our annotations are @Target(TYPE), so they're all TypeElements + final TypeElement type = (TypeElement) element; + + implementors.add(implementor(env, type)); + validationErrors.addAll(validator(type, env).validate()); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java index 3b1d5b434..81dbb146e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java @@ -40,8 +40,8 @@ class ResourceImplementation extends com.inrupt.rdf.wrapping.processor.Implementation { static final String FACTORY = "factory"; - ResourceImplementation(final EnvironmentHelper environment) { - super(environment); + ResourceImplementation(final Environment env) { + super(env); } void addImports(final JSourceFile source) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 8626c0012..68a8e53ea 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -20,19 +20,15 @@ */ package com.inrupt.rdf.wrapping.processor; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; -class ResourceImplementor extends Implementor { - ResourceImplementor(final ProcessingEnvironment environment, final Element element) { - super(environment, element); +class ResourceImplementor extends Implementor { + ResourceImplementor(final TypeElement type, final Environment env) { + super(type, new ResourceInterface(type, env), new ResourceImplementation(env), env); } @Override protected void implementInternal() { - final ResourceInterface myInterface = new ResourceInterface(environment, type); - final ResourceImplementation myClass = new ResourceImplementation(environment); - myClass.addImports(sourceFile); myClass.addClass(sourceFile, implementationClass, originalInterface); myClass.addFactoryField(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java index 30c78edbd..2dcbcffb9 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java @@ -33,8 +33,8 @@ import javax.lang.model.type.TypeMirror; class ResourceInterface extends Interface { - ResourceInterface(final EnvironmentHelper environment, final TypeElement type) { - super(environment, type); + ResourceInterface(final TypeElement type, final Environment env) { + super(type, env); } Stream primitivePropertyMethods() { @@ -50,14 +50,14 @@ Stream transitiveResourceTypes() { final Stream descendants = resourcePropertyMethods() .map(ExecutableElement::getReturnType) - .map(environment::type) - .map(type -> new ResourceInterface(environment, type)) + .map(env::type) + .map(type -> new ResourceInterface(type, env)) .flatMap(ResourceInterface::transitiveResourceTypes); return concat(children, descendants).distinct(); } private Predicate returnTypeIsResource() { - return method -> environment.type(method.getReturnType()).getAnnotation(Resource.class) != null; + return method -> env.type(method.getReturnType()).getAnnotation(Resource.class) != null; } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 3b59da662..3f523f207 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -24,15 +24,13 @@ import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.jena.ValueMappings; -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; class ResourceValidator extends Validator { - ResourceValidator(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { - super(annotation, env, element); + ResourceValidator(final TypeElement type, final Environment env) { + super(type, env); } @Override @@ -50,7 +48,7 @@ protected void validateInternal() { } private void requireCompatiblePrimitiveReturnType() { - env.methodsOf(element) + env.methodsOf(type) .filter(method -> method.getAnnotation(Property.class) != null) .filter(method -> method.getAnnotation(Property.class).mapping() != Property.Mapping.AS) .forEach(method -> { @@ -70,17 +68,16 @@ private void requireCompatiblePrimitiveReturnType() { } private void requireCompatibleComplexReturnType() { - env.methodsOf(element) + env.methodsOf(type) .filter(method -> method.getAnnotation(Property.class) != null) .filter(method -> method.getAnnotation(Property.class).mapping() == Property.Mapping.AS) .forEach(method -> { if (env.type(method.getReturnType()).getAnnotation(Resource.class) == null) { errors.add(new ValidationError( method, - "Method %s on interface %s annotated with @%s must return @Resource interface", + "Method %s on interface %s must return @Resource interface", method.getSimpleName(), - element.getSimpleName(), - annotation.getSimpleName())); + type.getSimpleName())); } }); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java index 09655e605..1fc0c7e60 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java @@ -20,9 +20,10 @@ */ package com.inrupt.rdf.wrapping.processor; +import static javax.tools.Diagnostic.Kind.ERROR; + import javax.annotation.processing.Messager; import javax.lang.model.element.Element; -import javax.tools.Diagnostic; class ValidationError { private final Element element; @@ -34,6 +35,6 @@ class ValidationError { } void printMessage(final Messager messager) { - messager.printMessage(Diagnostic.Kind.ERROR, msg, element); + messager.printMessage(ERROR, msg, element); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 12ef9d49a..398dbfded 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -20,9 +20,10 @@ */ package com.inrupt.rdf.wrapping.processor; +import static javax.lang.model.element.Modifier.STATIC; + import com.inrupt.rdf.wrapping.annotation.Dataset; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.Resource; import java.lang.annotation.Annotation; import java.util.ArrayList; @@ -31,34 +32,31 @@ import java.util.function.Predicate; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; // TODO: Use interfaces in validators abstract class Validator { - protected final TypeElement annotation; - protected final EnvironmentHelper env; - protected final Element element; + protected final TypeElement type; + protected final Environment env; protected final Collection errors = new ArrayList<>(); - protected Validator(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { - this.annotation = annotation; - this.env = new EnvironmentHelper(env); - this.element = element; + protected Validator(final TypeElement type, final ProcessingEnvironment env) { + this.env = new Environment(env); + this.type = type; } - static Validator get(final TypeElement annotation, final ProcessingEnvironment env, final Element element) { - if (element.getAnnotation(Dataset.class) != null) { - return new DatasetValidator(annotation, env, element); - } else if (element.getAnnotation(Graph.class) != null) { - return new GraphValidator(annotation, env, element); - } else if (element.getAnnotation(Resource.class) != null) { - return new ResourceValidator(annotation, env, element); - } else { - throw new RuntimeException("unknown annotation type"); + static Validator validator(final TypeElement type, final Environment env) { + if (type.getAnnotation(Dataset.class) != null) { + return new DatasetValidator(type, env); + + } else if (type.getAnnotation(Graph.class) != null) { + return new GraphValidator(type, env); + + } else { // Resource + // Processor's supported annotations are finite + return new ResourceValidator(type, env); } } @@ -72,71 +70,67 @@ Collection validate() { protected void requireMemberMethods(final Class annotation) { final Predicate isNotMember = method -> - method.isDefault() || method.getModifiers().contains(Modifier.STATIC); + method.isDefault() || method.getModifiers().contains(STATIC); final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; - env.methodsOf(element) + env.methodsOf(type) .filter(isNotMember) .filter(isAnnotated) .forEach(method -> errors.add(new ValidationError( method, "Method %s on interface %s annotated with @%s cannot be static or default", method.getSimpleName(), - element.getSimpleName(), + type.getSimpleName(), annotation.getSimpleName()))); } @SafeVarargs protected final void requireNonMemberMethods(final Class... annotations) { final Predicate isMember = method -> - !method.isDefault() && !method.getModifiers().contains(Modifier.STATIC); + !method.isDefault() && !method.getModifiers().contains(STATIC); final Predicate isUnannotated = method -> Arrays.stream(annotations).noneMatch(a -> method.getAnnotation(a) != null); - env.methodsOf(element) + env.methodsOf(type) .filter(isMember) .filter(isUnannotated) .forEach(method -> errors.add(new ValidationError( method, "Unannotated method %s on interface %s must be static or default", method.getSimpleName(), - element.getSimpleName()))); + type.getSimpleName()))); } protected void limitBaseInterfaces(final Class allowed) { - if (!element.getKind().isInterface()) { + if (!type.getKind().isInterface()) { return; } - final TypeElement type = (TypeElement) element; - for (final TypeMirror implemented : type.getInterfaces()) { if (env.isSameType(implemented, allowed)) { continue; } errors.add(new ValidationError( - element, - "Interface %s annotated with @%s can only extend %s or nothing", - element.getSimpleName(), - annotation.getSimpleName(), + type, + "Interface %s can only extend %s or nothing", + type.getSimpleName(), allowed.getName())); } } protected void requireInterface() { - if (element.getKind().isInterface()) { + if (type.getKind().isInterface()) { return; } errors.add(new ValidationError( - element, - "Element %s annotated with @%s must be an interface but was a %s", - element.getSimpleName(), - annotation.getSimpleName(), - element.getKind())); + type, + "Element %s must be an interface but was a %s", + type.getSimpleName(), + type.getKind())); } protected void requireAnnotatedReturnType( @@ -147,14 +141,14 @@ protected void requireAnnotatedReturnType( final Predicate isNotResource = method -> env.type(method.getReturnType()).getAnnotation(required) == null; - env.methodsOf(element) + env.methodsOf(type) .filter(isAnnotated) .filter(isNotResource) .forEach(method -> errors.add(new ValidationError( method, "Method %s on interface %s annotated with @%s must return @%s interface", method.getSimpleName(), - element.getSimpleName(), + type.getSimpleName(), annotation.getSimpleName(), required.getSimpleName()))); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java new file mode 100644 index 000000000..5d6037a86 --- /dev/null +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java @@ -0,0 +1,69 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static javax.lang.model.type.TypeKind.VOID; +import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import javax.annotation.processing.Filer; +import javax.lang.model.element.Name; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.NoType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Elements; + +import org.junit.jupiter.api.Test; + +class ImplementorTest { + @Test + void x() throws IOException { + final TypeElement type = mock(TypeElement.class); + final TypeMirror mirror = mock(NoType.class); + final Environment env = mock(Environment.class); + final Elements elementUtils = mock(Elements.class); + final Name name = mock(Name.class); + final PackageElement packageElement = mock(PackageElement.class); + final Filer filer = mock(Filer.class); + when(mirror.getKind()).thenReturn(VOID); + when(type.asType()).thenReturn(mirror); + + when(elementUtils.getBinaryName(any())).thenReturn(name); + when(packageElement.getQualifiedName()).thenReturn(name); + when(elementUtils.getPackageOf(any())).thenReturn(packageElement); + when(filer.createSourceFile(any())).thenThrow(IOException.class); + when(env.getElementUtils()).thenReturn(elementUtils); + when(env.getFiler()).thenReturn(filer); + + final Implementor mock = new Implementor(type, null, null, env) { + @Override + protected void implementInternal() { + } + }; + + assertThrows(RuntimeException.class, mock::implement); + } +} From 276a111f9d81ded27203b7df37d9797bb370db3f Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 17 Feb 2024 13:34:40 +0000 Subject: [PATCH 071/141] Generic validators --- .../wrapping/processor/DatasetValidator.java | 4 +- .../wrapping/processor/GraphValidator.java | 4 +- .../rdf/wrapping/processor/Interface.java | 2 +- .../wrapping/processor/ResourceInterface.java | 12 +++++ .../wrapping/processor/ResourceValidator.java | 20 ++++----- .../rdf/wrapping/processor/Validator.java | 45 +++++++++---------- 6 files changed, 46 insertions(+), 41 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java index 63235836f..7c35d801d 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java @@ -28,9 +28,9 @@ import org.apache.jena.query.Dataset; -class DatasetValidator extends Validator { +class DatasetValidator extends Validator { DatasetValidator(final TypeElement type, final Environment env) { - super(type, env); + super(new DatasetInterface(type, env)); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java index bd6185cb6..f557ebf9b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java @@ -29,9 +29,9 @@ import org.apache.jena.rdf.model.Model; -class GraphValidator extends Validator { +class GraphValidator extends Validator { GraphValidator(final TypeElement type, final Environment env) { - super(type, env); + super(new GraphInterface(type, env)); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java index 602be2a86..3529abcc8 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -28,7 +28,7 @@ import javax.lang.model.element.TypeElement; class Interface { - private final TypeElement type; + protected final TypeElement type; protected final Environment env; Interface(final TypeElement type, final Environment env) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java index 2dcbcffb9..49f27e96f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java @@ -45,6 +45,14 @@ Stream resourcePropertyMethods() { return membersAnnotatedWith(Property.class).filter(returnTypeIsResource()); } + Stream complexMappingPropertyMethods() { + return membersAnnotatedWith(Property.class).filter(isComplexMapping()); + } + + Stream primitiveMappingPropertyMethods() { + return membersAnnotatedWith(Property.class).filter(isComplexMapping().negate()); + } + Stream transitiveResourceTypes() { final Stream children = resourcePropertyMethods().map(ExecutableElement::getReturnType); @@ -60,4 +68,8 @@ Stream transitiveResourceTypes() { private Predicate returnTypeIsResource() { return method -> env.type(method.getReturnType()).getAnnotation(Resource.class) != null; } + + private Predicate isComplexMapping() { + return method -> method.getAnnotation(Property.class).mapping() == Property.Mapping.AS; + } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 3f523f207..3e913d969 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -28,9 +28,9 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -class ResourceValidator extends Validator { +class ResourceValidator extends Validator { ResourceValidator(final TypeElement type, final Environment env) { - super(type, env); + super(new ResourceInterface(type, env)); } @Override @@ -48,14 +48,12 @@ protected void validateInternal() { } private void requireCompatiblePrimitiveReturnType() { - env.methodsOf(type) - .filter(method -> method.getAnnotation(Property.class) != null) - .filter(method -> method.getAnnotation(Property.class).mapping() != Property.Mapping.AS) + myInterface.primitiveMappingPropertyMethods() .forEach(method -> { final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); - if (!env.getTypeUtils().isAssignable(mappingMethodReturnType, method.getReturnType())) { + if (!myInterface.env.getTypeUtils().isAssignable(mappingMethodReturnType, method.getReturnType())) { errors.add(new ValidationError( method, "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", @@ -68,22 +66,20 @@ private void requireCompatiblePrimitiveReturnType() { } private void requireCompatibleComplexReturnType() { - env.methodsOf(type) - .filter(method -> method.getAnnotation(Property.class) != null) - .filter(method -> method.getAnnotation(Property.class).mapping() == Property.Mapping.AS) + myInterface.complexMappingPropertyMethods() .forEach(method -> { - if (env.type(method.getReturnType()).getAnnotation(Resource.class) == null) { + if (myInterface.env.type(method.getReturnType()).getAnnotation(Resource.class) == null) { errors.add(new ValidationError( method, "Method %s on interface %s must return @Resource interface", method.getSimpleName(), - type.getSimpleName())); + myInterface.type.getSimpleName())); } }); } private TypeMirror returnTypeOfMapper(final String mappingMethod) { - return env.methodsOf(ValueMappings.class) + return myInterface.env.methodsOf(ValueMappings.class) .filter(method -> method.getSimpleName().contentEquals(mappingMethod)) .map(ExecutableElement::getReturnType) .findFirst() diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 398dbfded..3710aca91 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -36,18 +36,15 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -// TODO: Use interfaces in validators -abstract class Validator { - protected final TypeElement type; - protected final Environment env; +abstract class Validator { + protected final T myInterface; protected final Collection errors = new ArrayList<>(); - protected Validator(final TypeElement type, final ProcessingEnvironment env) { - this.env = new Environment(env); - this.type = type; + protected Validator(final T myInterface) { + this.myInterface = myInterface; } - static Validator validator(final TypeElement type, final Environment env) { + static Validator validator(final TypeElement type, final Environment env) { if (type.getAnnotation(Dataset.class) != null) { return new DatasetValidator(type, env); @@ -74,14 +71,14 @@ protected void requireMemberMethods(final Class annotation final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; - env.methodsOf(type) + myInterface.env.methodsOf(myInterface.type) .filter(isNotMember) .filter(isAnnotated) .forEach(method -> errors.add(new ValidationError( method, "Method %s on interface %s annotated with @%s cannot be static or default", method.getSimpleName(), - type.getSimpleName(), + myInterface.type.getSimpleName(), annotation.getSimpleName()))); } @@ -93,44 +90,44 @@ protected final void requireNonMemberMethods(final Class.. final Predicate isUnannotated = method -> Arrays.stream(annotations).noneMatch(a -> method.getAnnotation(a) != null); - env.methodsOf(type) + myInterface.env.methodsOf(myInterface.type) .filter(isMember) .filter(isUnannotated) .forEach(method -> errors.add(new ValidationError( method, "Unannotated method %s on interface %s must be static or default", method.getSimpleName(), - type.getSimpleName()))); + myInterface.type.getSimpleName()))); } protected void limitBaseInterfaces(final Class allowed) { - if (!type.getKind().isInterface()) { + if (!myInterface.type.getKind().isInterface()) { return; } - for (final TypeMirror implemented : type.getInterfaces()) { - if (env.isSameType(implemented, allowed)) { + for (final TypeMirror implemented : myInterface.type.getInterfaces()) { + if (myInterface.env.isSameType(implemented, allowed)) { continue; } errors.add(new ValidationError( - type, + myInterface.type, "Interface %s can only extend %s or nothing", - type.getSimpleName(), + myInterface.type.getSimpleName(), allowed.getName())); } } protected void requireInterface() { - if (type.getKind().isInterface()) { + if (myInterface.type.getKind().isInterface()) { return; } errors.add(new ValidationError( - type, + myInterface.type, "Element %s must be an interface but was a %s", - type.getSimpleName(), - type.getKind())); + myInterface.type.getSimpleName(), + myInterface.type.getKind())); } protected void requireAnnotatedReturnType( @@ -139,16 +136,16 @@ protected void requireAnnotatedReturnType( final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; final Predicate isNotResource = method -> - env.type(method.getReturnType()).getAnnotation(required) == null; + myInterface.env.type(method.getReturnType()).getAnnotation(required) == null; - env.methodsOf(type) + myInterface.env.methodsOf(myInterface.type) .filter(isAnnotated) .filter(isNotResource) .forEach(method -> errors.add(new ValidationError( method, "Method %s on interface %s annotated with @%s must return @%s interface", method.getSimpleName(), - type.getSimpleName(), + myInterface.type.getSimpleName(), annotation.getSimpleName(), required.getSimpleName()))); } From 1927ae277700b7b1085bd0b1311cbfc4d2e0938e Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 17 Feb 2024 14:00:31 +0000 Subject: [PATCH 072/141] Simplify type & env in Implementer --- .../processor/DatasetImplementor.java | 2 +- .../wrapping/processor/GraphImplementor.java | 2 +- .../wrapping/processor/GraphInterface.java | 4 +-- .../rdf/wrapping/processor/Implementor.java | 5 ++- .../rdf/wrapping/processor/Interface.java | 16 ++++++--- .../processor/ResourceImplementor.java | 2 +- .../wrapping/processor/ResourceInterface.java | 6 ++-- .../wrapping/processor/ResourceValidator.java | 8 ++--- .../rdf/wrapping/processor/Validator.java | 33 +++++++++---------- .../wrapping/processor/ImplementorTest.java | 5 ++- 10 files changed, 48 insertions(+), 35 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 8fa9c9dd8..bbbfa2f2e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -24,7 +24,7 @@ class DatasetImplementor extends Implementor { DatasetImplementor(final TypeElement type, final Environment env) { - super(type, new DatasetInterface(type, env), new DatasetImplementation(env), env); + super(new DatasetInterface(type, env), new DatasetImplementation(env)); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index c42cddef6..a6622af34 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -28,7 +28,7 @@ class GraphImplementor extends Implementor { GraphImplementor(final TypeElement type, final Environment env) { - super(type, new GraphInterface(type, env), new GraphImplementation(env), env); + super(new GraphInterface(type, env), new GraphImplementation(env)); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java index c85b20d13..c263fbb94 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java @@ -40,8 +40,8 @@ class GraphInterface extends Interface { Stream transitiveResourceTypes() { final Stream children = resourceMethodTypes(); final Stream descendants = resourceMethodTypes() - .map(env::type) - .map(type -> new ResourceInterface(type, env)) + .map(getEnv()::type) + .map(type -> new ResourceInterface(type, getEnv())) .flatMap(ResourceInterface::transitiveResourceTypes); return concat(children, descendants) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index fcb8c7433..b1594541c 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -40,10 +40,13 @@ abstract class Implementor { protected final T myInterface; protected final U myClass; - protected Implementor(final TypeElement type, final T myInterface, final U myClass, final Environment env) { + protected Implementor(final T myInterface, final U myClass) { this.myInterface = myInterface; this.myClass = myClass; + final TypeElement type = myInterface.getType(); + final Environment env = myInterface.getEnv(); + originalInterface = typeOf(type.asType()); final String originalBinaryName = env.getElementUtils().getBinaryName(type).toString(); final String qualifiedName = asImplementation(originalBinaryName); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java index 3529abcc8..922aabaaa 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -28,19 +28,27 @@ import javax.lang.model.element.TypeElement; class Interface { - protected final TypeElement type; - protected final Environment env; + private final TypeElement type; + private final Environment env; Interface(final TypeElement type, final Environment env) { this.env = env; this.type = type; } + protected TypeElement getType() { + return type; + } + + protected Environment getEnv() { + return env; + } + protected final Stream membersAnnotatedWith(final Class annotation) { - return env.methodsOf(type) + return getEnv().methodsOf(getType()) .filter(method -> !method.isDefault()) .filter(method -> !method.getModifiers().contains(Modifier.STATIC)) - .filter(method -> !env.isVoid(method.getReturnType())) + .filter(method -> !getEnv().isVoid(method.getReturnType())) .filter(method -> method.getAnnotation(annotation) != null); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 68a8e53ea..81454f83c 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -24,7 +24,7 @@ class ResourceImplementor extends Implementor { ResourceImplementor(final TypeElement type, final Environment env) { - super(type, new ResourceInterface(type, env), new ResourceImplementation(env), env); + super(new ResourceInterface(type, env), new ResourceImplementation(env)); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java index 49f27e96f..7f8fd2285 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java @@ -58,15 +58,15 @@ Stream transitiveResourceTypes() { final Stream descendants = resourcePropertyMethods() .map(ExecutableElement::getReturnType) - .map(env::type) - .map(type -> new ResourceInterface(type, env)) + .map(getEnv()::type) + .map(type -> new ResourceInterface(type, getEnv())) .flatMap(ResourceInterface::transitiveResourceTypes); return concat(children, descendants).distinct(); } private Predicate returnTypeIsResource() { - return method -> env.type(method.getReturnType()).getAnnotation(Resource.class) != null; + return method -> getEnv().type(method.getReturnType()).getAnnotation(Resource.class) != null; } private Predicate isComplexMapping() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 3e913d969..d0225432e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -53,7 +53,7 @@ private void requireCompatiblePrimitiveReturnType() { final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); - if (!myInterface.env.getTypeUtils().isAssignable(mappingMethodReturnType, method.getReturnType())) { + if (!myInterface.getEnv().getTypeUtils().isAssignable(mappingMethodReturnType, method.getReturnType())) { errors.add(new ValidationError( method, "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", @@ -68,18 +68,18 @@ private void requireCompatiblePrimitiveReturnType() { private void requireCompatibleComplexReturnType() { myInterface.complexMappingPropertyMethods() .forEach(method -> { - if (myInterface.env.type(method.getReturnType()).getAnnotation(Resource.class) == null) { + if (myInterface.getEnv().type(method.getReturnType()).getAnnotation(Resource.class) == null) { errors.add(new ValidationError( method, "Method %s on interface %s must return @Resource interface", method.getSimpleName(), - myInterface.type.getSimpleName())); + myInterface.getType().getSimpleName())); } }); } private TypeMirror returnTypeOfMapper(final String mappingMethod) { - return myInterface.env.methodsOf(ValueMappings.class) + return myInterface.getEnv().methodsOf(ValueMappings.class) .filter(method -> method.getSimpleName().contentEquals(mappingMethod)) .map(ExecutableElement::getReturnType) .findFirst() diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 3710aca91..24f8bded7 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -31,7 +31,6 @@ import java.util.Collection; import java.util.function.Predicate; -import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; @@ -71,14 +70,14 @@ protected void requireMemberMethods(final Class annotation final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; - myInterface.env.methodsOf(myInterface.type) + myInterface.getEnv().methodsOf(myInterface.getType()) .filter(isNotMember) .filter(isAnnotated) .forEach(method -> errors.add(new ValidationError( method, "Method %s on interface %s annotated with @%s cannot be static or default", method.getSimpleName(), - myInterface.type.getSimpleName(), + myInterface.getType().getSimpleName(), annotation.getSimpleName()))); } @@ -90,44 +89,44 @@ protected final void requireNonMemberMethods(final Class.. final Predicate isUnannotated = method -> Arrays.stream(annotations).noneMatch(a -> method.getAnnotation(a) != null); - myInterface.env.methodsOf(myInterface.type) + myInterface.getEnv().methodsOf(myInterface.getType()) .filter(isMember) .filter(isUnannotated) .forEach(method -> errors.add(new ValidationError( method, "Unannotated method %s on interface %s must be static or default", method.getSimpleName(), - myInterface.type.getSimpleName()))); + myInterface.getType().getSimpleName()))); } protected void limitBaseInterfaces(final Class allowed) { - if (!myInterface.type.getKind().isInterface()) { + if (!myInterface.getType().getKind().isInterface()) { return; } - for (final TypeMirror implemented : myInterface.type.getInterfaces()) { - if (myInterface.env.isSameType(implemented, allowed)) { + for (final TypeMirror implemented : myInterface.getType().getInterfaces()) { + if (myInterface.getEnv().isSameType(implemented, allowed)) { continue; } errors.add(new ValidationError( - myInterface.type, + myInterface.getType(), "Interface %s can only extend %s or nothing", - myInterface.type.getSimpleName(), + myInterface.getType().getSimpleName(), allowed.getName())); } } protected void requireInterface() { - if (myInterface.type.getKind().isInterface()) { + if (myInterface.getType().getKind().isInterface()) { return; } errors.add(new ValidationError( - myInterface.type, + myInterface.getType(), "Element %s must be an interface but was a %s", - myInterface.type.getSimpleName(), - myInterface.type.getKind())); + myInterface.getType().getSimpleName(), + myInterface.getType().getKind())); } protected void requireAnnotatedReturnType( @@ -136,16 +135,16 @@ protected void requireAnnotatedReturnType( final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; final Predicate isNotResource = method -> - myInterface.env.type(method.getReturnType()).getAnnotation(required) == null; + myInterface.getEnv().type(method.getReturnType()).getAnnotation(required) == null; - myInterface.env.methodsOf(myInterface.type) + myInterface.getEnv().methodsOf(myInterface.getType()) .filter(isAnnotated) .filter(isNotResource) .forEach(method -> errors.add(new ValidationError( method, "Method %s on interface %s annotated with @%s must return @%s interface", method.getSimpleName(), - myInterface.type.getSimpleName(), + myInterface.getType().getSimpleName(), annotation.getSimpleName(), required.getSimpleName()))); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java index 5d6037a86..8c76af87f 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java @@ -42,6 +42,7 @@ class ImplementorTest { @Test void x() throws IOException { final TypeElement type = mock(TypeElement.class); + final Interface myInterface = mock(Interface.class); final TypeMirror mirror = mock(NoType.class); final Environment env = mock(Environment.class); final Elements elementUtils = mock(Elements.class); @@ -50,6 +51,8 @@ void x() throws IOException { final Filer filer = mock(Filer.class); when(mirror.getKind()).thenReturn(VOID); when(type.asType()).thenReturn(mirror); + when(myInterface.getType()).thenReturn(type); + when(myInterface.getEnv()).thenReturn(env); when(elementUtils.getBinaryName(any())).thenReturn(name); when(packageElement.getQualifiedName()).thenReturn(name); @@ -58,7 +61,7 @@ void x() throws IOException { when(env.getElementUtils()).thenReturn(elementUtils); when(env.getFiler()).thenReturn(filer); - final Implementor mock = new Implementor(type, null, null, env) { + final Implementor mock = new Implementor(myInterface, null) { @Override protected void implementInternal() { } From 3398a79326aafab321d7f8f0d3fcd9ecab972b1b Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 17 Feb 2024 14:01:04 +0000 Subject: [PATCH 073/141] Simplify --- .../com/inrupt/rdf/wrapping/processor/Implementation.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java index 898c4c8f0..34c33cbac 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java @@ -46,17 +46,13 @@ abstract class Implementation { this.env = env; } - protected void annotateAndDocument() { - target.docComment().text("Warning, this class consists of generated code."); - target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); - } - protected void addClass(final JSourceFile source, final String name, final JType original, final Class clazz) { target = source._class(PUBLIC, name); target._extends(clazz); target._implements(original); - annotateAndDocument(); + target.docComment().text("Warning, this class consists of generated code."); + target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); } protected JMethodDef addMethod(final ExecutableElement method) { From 938e4a815f1f97c99262d7693eb854b54c659eec Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 17 Feb 2024 14:37:39 +0000 Subject: [PATCH 074/141] Move from implementor to Interface --- .../processor/DatasetImplementation.java | 4 ++-- .../wrapping/processor/DatasetImplementor.java | 4 ++-- .../wrapping/processor/GraphImplementation.java | 4 ++-- .../rdf/wrapping/processor/GraphImplementor.java | 4 ++-- .../rdf/wrapping/processor/Implementation.java | 6 +++--- .../rdf/wrapping/processor/Implementor.java | 12 +----------- .../inrupt/rdf/wrapping/processor/Interface.java | 16 ++++++++++++++++ .../processor/ResourceImplementation.java | 4 ++-- .../wrapping/processor/ResourceImplementor.java | 2 +- 9 files changed, 31 insertions(+), 25 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java index 5b1d35eb4..8415b5fde 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java @@ -52,8 +52,8 @@ void addImports(final JSourceFile source) { ._import(DatasetImpl.class); } - void addClass(final JSourceFile source, final String name, final JType originalInterface) { - addClass(source, name, originalInterface, DatasetImpl.class); + void addClass(final JSourceFile source, final Interface myInterface) { + addClass(source, myInterface, DatasetImpl.class); } void addConstructor() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index bbbfa2f2e..daae7780c 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -30,9 +30,9 @@ class DatasetImplementor extends Implementor @Override protected void implementInternal() { myClass.addImports(sourceFile); - myClass.addClass(sourceFile, implementationClass, originalInterface); + myClass.addClass(sourceFile, myInterface); myClass.addConstructor(); - myClass.addWrap(originalInterface); + myClass.addWrap(myInterface.getOriginalInterface()); myInterface.transitiveResourceTypes().forEach(myClass::addToPersonality); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java index 34c33cbac..539003be8 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java @@ -46,10 +46,10 @@ abstract class Implementation { this.env = env; } - protected void addClass(final JSourceFile source, final String name, final JType original, final Class clazz) { - target = source._class(PUBLIC, name); + protected void addClass(final JSourceFile source, final Interface myInterface, final Class clazz) { + target = source._class(PUBLIC, myInterface.getImplementationClass()); target._extends(clazz); - target._implements(original); + target._implements(myInterface.getOriginalInterface()); target.docComment().text("Warning, this class consists of generated code."); target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index b1594541c..74fcc1f09 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -20,9 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.processor.Implementation.asImplementation; -import static org.jboss.jdeparser.JTypes.typeOf; - import com.inrupt.rdf.wrapping.annotation.Dataset; import com.inrupt.rdf.wrapping.annotation.Graph; @@ -34,9 +31,7 @@ abstract class Implementor { protected final JSources sources; - protected final JType originalInterface; protected final JSourceFile sourceFile; - protected final String implementationClass; protected final T myInterface; protected final U myClass; @@ -47,16 +42,11 @@ protected Implementor(final T myInterface, final U myClass) { final TypeElement type = myInterface.getType(); final Environment env = myInterface.getEnv(); - originalInterface = typeOf(type.asType()); - final String originalBinaryName = env.getElementUtils().getBinaryName(type).toString(); - final String qualifiedName = asImplementation(originalBinaryName); - final int lastDot = originalBinaryName.lastIndexOf('.'); - implementationClass = qualifiedName.substring(lastDot + 1); final String packageName = env.getElementUtils().getPackageOf(type).getQualifiedName().toString(); final JFiler filer = JFiler.newInstance(env.getFiler()); sources = JDeparser.createSources(filer, new FormatPreferences()); - sourceFile = sources.createSourceFile(packageName, implementationClass); + sourceFile = sources.createSourceFile(packageName, myInterface.getImplementationClass()); } void implement() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java index 922aabaaa..a48d6e462 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -20,6 +20,9 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.processor.Implementation.asImplementation; +import static org.jboss.jdeparser.JTypes.typeOf; + import java.lang.annotation.Annotation; import java.util.stream.Stream; @@ -27,6 +30,8 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; +import org.jboss.jdeparser.JType; + class Interface { private final TypeElement type; private final Environment env; @@ -44,6 +49,17 @@ protected Environment getEnv() { return env; } + protected JType getOriginalInterface() { + return typeOf(type.asType()); + } + + protected String getImplementationClass() { + final String originalBinaryName = env.getElementUtils().getBinaryName(type).toString(); + final String qualifiedName = asImplementation(originalBinaryName); + final int lastDot = originalBinaryName.lastIndexOf('.'); + return qualifiedName.substring(lastDot + 1); + } + protected final Stream membersAnnotatedWith(final Class annotation) { return getEnv().methodsOf(getType()) .filter(method -> !method.isDefault()) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java index 81dbb146e..1e82d81f3 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java @@ -55,8 +55,8 @@ void addImports(final JSourceFile source) { ._import(ValueMappings.class); } - void addClass(final JSourceFile source, final String name, final JType originalInterface) { - addClass(source, name, originalInterface, WrapperResource.class); + void addClass(final JSourceFile source, final Interface myInterface) { + addClass(source, myInterface, WrapperResource.class); } void addFactoryField() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 81454f83c..881a3f9c6 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -30,7 +30,7 @@ class ResourceImplementor extends Implementor Date: Sat, 17 Feb 2024 15:19:19 +0000 Subject: [PATCH 075/141] Implementations have interface --- .../processor/DatasetImplementation.java | 14 ++++++------ .../processor/DatasetImplementor.java | 12 +++++----- .../processor/GraphImplementation.java | 14 ++++++------ .../wrapping/processor/GraphImplementor.java | 16 +++++++------- .../wrapping/processor/Implementation.java | 22 +++++++++++-------- .../rdf/wrapping/processor/Implementor.java | 16 ++++++-------- .../rdf/wrapping/processor/Processor.java | 2 +- .../processor/ResourceImplementation.java | 15 ++++++------- .../processor/ResourceImplementor.java | 10 ++++----- .../wrapping/processor/ImplementorTest.java | 4 +++- 10 files changed, 64 insertions(+), 61 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java index 8415b5fde..96097f016 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java @@ -37,11 +37,11 @@ import org.jboss.jdeparser.JSourceFile; import org.jboss.jdeparser.JType; -class DatasetImplementation extends Implementation { +class DatasetImplementation extends Implementation { private static final String ORIGINAL = "original"; - DatasetImplementation(final Environment env) { - super(env); + DatasetImplementation(final DatasetInterface myInterface) { + super(myInterface); } void addImports(final JSourceFile source) { @@ -52,8 +52,8 @@ void addImports(final JSourceFile source) { ._import(DatasetImpl.class); } - void addClass(final JSourceFile source, final Interface myInterface) { - addClass(source, myInterface, DatasetImpl.class); + void addClass(final JSourceFile source) { + addClass(source, DatasetImpl.class); } void addConstructor() { @@ -62,8 +62,8 @@ void addConstructor() { myConstructor.body().callSuper().arg($v(ORIGINAL)); } - void addWrap(final JType originalInterface) { - final JMethodDef myWrap = target.method(PUBLIC | STATIC, originalInterface, WRAP); + void addWrap() { + final JMethodDef myWrap = target.method(PUBLIC | STATIC, getMyInterface().getOriginalInterface(), WRAP); myWrap.param(FINAL, Dataset.class, ORIGINAL); myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("asDatasetGraph"))); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index daae7780c..49b7bbd61 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -22,19 +22,19 @@ import javax.lang.model.element.TypeElement; -class DatasetImplementor extends Implementor { +class DatasetImplementor extends Implementor { DatasetImplementor(final TypeElement type, final Environment env) { - super(new DatasetInterface(type, env), new DatasetImplementation(env)); + super(new DatasetImplementation(new DatasetInterface(type, env))); } @Override protected void implementInternal() { myClass.addImports(sourceFile); - myClass.addClass(sourceFile, myInterface); + myClass.addClass(sourceFile); myClass.addConstructor(); - myClass.addWrap(myInterface.getOriginalInterface()); + myClass.addWrap(); - myInterface.defaultGraphMethods().forEach(myClass::addDefaultGraph); - myInterface.namedGraphMethods().forEach(myClass::addNamedGraph); + myClass.getMyInterface().defaultGraphMethods().forEach(myClass::addDefaultGraph); + myClass.getMyInterface().namedGraphMethods().forEach(myClass::addNamedGraph); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java index ec4b23ada..c2d86bd3b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java @@ -37,13 +37,13 @@ import org.apache.jena.rdf.model.impl.ModelCom; import org.jboss.jdeparser.*; -class GraphImplementation extends Implementation { +class GraphImplementation extends Implementation { private static final String ORIGINAL = "original"; private JMethodDef constructor; - GraphImplementation(final Environment env) { - super(env); + GraphImplementation(final GraphInterface myInterface) { + super(myInterface); } void addImports(final JSourceFile source) { @@ -55,8 +55,8 @@ void addImports(final JSourceFile source) { ._import(ModelCom.class); } - void addClass(final JSourceFile source, final Interface myInterface) { - addClass(source, myInterface, WrapperModel.class); + void addClass(final JSourceFile source) { + addClass(source, WrapperModel.class); } void addConstructor() { @@ -65,8 +65,8 @@ void addConstructor() { constructor.body().callSuper().arg($v(ORIGINAL)); } - void addWrap(final JType originalInterface) { - final JMethodDef myWrap = target.method(PUBLIC | STATIC, originalInterface, WRAP); + void addWrap() { + final JMethodDef myWrap = target.method(PUBLIC | STATIC, getMyInterface().getOriginalInterface(), WRAP); myWrap.param(FINAL, Model.class, ORIGINAL); myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("getGraph"))); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index feebd93f6..6a342c19b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -26,31 +26,31 @@ import javax.lang.model.element.TypeElement; -class GraphImplementor extends Implementor { +class GraphImplementor extends Implementor { GraphImplementor(final TypeElement type, final Environment env) { - super(new GraphInterface(type, env), new GraphImplementation(env)); + super(new GraphImplementation(new GraphInterface(type, env))); } @Override protected void implementInternal() { myClass.addImports(sourceFile); - myClass.addClass(sourceFile, myInterface); + myClass.addClass(sourceFile); myClass.addConstructor(); - myClass.addWrap(myInterface.getOriginalInterface()); + myClass.addWrap(); - myInterface.transitiveResourceTypes().forEach(myClass::addToPersonality); + myClass.getMyInterface().transitiveResourceTypes().forEach(myClass::addToPersonality); - myInterface.instanceMethods().forEach(method -> myClass.addResourceMethod( + myClass.getMyInterface().instanceMethods().forEach(method -> myClass.addResourceMethod( method, "optionalFirstInstanceOfEither", method.getAnnotation(OptionalFirstInstanceOfEither.class).value())); - myInterface.subjectMethods().forEach(method -> myClass.addResourceMethod( + myClass.getMyInterface().subjectMethods().forEach(method -> myClass.addResourceMethod( method, "optionalFirstSubjectOfEither", method.getAnnotation(OptionalFirstSubjectOfEither.class).value())); - myInterface.objectMethods().forEach(method -> myClass.addResourceMethod( + myClass.getMyInterface().objectMethods().forEach(method -> myClass.addResourceMethod( method, "optionalFirstObjectOfEither", method.getAnnotation(OptionalFirstObjectOfEither.class).value())); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java index 539003be8..53d90d146 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java @@ -36,20 +36,24 @@ import org.jboss.jdeparser.JSourceFile; import org.jboss.jdeparser.JType; -abstract class Implementation { +abstract class Implementation { static final String WRAP = "wrap"; - private final Environment env; + private final T myInterface; protected JClassDef target; - Implementation(final Environment env) { - this.env = env; + Implementation(final T myInterface) { + this.myInterface = myInterface; } - protected void addClass(final JSourceFile source, final Interface myInterface, final Class clazz) { - target = source._class(PUBLIC, myInterface.getImplementationClass()); + protected T getMyInterface() { + return myInterface; + } + + protected void addClass(final JSourceFile source, final Class clazz) { + target = source._class(PUBLIC, getMyInterface().getImplementationClass()); target._extends(clazz); - target._implements(myInterface.getOriginalInterface()); + target._implements(getMyInterface().getOriginalInterface()); target.docComment().text("Warning, this class consists of generated code."); target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); @@ -66,8 +70,8 @@ protected JMethodDef addMethod(final ExecutableElement method) { } protected JType asImplementation(final TypeMirror original) { - final TypeElement returnType = env.type(original); - final String originalBinaryName = env + final TypeElement returnType = getMyInterface().getEnv().type(original); + final String originalBinaryName = getMyInterface().getEnv() .getElementUtils() .getBinaryName(returnType) .toString(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 74fcc1f09..988dfe7de 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -29,24 +29,22 @@ import org.jboss.jdeparser.*; -abstract class Implementor { +abstract class Implementor> { protected final JSources sources; protected final JSourceFile sourceFile; - protected final T myInterface; - protected final U myClass; + protected final T myClass; - protected Implementor(final T myInterface, final U myClass) { - this.myInterface = myInterface; + protected Implementor(final T myClass) { this.myClass = myClass; - final TypeElement type = myInterface.getType(); - final Environment env = myInterface.getEnv(); + final TypeElement type = myClass.getMyInterface().getType(); + final Environment env = myClass.getMyInterface().getEnv(); final String packageName = env.getElementUtils().getPackageOf(type).getQualifiedName().toString(); final JFiler filer = JFiler.newInstance(env.getFiler()); sources = JDeparser.createSources(filer, new FormatPreferences()); - sourceFile = sources.createSourceFile(packageName, myInterface.getImplementationClass()); + sourceFile = sources.createSourceFile(packageName, myClass.getMyInterface().getImplementationClass()); } void implement() { @@ -61,7 +59,7 @@ void implement() { protected abstract void implementInternal(); - static Implementor implementor(final Environment env, final TypeElement e) { + static Implementor implementor(final Environment env, final TypeElement e) { if (e.getAnnotation(Dataset.class) != null) { return new DatasetImplementor(e, env); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java index 9e2614e13..46c145b30 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java @@ -55,7 +55,7 @@ public boolean process(final Set annotations, final Round return false; } - final Collection> implementors = new ArrayList<>(); + final Collection> implementors = new ArrayList<>(); final Collection validationErrors = new ArrayList<>(); final Environment env = new Environment(processingEnv); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java index 1e82d81f3..30d0a1c3a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java @@ -33,15 +33,14 @@ import javax.lang.model.element.ExecutableElement; import org.apache.jena.enhanced.EnhGraph; -import org.apache.jena.enhanced.Implementation; import org.apache.jena.graph.Node; import org.jboss.jdeparser.*; -class ResourceImplementation extends com.inrupt.rdf.wrapping.processor.Implementation { +class ResourceImplementation extends Implementation { static final String FACTORY = "factory"; - ResourceImplementation(final Environment env) { - super(env); + ResourceImplementation(final ResourceInterface myInterface) { + super(myInterface); } void addImports(final JSourceFile source) { @@ -50,19 +49,19 @@ void addImports(final JSourceFile source) { ._import(WrapperResource.class) ._import(Generated.class) ._import(EnhGraph.class) - ._import(Implementation.class) + ._import(org.apache.jena.enhanced.Implementation.class) ._import(Node.class) ._import(ValueMappings.class); } - void addClass(final JSourceFile source, final Interface myInterface) { - addClass(source, myInterface, WrapperResource.class); + void addClass(final JSourceFile source) { + addClass(source, WrapperResource.class); } void addFactoryField() { target.field( STATIC | FINAL, - Implementation.class, + org.apache.jena.enhanced.Implementation.class, FACTORY, $t(UriOrBlankFactory.class)._new().arg($t(target).methodRef("new"))); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 881a3f9c6..0f1872167 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -22,19 +22,19 @@ import javax.lang.model.element.TypeElement; -class ResourceImplementor extends Implementor { +class ResourceImplementor extends Implementor { ResourceImplementor(final TypeElement type, final Environment env) { - super(new ResourceInterface(type, env), new ResourceImplementation(env)); + super(new ResourceImplementation(new ResourceInterface(type, env))); } @Override protected void implementInternal() { myClass.addImports(sourceFile); - myClass.addClass(sourceFile, myInterface); + myClass.addClass(sourceFile); myClass.addFactoryField(); myClass.addConstructor(); - myInterface.primitivePropertyMethods().forEach(myClass::addPrimitivePropertyMethod); - myInterface.resourcePropertyMethods().forEach(myClass::addResourcePropertyMethod); + myClass.getMyInterface().primitivePropertyMethods().forEach(myClass::addPrimitivePropertyMethod); + myClass.getMyInterface().resourcePropertyMethods().forEach(myClass::addResourcePropertyMethod); } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java index 8c76af87f..1920cba2d 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java @@ -43,6 +43,7 @@ class ImplementorTest { void x() throws IOException { final TypeElement type = mock(TypeElement.class); final Interface myInterface = mock(Interface.class); + final Implementation myClass = mock(Implementation.class); final TypeMirror mirror = mock(NoType.class); final Environment env = mock(Environment.class); final Elements elementUtils = mock(Elements.class); @@ -53,6 +54,7 @@ void x() throws IOException { when(type.asType()).thenReturn(mirror); when(myInterface.getType()).thenReturn(type); when(myInterface.getEnv()).thenReturn(env); + when(myClass.getMyInterface()).thenReturn(myInterface); when(elementUtils.getBinaryName(any())).thenReturn(name); when(packageElement.getQualifiedName()).thenReturn(name); @@ -61,7 +63,7 @@ void x() throws IOException { when(env.getElementUtils()).thenReturn(elementUtils); when(env.getFiler()).thenReturn(filer); - final Implementor mock = new Implementor(myInterface, null) { + final Implementor mock = new Implementor(myClass) { @Override protected void implementInternal() { } From f1ec5d5fe91f83b53e00e95faa71cb93b8585f2b Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 17 Feb 2024 16:08:13 +0000 Subject: [PATCH 076/141] Eliminate implementation --- .../processor/DatasetImplementation.java | 86 --------------- .../processor/DatasetImplementor.java | 71 +++++++++++-- .../processor/GraphImplementation.java | 97 ----------------- .../wrapping/processor/GraphImplementor.java | 89 ++++++++++++++-- .../wrapping/processor/Implementation.java | 85 --------------- .../rdf/wrapping/processor/Implementor.java | 66 ++++++++++-- .../rdf/wrapping/processor/Interface.java | 10 +- .../rdf/wrapping/processor/Manager.java | 4 +- .../processor/ResourceImplementation.java | 100 ------------------ .../processor/ResourceImplementor.java | 91 ++++++++++++++-- .../rdf/wrapping/processor/Validator.java | 2 +- .../wrapping/processor/ImplementorTest.java | 4 +- 12 files changed, 289 insertions(+), 416 deletions(-) delete mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java delete mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java delete mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java delete mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java deleted file mode 100644 index 96097f016..000000000 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementation.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.processor; - -import static org.jboss.jdeparser.JExprs.*; -import static org.jboss.jdeparser.JMod.*; -import static org.jboss.jdeparser.JTypes.$t; - -import com.inrupt.rdf.wrapping.annotation.NamedGraph; - -import javax.annotation.Generated; -import javax.lang.model.element.ExecutableElement; - -import org.apache.jena.query.Dataset; -import org.apache.jena.sparql.core.DatasetGraph; -import org.apache.jena.sparql.core.DatasetImpl; -import org.jboss.jdeparser.JExpr; -import org.jboss.jdeparser.JMethodDef; -import org.jboss.jdeparser.JSourceFile; -import org.jboss.jdeparser.JType; - -class DatasetImplementation extends Implementation { - private static final String ORIGINAL = "original"; - - DatasetImplementation(final DatasetInterface myInterface) { - super(myInterface); - } - - void addImports(final JSourceFile source) { - source - ._import(Generated.class) - ._import(Dataset.class) - ._import(DatasetGraph.class) - ._import(DatasetImpl.class); - } - - void addClass(final JSourceFile source) { - addClass(source, DatasetImpl.class); - } - - void addConstructor() { - final JMethodDef myConstructor = target.constructor(PROTECTED); - myConstructor.param(FINAL, DatasetGraph.class, ORIGINAL); - myConstructor.body().callSuper().arg($v(ORIGINAL)); - } - - void addWrap() { - final JMethodDef myWrap = target.method(PUBLIC | STATIC, getMyInterface().getOriginalInterface(), WRAP); - myWrap.param(FINAL, Dataset.class, ORIGINAL); - myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("asDatasetGraph"))); - } - - void addDefaultGraph(final ExecutableElement method) { - addGraph(method, call("getDefaultModel")); - } - - void addNamedGraph(final ExecutableElement method) { - final String graph = method.getAnnotation(NamedGraph.class).value(); - - addGraph(method, call("getNamedModel").arg(str(graph))); - } - - private void addGraph(final ExecutableElement method, final JExpr expr) { - final JType implementation = asImplementation(method.getReturnType()); - - addMethod(method).body()._return(implementation.call(WRAP).arg(expr)); - } -} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 49b7bbd61..17639b2a6 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -20,21 +20,76 @@ */ package com.inrupt.rdf.wrapping.processor; +import static org.jboss.jdeparser.JExprs.*; +import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JTypes.$t; + +import com.inrupt.rdf.wrapping.annotation.NamedGraph; + +import javax.annotation.Generated; +import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; -class DatasetImplementor extends Implementor { +import org.apache.jena.query.Dataset; +import org.apache.jena.sparql.core.DatasetGraph; +import org.apache.jena.sparql.core.DatasetImpl; +import org.jboss.jdeparser.JExpr; +import org.jboss.jdeparser.JMethodDef; +import org.jboss.jdeparser.JType; + +class DatasetImplementor extends Implementor { DatasetImplementor(final TypeElement type, final Environment env) { - super(new DatasetImplementation(new DatasetInterface(type, env))); + super(new DatasetInterface(type, env)); } @Override protected void implementInternal() { - myClass.addImports(sourceFile); - myClass.addClass(sourceFile); - myClass.addConstructor(); - myClass.addWrap(); + addImports(); + addClass(); + addConstructor(); + addWrap(); + + myInterface.defaultGraphMethods().forEach(this::addDefaultGraph); // TODO: fold + myInterface.namedGraphMethods().forEach(this::addNamedGraph); // TODO: fold + } + + private void addImports() { + sourceFile + ._import(Generated.class) + ._import(Dataset.class) + ._import(DatasetGraph.class) + ._import(DatasetImpl.class); + } + + private void addClass() { + addClass(DatasetImpl.class); + } + + private void addConstructor() { + final JMethodDef myConstructor = target.constructor(PROTECTED); + myConstructor.param(FINAL, DatasetGraph.class, ORIGINAL); + myConstructor.body().callSuper().arg($v(ORIGINAL)); + } + + private void addWrap() { + final JMethodDef myWrap = target.method(PUBLIC | STATIC, myInterface.getOriginalInterface(), WRAP); + myWrap.param(FINAL, Dataset.class, ORIGINAL); + myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("asDatasetGraph"))); + } + + private void addDefaultGraph(final ExecutableElement method) { + addGraph(method, call("getDefaultModel")); + } + + private void addNamedGraph(final ExecutableElement method) { + final String graph = method.getAnnotation(NamedGraph.class).value(); + + addGraph(method, call("getNamedModel").arg(str(graph))); + } + + private void addGraph(final ExecutableElement method, final JExpr expr) { + final JType implementation = asImplementation(method.getReturnType()); - myClass.getMyInterface().defaultGraphMethods().forEach(myClass::addDefaultGraph); - myClass.getMyInterface().namedGraphMethods().forEach(myClass::addNamedGraph); + addMethod(method).body()._return(implementation.call(WRAP).arg(expr)); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java deleted file mode 100644 index c2d86bd3b..000000000 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementation.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.processor; - -import static com.inrupt.rdf.wrapping.processor.ResourceImplementation.FACTORY; -import static org.jboss.jdeparser.JExprs.$v; -import static org.jboss.jdeparser.JExprs.call; -import static org.jboss.jdeparser.JMod.*; -import static org.jboss.jdeparser.JTypes.$t; - -import com.inrupt.rdf.wrapping.jena.WrapperModel; - -import javax.annotation.Generated; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.type.TypeMirror; - -import org.apache.jena.graph.Graph; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.impl.ModelCom; -import org.jboss.jdeparser.*; - -class GraphImplementation extends Implementation { - private static final String ORIGINAL = "original"; - - private JMethodDef constructor; - - GraphImplementation(final GraphInterface myInterface) { - super(myInterface); - } - - void addImports(final JSourceFile source) { - source - ._import(WrapperModel.class) - ._import(Generated.class) - ._import(Graph.class) - ._import(Model.class) - ._import(ModelCom.class); - } - - void addClass(final JSourceFile source) { - addClass(source, WrapperModel.class); - } - - void addConstructor() { - constructor = target.constructor(PROTECTED); - constructor.param(FINAL, Graph.class, ORIGINAL); - constructor.body().callSuper().arg($v(ORIGINAL)); - } - - void addWrap() { - final JMethodDef myWrap = target.method(PUBLIC | STATIC, getMyInterface().getOriginalInterface(), WRAP); - myWrap.param(FINAL, Model.class, ORIGINAL); - myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("getGraph"))); - } - - void addToPersonality(final TypeMirror type) { - final JType implementation = asImplementation(type); - - constructor - .body() - .call(call("getPersonality"), "add") - .arg(implementation._class()) - .arg(implementation.field(FACTORY)); - } - - void addResourceMethod(final ExecutableElement method, final String convenience, final String[] values) { - final JType implementation = asImplementation(method.getReturnType()); - - // Call model wrapper convenience method passing projection class argument - final JCall convenienceCall = call(convenience).arg(implementation._class()); - - // Pass each filter value from the annotation as additional argument - for (final String value : values) { - convenienceCall.arg(JExprs.str(value)); - } - - addMethod(method).body()._return(convenienceCall); - } -} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 6a342c19b..877abaa80 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -20,39 +20,108 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.processor.ResourceImplementor.FACTORY; +import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JExprs.call; +import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JTypes.$t; + import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; +import com.inrupt.rdf.wrapping.jena.WrapperModel; +import javax.annotation.Generated; +import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; + +import org.apache.jena.graph.Graph; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.impl.ModelCom; +import org.jboss.jdeparser.JCall; +import org.jboss.jdeparser.JExprs; +import org.jboss.jdeparser.JMethodDef; +import org.jboss.jdeparser.JType; -class GraphImplementor extends Implementor { +class GraphImplementor extends Implementor { GraphImplementor(final TypeElement type, final Environment env) { - super(new GraphImplementation(new GraphInterface(type, env))); + super(new GraphInterface(type, env)); } @Override protected void implementInternal() { - myClass.addImports(sourceFile); - myClass.addClass(sourceFile); - myClass.addConstructor(); - myClass.addWrap(); + addImports(); + addClass(); + final JMethodDef constructor = addConstructor(); + addWrap(); - myClass.getMyInterface().transitiveResourceTypes().forEach(myClass::addToPersonality); + myInterface.transitiveResourceTypes().forEach(type -> addToPersonality(type, constructor)); - myClass.getMyInterface().instanceMethods().forEach(method -> myClass.addResourceMethod( + myInterface.instanceMethods().forEach(method -> addResourceMethod( method, "optionalFirstInstanceOfEither", method.getAnnotation(OptionalFirstInstanceOfEither.class).value())); - myClass.getMyInterface().subjectMethods().forEach(method -> myClass.addResourceMethod( + myInterface.subjectMethods().forEach(method -> addResourceMethod( method, "optionalFirstSubjectOfEither", method.getAnnotation(OptionalFirstSubjectOfEither.class).value())); - myClass.getMyInterface().objectMethods().forEach(method -> myClass.addResourceMethod( + myInterface.objectMethods().forEach(method -> addResourceMethod( method, "optionalFirstObjectOfEither", method.getAnnotation(OptionalFirstObjectOfEither.class).value())); } + + private void addImports() { + sourceFile + ._import(WrapperModel.class) + ._import(Generated.class) + ._import(Graph.class) + ._import(Model.class) + ._import(ModelCom.class); + } + + private void addClass() { + addClass(WrapperModel.class); + } + + private JMethodDef addConstructor() { + final JMethodDef constructor = target.constructor(PROTECTED); + constructor.param(FINAL, Graph.class, ORIGINAL); + constructor.body().callSuper().arg($v(ORIGINAL)); + + return constructor; + } + + private void addWrap() { + final JMethodDef myWrap = target.method(PUBLIC | STATIC, myInterface.getOriginalInterface(), WRAP); + myWrap.param(FINAL, Model.class, ORIGINAL); + myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("getGraph"))); + } + + private void addToPersonality(final TypeMirror type, final JMethodDef constructor) { + final JType implementation = asImplementation(type); + + constructor + .body() + .call(call("getPersonality"), "add") + .arg(implementation._class()) + .arg(implementation.field(FACTORY)); + } + + private void addResourceMethod(final ExecutableElement method, final String convenience, final String[] values) { + final JType implementation = asImplementation(method.getReturnType()); + + // Call model wrapper convenience method passing projection class argument + final JCall convenienceCall = call(convenience).arg(implementation._class()); + + // Pass each filter value from the annotation as additional argument + for (final String value : values) { + convenienceCall.arg(JExprs.str(value)); + } + + addMethod(method).body()._return(convenienceCall); + } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java deleted file mode 100644 index 53d90d146..000000000 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementation.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.processor; - -import static org.jboss.jdeparser.JMod.PUBLIC; -import static org.jboss.jdeparser.JTypes.$t; -import static org.jboss.jdeparser.JTypes.typeOf; - -import java.time.Instant; - -import javax.annotation.Generated; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; - -import org.jboss.jdeparser.JClassDef; -import org.jboss.jdeparser.JMethodDef; -import org.jboss.jdeparser.JSourceFile; -import org.jboss.jdeparser.JType; - -abstract class Implementation { - static final String WRAP = "wrap"; - - private final T myInterface; - protected JClassDef target; - - Implementation(final T myInterface) { - this.myInterface = myInterface; - } - - protected T getMyInterface() { - return myInterface; - } - - protected void addClass(final JSourceFile source, final Class clazz) { - target = source._class(PUBLIC, getMyInterface().getImplementationClass()); - target._extends(clazz); - target._implements(getMyInterface().getOriginalInterface()); - - target.docComment().text("Warning, this class consists of generated code."); - target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); - } - - protected JMethodDef addMethod(final ExecutableElement method) { - final String myName = method.getSimpleName().toString(); - final JType myType = typeOf(method.getReturnType()); - - final JMethodDef myMethod = target.method(PUBLIC, myType, myName); - myMethod.annotate(Override.class); - - return myMethod; - } - - protected JType asImplementation(final TypeMirror original) { - final TypeElement returnType = getMyInterface().getEnv().type(original); - final String originalBinaryName = getMyInterface().getEnv() - .getElementUtils() - .getBinaryName(returnType) - .toString(); - - return $t(asImplementation(originalBinaryName)); - } - - static String asImplementation(final String original) { - return original + "_$impl"; - } -} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 988dfe7de..fece2304f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -20,31 +20,50 @@ */ package com.inrupt.rdf.wrapping.processor; +import static org.jboss.jdeparser.JMod.PUBLIC; +import static org.jboss.jdeparser.JTypes.$t; +import static org.jboss.jdeparser.JTypes.typeOf; + import com.inrupt.rdf.wrapping.annotation.Dataset; import com.inrupt.rdf.wrapping.annotation.Graph; import java.io.IOException; +import java.time.Instant; +import javax.annotation.Generated; +import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; import org.jboss.jdeparser.*; -abstract class Implementor> { +abstract class Implementor { + protected static final String ORIGINAL = "original"; + static final String WRAP = "wrap"; + protected final JSources sources; protected final JSourceFile sourceFile; - protected final T myClass; + protected final T myInterface; + protected JClassDef target; - protected Implementor(final T myClass) { - this.myClass = myClass; + protected Implementor(final T myInterface) { + this.myInterface = myInterface; - final TypeElement type = myClass.getMyInterface().getType(); - final Environment env = myClass.getMyInterface().getEnv(); + final TypeElement type = myInterface.getType(); + final Environment env = myInterface.getEnv(); final String packageName = env.getElementUtils().getPackageOf(type).getQualifiedName().toString(); final JFiler filer = JFiler.newInstance(env.getFiler()); sources = JDeparser.createSources(filer, new FormatPreferences()); - sourceFile = sources.createSourceFile(packageName, myClass.getMyInterface().getImplementationClass()); + sourceFile = sources.createSourceFile(packageName, getImplementationClass()); + } + + private String getImplementationClass() { + final String originalBinaryName = myInterface.getEnv().getElementUtils().getBinaryName(myInterface.getType()).toString(); + final String qualifiedName = asImplementation(originalBinaryName); + final int lastDot = originalBinaryName.lastIndexOf('.'); + return qualifiedName.substring(lastDot + 1); } void implement() { @@ -71,4 +90,37 @@ static Implementor implementor(final Environment env, final TypeElement e) { return new ResourceImplementor(e, env); } } + + protected void addClass(final Class clazz) { + target = sourceFile._class(PUBLIC, getImplementationClass()); + target._extends(clazz); + target._implements(myInterface.getOriginalInterface()); + + target.docComment().text("Warning, this class consists of generated code."); + target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); + } + + protected JMethodDef addMethod(final ExecutableElement method) { + final String myName = method.getSimpleName().toString(); + final JType myType = typeOf(method.getReturnType()); + + final JMethodDef myMethod = target.method(PUBLIC, myType, myName); + myMethod.annotate(Override.class); + + return myMethod; + } + + protected JType asImplementation(final TypeMirror original) { + final TypeElement returnType = myInterface.getEnv().type(original); + final String originalBinaryName = myInterface.getEnv() + .getElementUtils() + .getBinaryName(returnType) + .toString(); + + return $t(asImplementation(originalBinaryName)); + } + + static String asImplementation(final String original) { + return original + "_$impl"; + } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java index a48d6e462..65f1bf38a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -20,7 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.processor.Implementation.asImplementation; import static org.jboss.jdeparser.JTypes.typeOf; import java.lang.annotation.Annotation; @@ -50,14 +49,7 @@ protected Environment getEnv() { } protected JType getOriginalInterface() { - return typeOf(type.asType()); - } - - protected String getImplementationClass() { - final String originalBinaryName = env.getElementUtils().getBinaryName(type).toString(); - final String qualifiedName = asImplementation(originalBinaryName); - final int lastDot = originalBinaryName.lastIndexOf('.'); - return qualifiedName.substring(lastDot + 1); + return typeOf(getType().asType()); } protected final Stream membersAnnotatedWith(final Class annotation) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java index 41572485f..67c917016 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java @@ -20,8 +20,8 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.processor.Implementation.WRAP; -import static com.inrupt.rdf.wrapping.processor.Implementation.asImplementation; +import static com.inrupt.rdf.wrapping.processor.Implementor.WRAP; +import static com.inrupt.rdf.wrapping.processor.Implementor.asImplementation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java deleted file mode 100644 index 30d0a1c3a..000000000 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementation.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.processor; - -import static org.jboss.jdeparser.JExprs.*; -import static org.jboss.jdeparser.JMod.*; -import static org.jboss.jdeparser.JTypes.$t; - -import com.inrupt.rdf.wrapping.annotation.Property; -import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; -import com.inrupt.rdf.wrapping.jena.ValueMappings; -import com.inrupt.rdf.wrapping.jena.WrapperResource; - -import javax.annotation.Generated; -import javax.lang.model.element.ExecutableElement; - -import org.apache.jena.enhanced.EnhGraph; -import org.apache.jena.graph.Node; -import org.jboss.jdeparser.*; - -class ResourceImplementation extends Implementation { - static final String FACTORY = "factory"; - - ResourceImplementation(final ResourceInterface myInterface) { - super(myInterface); - } - - void addImports(final JSourceFile source) { - source - ._import(UriOrBlankFactory.class) - ._import(WrapperResource.class) - ._import(Generated.class) - ._import(EnhGraph.class) - ._import(org.apache.jena.enhanced.Implementation.class) - ._import(Node.class) - ._import(ValueMappings.class); - } - - void addClass(final JSourceFile source) { - addClass(source, WrapperResource.class); - } - - void addFactoryField() { - target.field( - STATIC | FINAL, - org.apache.jena.enhanced.Implementation.class, - FACTORY, - $t(UriOrBlankFactory.class)._new().arg($t(target).methodRef("new"))); - } - - void addConstructor() { - final String node = "node"; - final String graph = "graph"; - - final JMethodDef myConstructor = target.constructor(PROTECTED); - myConstructor.param(FINAL, Node.class, node); - myConstructor.param(FINAL, EnhGraph.class, graph); - myConstructor.body().callSuper().arg($v(node)).arg($v(graph)); - } - - void addPrimitivePropertyMethod(final ExecutableElement method) { - final String mappingMethodName = method.getAnnotation(Property.class).mapping().getMethodName(); - final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); - - addPropertyMethod(method, mapping); - } - - void addResourcePropertyMethod(final ExecutableElement method) { - final JType implementation = asImplementation(method.getReturnType()); - final JCall mapping = $t(ValueMappings.class).call("as").arg(implementation._class()); - - addPropertyMethod(method, mapping); - } - - private void addPropertyMethod(final ExecutableElement method, final JExpr mapping) { - final String predicateFromAnnotation = method.getAnnotation(Property.class).predicate(); - final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); - - // TODO: Dynamic cardniality - addMethod(method).body()._return(call("anyOrNull").arg(predicate).arg(mapping)); - } -} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 0f1872167..cf2d4e995 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -20,21 +20,96 @@ */ package com.inrupt.rdf.wrapping.processor; +import static org.jboss.jdeparser.JExprs.*; +import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JTypes.$t; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; +import com.inrupt.rdf.wrapping.jena.ValueMappings; +import com.inrupt.rdf.wrapping.jena.WrapperResource; + +import javax.annotation.Generated; +import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; -class ResourceImplementor extends Implementor { +import org.apache.jena.enhanced.EnhGraph; +import org.apache.jena.graph.Node; +import org.jboss.jdeparser.JCall; +import org.jboss.jdeparser.JExpr; +import org.jboss.jdeparser.JMethodDef; +import org.jboss.jdeparser.JType; + +class ResourceImplementor extends Implementor { + static final String FACTORY = "factory"; + ResourceImplementor(final TypeElement type, final Environment env) { - super(new ResourceImplementation(new ResourceInterface(type, env))); + super(new ResourceInterface(type, env)); } @Override protected void implementInternal() { - myClass.addImports(sourceFile); - myClass.addClass(sourceFile); - myClass.addFactoryField(); - myClass.addConstructor(); + addImports(); + addClass(); + addFactoryField(); + addConstructor(); + + myInterface.primitivePropertyMethods().forEach(this::addPrimitivePropertyMethod); // TODO: fold + myInterface.resourcePropertyMethods().forEach(this::addResourcePropertyMethod); // TODO: fold + } + + private void addImports() { + sourceFile + ._import(UriOrBlankFactory.class) + ._import(WrapperResource.class) + ._import(Generated.class) + ._import(EnhGraph.class) + ._import(org.apache.jena.enhanced.Implementation.class) + ._import(Node.class) + ._import(ValueMappings.class); + } + + private void addClass() { + addClass(WrapperResource.class); + } + + private void addFactoryField() { + target.field( + STATIC | FINAL, + org.apache.jena.enhanced.Implementation.class, + FACTORY, + $t(UriOrBlankFactory.class)._new().arg($t(target).methodRef("new"))); + } + + private void addConstructor() { + final String node = "node"; + final String graph = "graph"; + + final JMethodDef myConstructor = target.constructor(PROTECTED); + myConstructor.param(FINAL, Node.class, node); + myConstructor.param(FINAL, EnhGraph.class, graph); + myConstructor.body().callSuper().arg($v(node)).arg($v(graph)); + } + + private void addPrimitivePropertyMethod(final ExecutableElement method) { + final String mappingMethodName = method.getAnnotation(Property.class).mapping().getMethodName(); + final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); + + addPropertyMethod(method, mapping); + } + + private void addResourcePropertyMethod(final ExecutableElement method) { + final JType implementation = asImplementation(method.getReturnType()); + final JCall mapping = $t(ValueMappings.class).call("as").arg(implementation._class()); + + addPropertyMethod(method, mapping); + } + + private void addPropertyMethod(final ExecutableElement method, final JExpr mapping) { + final String predicateFromAnnotation = method.getAnnotation(Property.class).predicate(); + final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); - myClass.getMyInterface().primitivePropertyMethods().forEach(myClass::addPrimitivePropertyMethod); - myClass.getMyInterface().resourcePropertyMethods().forEach(myClass::addResourcePropertyMethod); + // TODO: Dynamic cardniality + addMethod(method).body()._return(call("anyOrNull").arg(predicate).arg(mapping)); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 24f8bded7..3e4f51d59 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -43,7 +43,7 @@ protected Validator(final T myInterface) { this.myInterface = myInterface; } - static Validator validator(final TypeElement type, final Environment env) { + static Validator validator(final TypeElement type, final Environment env) { if (type.getAnnotation(Dataset.class) != null) { return new DatasetValidator(type, env); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java index 1920cba2d..d6b7533fd 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java @@ -43,7 +43,6 @@ class ImplementorTest { void x() throws IOException { final TypeElement type = mock(TypeElement.class); final Interface myInterface = mock(Interface.class); - final Implementation myClass = mock(Implementation.class); final TypeMirror mirror = mock(NoType.class); final Environment env = mock(Environment.class); final Elements elementUtils = mock(Elements.class); @@ -54,7 +53,6 @@ void x() throws IOException { when(type.asType()).thenReturn(mirror); when(myInterface.getType()).thenReturn(type); when(myInterface.getEnv()).thenReturn(env); - when(myClass.getMyInterface()).thenReturn(myInterface); when(elementUtils.getBinaryName(any())).thenReturn(name); when(packageElement.getQualifiedName()).thenReturn(name); @@ -63,7 +61,7 @@ void x() throws IOException { when(env.getElementUtils()).thenReturn(elementUtils); when(env.getFiler()).thenReturn(filer); - final Implementor mock = new Implementor(myClass) { + final Implementor mock = new Implementor(myInterface) { @Override protected void implementInternal() { } From 4b03d88d410aedf1310f3af8242a9b1e96a5b964 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 17 Feb 2024 16:31:29 +0000 Subject: [PATCH 077/141] Style --- .../processor/DatasetImplementor.java | 17 +++++++------ .../wrapping/processor/GraphImplementor.java | 20 +++++++-------- .../rdf/wrapping/processor/Implementor.java | 3 ++- .../processor/ResourceImplementor.java | 25 +++++++++++-------- .../wrapping/processor/ResourceValidator.java | 4 ++- 5 files changed, 38 insertions(+), 31 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 17639b2a6..7c0a0c6de 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -48,9 +48,8 @@ protected void implementInternal() { addClass(); addConstructor(); addWrap(); - - myInterface.defaultGraphMethods().forEach(this::addDefaultGraph); // TODO: fold - myInterface.namedGraphMethods().forEach(this::addNamedGraph); // TODO: fold + addDefaultGraphs(); + addNamedGraphs(); } private void addImports() { @@ -77,14 +76,16 @@ private void addWrap() { myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("asDatasetGraph"))); } - private void addDefaultGraph(final ExecutableElement method) { - addGraph(method, call("getDefaultModel")); + private void addDefaultGraphs() { + myInterface.defaultGraphMethods().forEach(method -> addGraph(method, call("getDefaultModel"))); } - private void addNamedGraph(final ExecutableElement method) { - final String graph = method.getAnnotation(NamedGraph.class).value(); + private void addNamedGraphs() { + myInterface.namedGraphMethods().forEach(method -> { + final String graph = method.getAnnotation(NamedGraph.class).value(); - addGraph(method, call("getNamedModel").arg(str(graph))); + addGraph(method, call("getNamedModel").arg(str(graph))); + }); } private void addGraph(final ExecutableElement method, final JExpr expr) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 877abaa80..26489f94e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -34,7 +34,6 @@ import javax.annotation.Generated; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; @@ -54,10 +53,9 @@ protected void implementInternal() { addImports(); addClass(); final JMethodDef constructor = addConstructor(); + addToPersonality(constructor); addWrap(); - myInterface.transitiveResourceTypes().forEach(type -> addToPersonality(type, constructor)); - myInterface.instanceMethods().forEach(method -> addResourceMethod( method, "optionalFirstInstanceOfEither", @@ -101,14 +99,16 @@ private void addWrap() { myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("getGraph"))); } - private void addToPersonality(final TypeMirror type, final JMethodDef constructor) { - final JType implementation = asImplementation(type); + private void addToPersonality(final JMethodDef constructor) { + myInterface.transitiveResourceTypes().forEach(type -> { + final JType implementation = asImplementation(type); - constructor - .body() - .call(call("getPersonality"), "add") - .arg(implementation._class()) - .arg(implementation.field(FACTORY)); + constructor + .body() + .call(call("getPersonality"), "add") + .arg(implementation._class()) + .arg(implementation.field(FACTORY)); + }); } private void addResourceMethod(final ExecutableElement method, final String convenience, final String[] values) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index fece2304f..0d00f7227 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -60,7 +60,8 @@ protected Implementor(final T myInterface) { } private String getImplementationClass() { - final String originalBinaryName = myInterface.getEnv().getElementUtils().getBinaryName(myInterface.getType()).toString(); + final String originalBinaryName = + myInterface.getEnv().getElementUtils().getBinaryName(myInterface.getType()).toString(); final String qualifiedName = asImplementation(originalBinaryName); final int lastDot = originalBinaryName.lastIndexOf('.'); return qualifiedName.substring(lastDot + 1); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index cf2d4e995..db3400d28 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -53,9 +53,8 @@ protected void implementInternal() { addClass(); addFactoryField(); addConstructor(); - - myInterface.primitivePropertyMethods().forEach(this::addPrimitivePropertyMethod); // TODO: fold - myInterface.resourcePropertyMethods().forEach(this::addResourcePropertyMethod); // TODO: fold + addPrimitivePropertyMethods(); + addResourcePropertyMethods(); } private void addImports() { @@ -91,18 +90,22 @@ private void addConstructor() { myConstructor.body().callSuper().arg($v(node)).arg($v(graph)); } - private void addPrimitivePropertyMethod(final ExecutableElement method) { - final String mappingMethodName = method.getAnnotation(Property.class).mapping().getMethodName(); - final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); + private void addPrimitivePropertyMethods() { + myInterface.primitivePropertyMethods().forEach(method -> { + final String mappingMethodName = method.getAnnotation(Property.class).mapping().getMethodName(); + final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); - addPropertyMethod(method, mapping); + addPropertyMethod(method, mapping); + }); } - private void addResourcePropertyMethod(final ExecutableElement method) { - final JType implementation = asImplementation(method.getReturnType()); - final JCall mapping = $t(ValueMappings.class).call("as").arg(implementation._class()); + private void addResourcePropertyMethods() { + myInterface.resourcePropertyMethods().forEach(method -> { + final JType implementation = asImplementation(method.getReturnType()); + final JCall mapping = $t(ValueMappings.class).call("as").arg(implementation._class()); - addPropertyMethod(method, mapping); + addPropertyMethod(method, mapping); + }); } private void addPropertyMethod(final ExecutableElement method, final JExpr mapping) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index d0225432e..1b531c72f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -53,7 +53,9 @@ private void requireCompatiblePrimitiveReturnType() { final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); - if (!myInterface.getEnv().getTypeUtils().isAssignable(mappingMethodReturnType, method.getReturnType())) { + if (!myInterface.getEnv().getTypeUtils().isAssignable( + mappingMethodReturnType, + method.getReturnType())) { errors.add(new ValidationError( method, "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", From d578953c076708b8cb64a80b0138c693463fd48f Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 17 Feb 2024 19:29:46 +0000 Subject: [PATCH 078/141] Manager readability and coverage --- processor/pom.xml | 5 + .../rdf/wrapping/processor/Manager.java | 62 +++++-- .../rdf/wrapping/processor/ManagerTest.java | 157 ++++++++++++++++++ 3 files changed, 209 insertions(+), 15 deletions(-) create mode 100644 processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java diff --git a/processor/pom.xml b/processor/pom.xml index bcfd6a8d6..289a0d2af 100644 --- a/processor/pom.xml +++ b/processor/pom.xml @@ -58,6 +58,11 @@ mockito-core test + + org.hamcrest + hamcrest + test + diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java index 67c917016..0c59c7fc9 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java @@ -37,44 +37,76 @@ public final class Manager { private Manager() { } - public static T wrap(final Model original, final Class interfaceType) { - return wrap(original, interfaceType, Model.class); + public static T wrap(final Model original, final Class definition) { + return wrap(original, definition, Model.class); } - public static T wrap(final Dataset original, final Class interfaceType) { - return wrap(original, interfaceType, Dataset.class); + public static T wrap(final Dataset original, final Class definition) { + return wrap(original, definition, Dataset.class); } - private static T wrap(final Object original, final Class interfaceType, final Class parameterType) { - final ClassLoader classLoader = interfaceType.getClassLoader(); - final String implTypeName = asImplementation(interfaceType.getName()); + private static T wrap(final Object original, final Class definition, final Class parameterType) { + final Class rawImplementation = findImplementation(definition); + final Class implementation = subclass(rawImplementation, definition); + final Method wrap = findWrapMethod(implementation, parameterType); + ensureNotVoid(wrap); + final Object result = invoke(wrap, original); + return cast(result, definition); + } + + private static Class findImplementation(final Class definition) { + final String implementation = asImplementation(definition.getName()); + final ClassLoader loader = definition.getClassLoader(); - final Class implClass; try { - implClass = Class.forName(implTypeName, true, classLoader).asSubclass(interfaceType); + return Class.forName(implementation, true, loader); + } catch (ClassNotFoundException e) { throw new RuntimeException("implementation not found", e); + } + } + + private static Class subclass(final Class implementation, final Class definition) { + try { + return implementation.asSubclass(definition); + } catch (ClassCastException e) { - // TODO: probably not needed as it's generated, match on $impl throw new RuntimeException("implementation type mismatch", e); } + } - - final Method wrapMethod; + private static Method findWrapMethod(final Class implementation, final Class parameterType) { try { - wrapMethod = implClass.getMethod(WRAP, parameterType); + return implementation.getDeclaredMethod(WRAP, parameterType); + } catch (NoSuchMethodException e) { throw new RuntimeException("wrap method not found", e); } + } + + private static void ensureNotVoid(final Method wrap) { + if (wrap.getReturnType() == void.class) { + throw new RuntimeException("wrap method is void"); + } + } + private static Object invoke(final Method wrap, final Object... original) { try { - return interfaceType.cast(wrapMethod.invoke(null, original)); + return wrap.invoke(null, original); + } catch (IllegalAccessException e) { throw new RuntimeException("wrap method inaccessible", e); + } catch (InvocationTargetException e) { throw new RuntimeException("wrap method threw exception", e); + } + } + + private static T cast(final Object result, final Class definition) { + try { + return definition.cast(result); + } catch (ClassCastException e) { - // TODO: probably not needed as it's generated, match on $impl throw new RuntimeException("wrap method return type mismatch", e); } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java new file mode 100644 index 000000000..20ae068e0 --- /dev/null +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java @@ -0,0 +1,157 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static com.inrupt.rdf.wrapping.processor.Manager.wrap; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThrows; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import java.util.stream.Stream; + +import org.apache.jena.query.Dataset; +import org.apache.jena.query.DatasetFactory; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +@DisplayName("Manager") +class ManagerTest { + @DisplayName("fails to wrap with error") + @ParameterizedTest(name = "[{1}] when definition is [{0}]") + @MethodSource + void wrapFails(final Class definition, final String error) { + final Model model = ModelFactory.createDefaultModel(); + + final Throwable t = assertThrows(RuntimeException.class, () -> wrap(model, definition)); + assertThat(t, hasProperty("message", is(error))); + } + + static Stream wrapFails() { + return Stream.of( + arguments(NoImplementation.class, "implementation not found"), + arguments(ImplementationTypeMismatch.class, "implementation type mismatch"), + arguments(WrapMissing.class, "wrap method not found"), + arguments(WrapVoid.class, "wrap method is void"), + arguments(WrapInaccessible.class, "wrap method inaccessible"), + arguments(WrapThrows.class, "wrap method threw exception"), + arguments(WrapMismatch.class, "wrap method return type mismatch") + ); + } + + @Test + @DisplayName("wraps graph") + void wrapModel() { + final Model model = ModelFactory.createDefaultModel(); + + assertDoesNotThrow(() -> wrap(model, OkModel.class)); + } + + @Test + @DisplayName("wraps dataset") + void wrapDataset() { + final Dataset dataset = DatasetFactory.create(); + + assertDoesNotThrow(() -> wrap(dataset, OkDataset.class)); + } +} + +interface NoImplementation { +} + +interface ImplementationTypeMismatch { +} + +class ImplementationTypeMismatch_$impl { +} + +interface WrapMissing { +} + +class WrapMissing_$impl implements WrapMissing { +} + +interface WrapVoid { +} + +@SuppressWarnings("HideUtilityClassConstructor") // Not really a utility class +class WrapVoid_$impl implements WrapVoid { + public static void wrap(final Model ignored) { + } +} + +interface WrapInaccessible { +} + +class WrapInaccessible_$impl implements WrapInaccessible { + private static WrapInaccessible wrap(final Model ignored) { + return null; + } +} + +interface WrapThrows { +} + +@SuppressWarnings("HideUtilityClassConstructor") // Not really a utility class +class WrapThrows_$impl implements WrapThrows { + public static Object wrap(final Model ignored) { + throw new RuntimeException(); + } +} + +interface WrapMismatch { +} + +@SuppressWarnings("HideUtilityClassConstructor") // Not really a utility class +class WrapMismatch_$impl implements WrapMismatch { + public static Object wrap(final Model ignored) { + return new Object(); + } +} + +interface OkModel { +} + +@SuppressWarnings("HideUtilityClassConstructor") // Not really a utility class +class OkModel_$impl implements OkModel { + public static OkModel wrap(final Model ignored) { + return new OkModel() { + }; + } +} + +interface OkDataset { +} + +@SuppressWarnings("HideUtilityClassConstructor") // Not really a utility class +class OkDataset_$impl implements OkDataset { + public static OkDataset wrap(final Dataset ignored) { + return new OkDataset() { + }; + } +} From 8cf27e0d15db223175e156ee571f1a6e3a94e95f Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 17 Feb 2024 19:40:55 +0000 Subject: [PATCH 079/141] Extract wrapping processing environment --- .../rdf/wrapping/processor/Environment.java | 56 ++-------------- .../WrapperProcessingEnvironment.java | 67 +++++++++++++++++++ 2 files changed, 72 insertions(+), 51 deletions(-) create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java index f2adff8e7..832d7cdf7 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java @@ -22,25 +22,18 @@ import com.inrupt.rdf.wrapping.jena.ValueMappings; -import java.util.Locale; -import java.util.Map; import java.util.stream.Stream; -import javax.annotation.processing.Filer; -import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; -class Environment implements ProcessingEnvironment { - TypeMirror mirror(final Class clazz) { - return type(clazz).asType(); +class Environment extends WrapperProcessingEnvironment { + Environment(final ProcessingEnvironment env) { + super(env); } TypeElement type(final Class clazz) { @@ -67,46 +60,7 @@ Stream methodsOf(final Class clazz) { return methodsOf(type(clazz)); } - // region pass-through - private final ProcessingEnvironment env; - - Environment(final ProcessingEnvironment env) { - this.env = env; - } - - @Override - public Map getOptions() { - return env.getOptions(); - } - - @Override - public Messager getMessager() { - return env.getMessager(); - } - - @Override - public Filer getFiler() { - return env.getFiler(); - } - - @Override - public Elements getElementUtils() { - return env.getElementUtils(); - } - - @Override - public Types getTypeUtils() { - return env.getTypeUtils(); - } - - @Override - public SourceVersion getSourceVersion() { - return env.getSourceVersion(); - } - - @Override - public Locale getLocale() { - return env.getLocale(); + private TypeMirror mirror(final Class clazz) { + return type(clazz).asType(); } - // endregion } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java new file mode 100644 index 000000000..1c168712b --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java @@ -0,0 +1,67 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import java.util.Locale; +import java.util.Map; + +import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.SourceVersion; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; + +class WrapperProcessingEnvironment implements ProcessingEnvironment { + protected final ProcessingEnvironment env; + + public WrapperProcessingEnvironment(final ProcessingEnvironment env) { + this.env = env; + } + + public Map getOptions() { + return env.getOptions(); + } + + public Messager getMessager() { + return env.getMessager(); + } + + public Filer getFiler() { + return env.getFiler(); + } + + public Elements getElementUtils() { + return env.getElementUtils(); + } + + public Types getTypeUtils() { + return env.getTypeUtils(); + } + + public SourceVersion getSourceVersion() { + return env.getSourceVersion(); + } + + public Locale getLocale() { + return env.getLocale(); + } +} From 42062613e010d2a4b78d7c428123fda785239c8f Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 18 Feb 2024 13:15:36 +0000 Subject: [PATCH 080/141] Tidy implementor test --- .../wrapping/processor/ImplementorTest.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java index d6b7533fd..26dd175a5 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java @@ -20,7 +20,9 @@ */ package com.inrupt.rdf.wrapping.processor; -import static javax.lang.model.type.TypeKind.VOID; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasProperty; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -32,32 +34,30 @@ import javax.lang.model.element.Name; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; -import javax.lang.model.type.NoType; -import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +@DisplayName("Implementor") class ImplementorTest { @Test - void x() throws IOException { + @DisplayName("fails to implement when filer can't write") + void failsToWrite() throws IOException { final TypeElement type = mock(TypeElement.class); final Interface myInterface = mock(Interface.class); - final TypeMirror mirror = mock(NoType.class); final Environment env = mock(Environment.class); final Elements elementUtils = mock(Elements.class); final Name name = mock(Name.class); final PackageElement packageElement = mock(PackageElement.class); final Filer filer = mock(Filer.class); - when(mirror.getKind()).thenReturn(VOID); - when(type.asType()).thenReturn(mirror); when(myInterface.getType()).thenReturn(type); when(myInterface.getEnv()).thenReturn(env); when(elementUtils.getBinaryName(any())).thenReturn(name); when(packageElement.getQualifiedName()).thenReturn(name); when(elementUtils.getPackageOf(any())).thenReturn(packageElement); - when(filer.createSourceFile(any())).thenThrow(IOException.class); + when(filer.createSourceFile(any())).thenThrow(IOException.class); // Substance when(env.getElementUtils()).thenReturn(elementUtils); when(env.getFiler()).thenReturn(filer); @@ -67,6 +67,7 @@ protected void implementInternal() { } }; - assertThrows(RuntimeException.class, mock::implement); + final Throwable t = assertThrows(RuntimeException.class, mock::implement); + assertThat(t, hasProperty("message", is("could not open writer"))); } } From 4aef33268b2806e4ce0e960874674b5484e0e955 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 18 Feb 2024 13:36:51 +0000 Subject: [PATCH 081/141] More reliance on interfaces --- .../wrapping/processor/DatasetImplementor.java | 5 ++--- .../wrapping/processor/DatasetValidator.java | 6 ++---- .../wrapping/processor/GraphImplementor.java | 4 ++-- .../rdf/wrapping/processor/GraphValidator.java | 6 ++---- .../rdf/wrapping/processor/Implementor.java | 12 ++++++------ .../rdf/wrapping/processor/Interface.java | 17 +++++++++++++++++ .../rdf/wrapping/processor/Processor.java | 6 ++++-- .../wrapping/processor/ResourceImplementor.java | 5 ++--- .../wrapping/processor/ResourceValidator.java | 5 ++--- .../rdf/wrapping/processor/Validator.java | 16 ++++++---------- 10 files changed, 45 insertions(+), 37 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 7c0a0c6de..c7de2ca9a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -28,7 +28,6 @@ import javax.annotation.Generated; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; import org.apache.jena.query.Dataset; import org.apache.jena.sparql.core.DatasetGraph; @@ -38,8 +37,8 @@ import org.jboss.jdeparser.JType; class DatasetImplementor extends Implementor { - DatasetImplementor(final TypeElement type, final Environment env) { - super(new DatasetInterface(type, env)); + DatasetImplementor(final DatasetInterface definition) { + super(definition); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java index 7c35d801d..1481668c6 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java @@ -24,13 +24,11 @@ import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.NamedGraph; -import javax.lang.model.element.TypeElement; - import org.apache.jena.query.Dataset; class DatasetValidator extends Validator { - DatasetValidator(final TypeElement type, final Environment env) { - super(new DatasetInterface(type, env)); + DatasetValidator(final DatasetInterface definition) { + super(definition); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 26489f94e..211a9132d 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -44,8 +44,8 @@ import org.jboss.jdeparser.JType; class GraphImplementor extends Implementor { - GraphImplementor(final TypeElement type, final Environment env) { - super(new GraphInterface(type, env)); + GraphImplementor(final GraphInterface definition) { + super(definition); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java index f557ebf9b..438634efb 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java @@ -25,13 +25,11 @@ import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; import com.inrupt.rdf.wrapping.annotation.Resource; -import javax.lang.model.element.TypeElement; - import org.apache.jena.rdf.model.Model; class GraphValidator extends Validator { - GraphValidator(final TypeElement type, final Environment env) { - super(new GraphInterface(type, env)); + GraphValidator(final GraphInterface definition) { + super(definition); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 0d00f7227..5082396cc 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -79,16 +79,16 @@ void implement() { protected abstract void implementInternal(); - static Implementor implementor(final Environment env, final TypeElement e) { - if (e.getAnnotation(Dataset.class) != null) { - return new DatasetImplementor(e, env); + static Implementor implementor(final Interface definition) { + if (definition instanceof DatasetInterface) { + return new DatasetImplementor((DatasetInterface) definition); - } else if (e.getAnnotation(Graph.class) != null) { - return new GraphImplementor(e, env); + } else if (definition instanceof GraphInterface) { + return new GraphImplementor((GraphInterface) definition); } else { // Resource // Processor's supported annotations are finite - return new ResourceImplementor(e, env); + return new ResourceImplementor((ResourceInterface) definition); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java index 65f1bf38a..68022c86b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -22,6 +22,9 @@ import static org.jboss.jdeparser.JTypes.typeOf; +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.Graph; + import java.lang.annotation.Annotation; import java.util.stream.Stream; @@ -40,6 +43,20 @@ class Interface { this.type = type; } + static Interface definition(final TypeElement type, final Environment env) { + if (type.getAnnotation(Dataset.class) != null) { + return new DatasetInterface(type, env); + + } else if (type.getAnnotation(Graph.class) != null) { + return new GraphInterface(type, env); + + } else { // Resource + // Processor's supported annotations are finite + return new ResourceInterface(type, env); + } + } + + protected TypeElement getType() { return type; } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java index 46c145b30..6aa5613eb 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java @@ -21,6 +21,7 @@ package com.inrupt.rdf.wrapping.processor; import static com.inrupt.rdf.wrapping.processor.Implementor.implementor; +import static com.inrupt.rdf.wrapping.processor.Interface.definition; import static com.inrupt.rdf.wrapping.processor.Validator.validator; import static java.util.stream.Collectors.toSet; import static javax.lang.model.SourceVersion.RELEASE_8; @@ -64,8 +65,9 @@ public boolean process(final Set annotations, final Round // All our annotations are @Target(TYPE), so they're all TypeElements final TypeElement type = (TypeElement) element; - implementors.add(implementor(env, type)); - validationErrors.addAll(validator(type, env).validate()); + final Interface definition = definition(type, env); + implementors.add(implementor(definition)); + validationErrors.addAll(validator(definition).validate()); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index db3400d28..d7fefbd57 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -31,7 +31,6 @@ import javax.annotation.Generated; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.graph.Node; @@ -43,8 +42,8 @@ class ResourceImplementor extends Implementor { static final String FACTORY = "factory"; - ResourceImplementor(final TypeElement type, final Environment env) { - super(new ResourceInterface(type, env)); + ResourceImplementor(final ResourceInterface definition) { + super(definition); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 1b531c72f..87d7e545d 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -25,12 +25,11 @@ import com.inrupt.rdf.wrapping.jena.ValueMappings; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; class ResourceValidator extends Validator { - ResourceValidator(final TypeElement type, final Environment env) { - super(new ResourceInterface(type, env)); + ResourceValidator(final ResourceInterface definition) { + super(definition); } @Override diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 3e4f51d59..fd7d31ebd 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -22,9 +22,6 @@ import static javax.lang.model.element.Modifier.STATIC; -import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.Graph; - import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; @@ -32,7 +29,6 @@ import java.util.function.Predicate; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; abstract class Validator { @@ -43,16 +39,16 @@ protected Validator(final T myInterface) { this.myInterface = myInterface; } - static Validator validator(final TypeElement type, final Environment env) { - if (type.getAnnotation(Dataset.class) != null) { - return new DatasetValidator(type, env); + static Validator validator(final Interface definition) { + if (definition instanceof DatasetInterface) { + return new DatasetValidator((DatasetInterface) definition); - } else if (type.getAnnotation(Graph.class) != null) { - return new GraphValidator(type, env); + } else if (definition instanceof GraphInterface) { + return new GraphValidator((GraphInterface) definition); } else { // Resource // Processor's supported annotations are finite - return new ResourceValidator(type, env); + return new ResourceValidator((ResourceInterface) definition); } } From 752a7a37ab1c8c3db67004c848111356740b6cb7 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 18 Feb 2024 15:11:54 +0000 Subject: [PATCH 082/141] Cover wrapper processing environment --- .../WrapperProcessingEnvironment.java | 20 ++--- .../WrapperProcessingEnvironmentTest.java | 84 +++++++++++++++++++ 2 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 processor/src/test/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironmentTest.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java index 1c168712b..e7bf3cc0c 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java @@ -31,37 +31,37 @@ import javax.lang.model.util.Types; class WrapperProcessingEnvironment implements ProcessingEnvironment { - protected final ProcessingEnvironment env; + protected final ProcessingEnvironment original; - public WrapperProcessingEnvironment(final ProcessingEnvironment env) { - this.env = env; + public WrapperProcessingEnvironment(final ProcessingEnvironment original) { + this.original = original; } public Map getOptions() { - return env.getOptions(); + return original.getOptions(); } public Messager getMessager() { - return env.getMessager(); + return original.getMessager(); } public Filer getFiler() { - return env.getFiler(); + return original.getFiler(); } public Elements getElementUtils() { - return env.getElementUtils(); + return original.getElementUtils(); } public Types getTypeUtils() { - return env.getTypeUtils(); + return original.getTypeUtils(); } public SourceVersion getSourceVersion() { - return env.getSourceVersion(); + return original.getSourceVersion(); } public Locale getLocale() { - return env.getLocale(); + return original.getLocale(); } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironmentTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironmentTest.java new file mode 100644 index 000000000..99710d92f --- /dev/null +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironmentTest.java @@ -0,0 +1,84 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.hamcrest.beans.PropertyUtil.propertyDescriptorsFor; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.beans.PropertyDescriptor; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Stream; + +import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.SourceVersion; +import javax.lang.model.util.Elements; +import javax.lang.model.util.Types; + +import org.hamcrest.Matcher; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +@DisplayName("Wrapper processing environment") +class WrapperProcessingEnvironmentTest { + private static final ProcessingEnvironment original = mock(ProcessingEnvironment.class); + private static final ProcessingEnvironment wrapper = new WrapperProcessingEnvironment(original); + + @BeforeAll + static void beforeAll() { + // Mocks suffice as we're testing only for reference equality + when(original.getOptions()).thenReturn(mock(Map.class)); + when(original.getMessager()).thenReturn(mock(Messager.class)); + when(original.getFiler()).thenReturn(mock(Filer.class)); + when(original.getElementUtils()).thenReturn(mock(Elements.class)); + when(original.getTypeUtils()).thenReturn(mock(Types.class)); + when(original.getSourceVersion()).thenReturn(mock(SourceVersion.class)); + when(original.getLocale()).thenReturn(mock(Locale.class)); + } + + @DisplayName("returns original value for property") + @ParameterizedTest(name = "{0}") + @MethodSource("propertiesOfWrapper") + void roundtrips(final String propertyName, final PropertyDescriptor descriptor) throws Exception { + final Object originalValue = descriptor.getReadMethod().invoke(original); + + final Matcher sameAsOriginal = describedAs("the same instance as the original's", + is(theInstance(originalValue))); + final Matcher roundtripsProperty = describedAs("Wrapper property which is %0", + hasProperty(propertyName, is(sameAsOriginal)), + sameAsOriginal); + + assertThat("Property differs", wrapper, roundtripsProperty); + } + + static Stream propertiesOfWrapper() { + return Stream.of(propertyDescriptorsFor(wrapper, Object.class)).map(d -> arguments(d.getName(), d)); + } +} From c005630a334eb629422e794775cec92e7cad24bd Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 18 Feb 2024 21:14:21 +0000 Subject: [PATCH 083/141] Represent all value mapping methods --- .../java/com/inrupt/rdf/wrapping/annotation/Property.java | 6 +++++- .../com/inrupt/rdf/wrapping/annotation/MappingTest.java | 2 -- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java index 1f0a52f42..91a83abf5 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java @@ -36,9 +36,13 @@ Mapping mapping(); enum Mapping { + AS("as"), IRI_AS_STRING("iriAsString"), IRI_AS_URI("iriAsUri"), - AS("as"); + LITERAL_AS_BOOLEAN("literalAsBoolean"), + LITERAL_AS_INSTANT("literalAsInstant"), + LITERAL_AS_INTEGER_OR_NULL("literalAsIntegerOrNull"), + LITERAL_AS_STRING("literalAsString"); private final String methodName; diff --git a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java index e4dae4a5c..537fcff90 100644 --- a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java +++ b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java @@ -34,7 +34,6 @@ import java.util.Collection; import java.util.stream.Stream; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -54,7 +53,6 @@ void constantHasEquivalentMethod(final Mapping mapping) { assertThat(mapping.getMethodName(), is(in(MAPPING_METHODS))); } - @Disabled("not ready yet") // TODO: Enable when ready @DisplayName("has enum constant equivalent to ValueMappings method") @ParameterizedTest(name = "{0}") @MethodSource("mappingMethods") From 9dc786c25ab61a72abab9d7577c1fa30893d5510 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 18 Feb 2024 21:16:32 +0000 Subject: [PATCH 084/141] Better describe property mapping correspondence --- .../rdf/wrapping/annotation/MappingTest.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java index 537fcff90..d502c087e 100644 --- a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java +++ b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java @@ -25,8 +25,8 @@ import static java.util.Arrays.stream; import static java.util.stream.Collectors.toList; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.describedAs; import static org.hamcrest.Matchers.in; -import static org.hamcrest.Matchers.is; import com.inrupt.rdf.wrapping.jena.ValueMappings; @@ -34,6 +34,7 @@ import java.util.Collection; import java.util.stream.Stream; +import org.hamcrest.Matcher; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -50,14 +51,22 @@ class MappingTest { @ParameterizedTest(name = "{0}") @EnumSource(Mapping.class) void constantHasEquivalentMethod(final Mapping mapping) { - assertThat(mapping.getMethodName(), is(in(MAPPING_METHODS))); + final Matcher hasCorrespondingMethod = describedAs("ValueMappings to have corresponding method", + in(MAPPING_METHODS)); + + assertThat("Mapping enum constant without corresponding ValueMappings method", + mapping.getMethodName(), hasCorrespondingMethod); } @DisplayName("has enum constant equivalent to ValueMappings method") @ParameterizedTest(name = "{0}") @MethodSource("mappingMethods") void methodHasEquivalentConstant(final String method) { - assertThat(method, is(in(ENUM_CONSTANTS))); + final Matcher hasCorrespondingConstant = describedAs("Mapping enum to have corresponding constant", + in(ENUM_CONSTANTS)); + + assertThat("ValueMappings method without corresponding Mapping enum constant", + method, hasCorrespondingConstant); } private static Stream mappingMethods() { From 0afc6a60f7fb12cfab103fb93a4d98419e06fc99 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 18 Feb 2024 22:18:17 +0000 Subject: [PATCH 085/141] Validate the resource property methods are not void --- .../rdf/wrapping/processor/Interface.java | 1 - .../wrapping/processor/ResourceValidator.java | 19 ++++++++++++++++++- .../rdf/wrapping/processor/ValidatorTest.java | 1 + .../bad/resource property method is void.java | 13 +++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/bad/resource property method is void.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java index 68022c86b..a5370b7b3 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java @@ -73,7 +73,6 @@ protected final Stream membersAnnotatedWith(final Class !method.isDefault()) .filter(method -> !method.getModifiers().contains(Modifier.STATIC)) - .filter(method -> !getEnv().isVoid(method.getReturnType())) .filter(method -> method.getAnnotation(annotation) != null); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 87d7e545d..5264cebbe 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -25,6 +25,7 @@ import com.inrupt.rdf.wrapping.jena.ValueMappings; import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; class ResourceValidator extends Validator { @@ -42,10 +43,25 @@ protected void validateInternal() { requireNonMemberMethods(Property.class); + requireNonVoidReturnType(); requireCompatiblePrimitiveReturnType(); requireCompatibleComplexReturnType(); } + private void requireNonVoidReturnType() { + myInterface.membersAnnotatedWith(Property.class) + .forEach(method -> { + final TypeElement returnType = myInterface.getEnv().type(method.getReturnType()); + + if (returnType == null) { + errors.add(new ValidationError( + method, + "Property method [%s] must not be void", + method.getSimpleName())); + } + }); + } + private void requireCompatiblePrimitiveReturnType() { myInterface.primitiveMappingPropertyMethods() .forEach(method -> { @@ -69,7 +85,8 @@ private void requireCompatiblePrimitiveReturnType() { private void requireCompatibleComplexReturnType() { myInterface.complexMappingPropertyMethods() .forEach(method -> { - if (myInterface.getEnv().type(method.getReturnType()).getAnnotation(Resource.class) == null) { + final TypeElement returnType = myInterface.getEnv().type(method.getReturnType()); + if (returnType != null && returnType.getAnnotation(Resource.class) == null) { errors.add(new ValidationError( method, "Method %s on interface %s must return @Resource interface", diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index e358722de..412422afd 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -93,6 +93,7 @@ private static Stream compilationErrorOnInvalid() { arguments("resource property method is default", CANNOT_BE_STATIC_OR_DEFAULT), arguments("resource instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), arguments("resource property method return type not assignable", "must be assignable from return type"), + arguments("resource property method is void", "must not be void"), arguments("resource complex property method is not resource", MUST_RETURN_RESOURCE_INTERFACE) ); } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is void.java b/processor/src/test/resources/validationExamples/bad/resource property method is void.java new file mode 100644 index 000000000..c11f12657 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource property method is void.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + @Property(predicate = "x", mapping = AS) + void x(); +} From d2c9d002614d0ab6a4e3314a3de5b04c8d95faa3 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Wed, 21 Feb 2024 21:14:31 +0000 Subject: [PATCH 086/141] Reproduce cycle on recursive resource property types --- .../rdf/wrapping/processor/ValidatorTest.java | 4 ++-- ...rce complex property method recursive.java | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/good/resource complex property method recursive.java diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 412422afd..2b5d09e4b 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -130,8 +130,8 @@ private static Stream compilationSucceeds() { arguments("resource property method is assignable instance"), arguments("resource unannotated method is static"), arguments("resource unannotated method is default"), - arguments("resource complex property method is resource instance") - + arguments("resource complex property method is resource instance"), + arguments("resource complex property method recursive") ); } } diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java new file mode 100644 index 000000000..91f621d63 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java @@ -0,0 +1,21 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Graph +interface X { + @OptionalFirstInstanceOfEither("x") + Y x(); + + @Resource + interface Y { + @Property(predicate = "x", mapping = AS) + Y x(); + } +} From a13005c83c32fd3d1e1c4fd801affffd98b90906 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Wed, 21 Feb 2024 21:16:00 +0000 Subject: [PATCH 087/141] Cut cycle on recursive resource property types --- .../wrapping/processor/ResourceInterface.java | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java index 7f8fd2285..dfff929b7 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java @@ -20,11 +20,13 @@ */ package com.inrupt.rdf.wrapping.processor; -import static java.util.stream.Stream.concat; - import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Set; import java.util.function.Predicate; import java.util.stream.Stream; @@ -54,15 +56,27 @@ Stream primitiveMappingPropertyMethods() { } Stream transitiveResourceTypes() { - final Stream children = resourcePropertyMethods().map(ExecutableElement::getReturnType); + final Queue outstanding = new LinkedList<>(); + final Set results = new HashSet<>(); + + ResourceInterface current = this; + while (true) { + current.resourcePropertyMethods() + .map(ExecutableElement::getReturnType) + .filter(results::add) + .forEach(outstanding::add); + + if (outstanding.isEmpty()) { + break; + } + + final TypeMirror next = outstanding.remove(); + final TypeElement nextType = getEnv().type(next); - final Stream descendants = resourcePropertyMethods() - .map(ExecutableElement::getReturnType) - .map(getEnv()::type) - .map(type -> new ResourceInterface(type, getEnv())) - .flatMap(ResourceInterface::transitiveResourceTypes); + current = new ResourceInterface(nextType, getEnv()); + } - return concat(children, descendants).distinct(); + return results.stream(); } private Predicate returnTypeIsResource() { From 096f6e8114e5a564af81c6ddb7155a28d6a22661 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 24 Feb 2024 14:15:35 +0000 Subject: [PATCH 088/141] Retain annotations at runtime --- .../main/java/com/inrupt/rdf/wrapping/annotation/Dataset.java | 4 ++-- .../java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java | 4 ++-- .../main/java/com/inrupt/rdf/wrapping/annotation/Graph.java | 4 ++-- .../java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java | 4 ++-- .../wrapping/annotation/OptionalFirstInstanceOfEither.java | 4 ++-- .../rdf/wrapping/annotation/OptionalFirstObjectOfEither.java | 4 ++-- .../rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java | 4 ++-- .../java/com/inrupt/rdf/wrapping/annotation/Property.java | 4 ++-- .../java/com/inrupt/rdf/wrapping/annotation/Resource.java | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Dataset.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Dataset.java index ce2c5f99d..0761e192e 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Dataset.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Dataset.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(TYPE) -@Retention(SOURCE) +@Retention(RUNTIME) @Documented public @interface Dataset { } diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java index a35f0a3ca..b4996ae7e 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.SOURCE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(METHOD) -@Retention(SOURCE) +@Retention(RUNTIME) @Documented public @interface DefaultGraph { } diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Graph.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Graph.java index f43078cab..0d8d3dccb 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Graph.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Graph.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(TYPE) -@Retention(SOURCE) +@Retention(RUNTIME) @Documented public @interface Graph { } diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java index d4db7e4b8..f4ad8fd3a 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.SOURCE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(METHOD) -@Retention(SOURCE) +@Retention(RUNTIME) @Documented public @interface NamedGraph { String value(); diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstInstanceOfEither.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstInstanceOfEither.java index 49f33d90f..63ec63c18 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstInstanceOfEither.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstInstanceOfEither.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.SOURCE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(METHOD) -@Retention(SOURCE) +@Retention(RUNTIME) @Documented public @interface OptionalFirstInstanceOfEither { String[] value(); diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java index ea0b112dd..f251471f7 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.SOURCE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(METHOD) -@Retention(SOURCE) +@Retention(RUNTIME) @Documented public @interface OptionalFirstObjectOfEither { String[] value(); diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java index ca845c3f1..187c29a8a 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.SOURCE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(METHOD) -@Retention(SOURCE) +@Retention(RUNTIME) @Documented public @interface OptionalFirstSubjectOfEither { String[] value(); diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java index 91a83abf5..83efa79d6 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.SOURCE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(METHOD) -@Retention(SOURCE) +@Retention(RUNTIME) @Documented public @interface Property { String predicate(); diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Resource.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Resource.java index 72300f460..d04c7d32b 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Resource.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Resource.java @@ -21,14 +21,14 @@ package com.inrupt.rdf.wrapping.annotation; import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.SOURCE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Target(TYPE) -@Retention(SOURCE) +@Retention(RUNTIME) @Documented public @interface Resource { } From 257d9654102cc0bec9908c63e15569a3625dbac7 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 24 Feb 2024 23:21:35 +0000 Subject: [PATCH 089/141] Cover resource definition --- .../processor/ResourceDefinitionTest.java | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java new file mode 100644 index 000000000..3272b27ac --- /dev/null +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java @@ -0,0 +1,170 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.*; +import static java.lang.reflect.Modifier.isPublic; +import static java.util.Arrays.stream; +import static java.util.UUID.randomUUID; +import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel; +import static org.apache.jena.rdf.model.ResourceFactory.createResource; +import static org.apache.jena.rdf.model.ResourceFactory.createTypedLiteral; +import static org.apache.jena.vocabulary.RDF.type; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Property.Mapping; +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.jena.ValueMappings; + +import java.lang.reflect.Method; +import java.net.URI; +import java.time.Instant; +import java.util.stream.Stream; + +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.RDFNode; +import org.hamcrest.Matcher; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class ResourceDefinitionTest { + private static final String P = "urn:example:p"; + private static final String C = "urn:example:c"; + private static final Object[] RESOURCE_DEFINITION_METHODS = stream(ResourceDefinition.class.getDeclaredMethods()) + .map(m -> m.getAnnotation(Property.class)) + .map(Property::mapping) + .map(Mapping::getMethodName) + .toArray(); + + private Model m; + private GraphDefinition wrapped; + + @BeforeEach + void setUp() { + m = createDefaultModel(); + wrapped = GraphDefinition.wrap(m); + } + + @DisplayName("properly converts node with mapping") + @ParameterizedTest(name = "{0}") + @MethodSource + void e2e(final Mapping mapping, final RDFNode original, final Object expected) { + final org.apache.jena.rdf.model.Property p = m.createProperty(P); + final org.apache.jena.rdf.model.Resource c = m.createResource(C); + + final Matcher isExpected; + final RDFNode o; + + if (mapping == AS) { + o = m.createResource().addProperty(p, (String) expected); // Complex properties need a bit more setup + isExpected = hasProperty(LITERAL_AS_STRING.getMethodName(), equalTo(expected)); // and matcher + } else { + o = original; // method source supplies value of object being wrapped + isExpected = equalTo(expected); // as well as expected value + } + + m.createResource() + .addProperty(type, c) // anchor for graph definition + .addProperty(p, o); // what's being wrapped + + assertThat(wrapped.getResource(), hasProperty(mapping.getMethodName(), isExpected)); + } + + private static Stream e2e() { + final String string = randomUUID().toString(); + final URI uri = URI.create(string); + final Instant instant = Instant.now(); + final boolean bool = true; + final Integer integer = instant.getNano(); + + final Literal stringLiteral = createTypedLiteral(string); + final org.apache.jena.rdf.model.Resource resource = createResource(string); + final Literal instantLiteral = createTypedLiteral(instant); + final Literal booleanLiteral = createTypedLiteral(bool); + final Literal integerLiteral = createTypedLiteral(integer); + + return Stream.of( + arguments(LITERAL_AS_STRING, stringLiteral, string), + arguments(IRI_AS_URI, resource, uri), + arguments(IRI_AS_STRING, resource, string), + arguments(LITERAL_AS_INSTANT, instantLiteral, instant), + arguments(LITERAL_AS_BOOLEAN, booleanLiteral, bool), + arguments(LITERAL_AS_INTEGER_OR_NULL, integerLiteral, integer), + arguments(AS, null, string) + ); + } + + @DisplayName("resource definition has equivalent of ValueMappings method") + @ParameterizedTest(name = "{0}") + @MethodSource + void valueMappingsMethods(final String name) { + assertThat(RESOURCE_DEFINITION_METHODS, hasItemInArray(name)); + } + + private static Stream valueMappingsMethods() { + return stream(ValueMappings.class.getDeclaredMethods()) + .filter(m -> isPublic(m.getModifiers())) + .map(Method::getName); + } + + @Resource + interface ResourceDefinition { + @Property(predicate = P, mapping = LITERAL_AS_STRING) + String getLiteralAsString(); + + @Property(predicate = P, mapping = IRI_AS_URI) + URI getIriAsUri(); + + @Property(predicate = P, mapping = IRI_AS_STRING) + String getIriAsString(); + + @Property(predicate = P, mapping = LITERAL_AS_INSTANT) + Instant getLiteralAsInstant(); + + @Property(predicate = P, mapping = LITERAL_AS_BOOLEAN) + Boolean getLiteralAsBoolean(); + + @Property(predicate = P, mapping = LITERAL_AS_INTEGER_OR_NULL) + Integer getLiteralAsIntegerOrNull(); + + @Property(predicate = P, mapping = Mapping.AS) + ResourceDefinition getAs(); + } + + @Graph + interface GraphDefinition { + static GraphDefinition wrap(final Model original) { + return Manager.wrap(original, GraphDefinition.class); + } + + @OptionalFirstInstanceOfEither(C) + ResourceDefinition getResource(); + } +} From 25b8cc72b16a45909b6788f6257eb2a0f7e3430f Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 24 Feb 2024 23:27:40 +0000 Subject: [PATCH 090/141] Update version of new modules --- annotation/pom.xml | 2 +- processor/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/annotation/pom.xml b/annotation/pom.xml index d67ae2f8d..e05983f15 100644 --- a/annotation/pom.xml +++ b/annotation/pom.xml @@ -4,7 +4,7 @@ com.inrupt.rdf inrupt-rdf-wrapping - 1.0.1-SNAPSHOT + 1.1.2-SNAPSHOT inrupt-rdf-wrapping-annotation diff --git a/processor/pom.xml b/processor/pom.xml index 289a0d2af..5f78978b3 100644 --- a/processor/pom.xml +++ b/processor/pom.xml @@ -4,7 +4,7 @@ com.inrupt.rdf inrupt-rdf-wrapping - 1.0.1-SNAPSHOT + 1.1.2-SNAPSHOT inrupt-rdf-wrapping-processor From 18bf2e531f90a5e8268ef874a6152ed782206f00 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 24 Feb 2024 23:30:30 +0000 Subject: [PATCH 091/141] Style --- .../com/inrupt/rdf/wrapping/processor/GraphImplementor.java | 1 - .../java/com/inrupt/rdf/wrapping/processor/Implementor.java | 3 --- 2 files changed, 4 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 211a9132d..7073bf205 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -33,7 +33,6 @@ import javax.annotation.Generated; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 5082396cc..93c3a7771 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -24,9 +24,6 @@ import static org.jboss.jdeparser.JTypes.$t; import static org.jboss.jdeparser.JTypes.typeOf; -import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.Graph; - import java.io.IOException; import java.time.Instant; From a0b698836653b034423a868c64255dfcbe523be4 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 25 Feb 2024 13:09:22 +0000 Subject: [PATCH 092/141] Tidy wrapper processing environment * Simplify test with mock annotations * Add override annotation --- processor/pom.xml | 2 +- .../WrapperProcessingEnvironment.java | 9 +++- .../WrapperProcessingEnvironmentTest.java | 42 +++++++------------ 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/processor/pom.xml b/processor/pom.xml index 5f78978b3..92fc600f4 100644 --- a/processor/pom.xml +++ b/processor/pom.xml @@ -55,7 +55,7 @@ org.mockito - mockito-core + mockito-junit-jupiter test diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java index e7bf3cc0c..aed59505e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironment.java @@ -33,34 +33,41 @@ class WrapperProcessingEnvironment implements ProcessingEnvironment { protected final ProcessingEnvironment original; - public WrapperProcessingEnvironment(final ProcessingEnvironment original) { + WrapperProcessingEnvironment(final ProcessingEnvironment original) { this.original = original; } + @Override public Map getOptions() { return original.getOptions(); } + @Override public Messager getMessager() { return original.getMessager(); } + @Override public Filer getFiler() { return original.getFiler(); } + @Override public Elements getElementUtils() { return original.getElementUtils(); } + @Override public Types getTypeUtils() { return original.getTypeUtils(); } + @Override public SourceVersion getSourceVersion() { return original.getSourceVersion(); } + @Override public Locale getLocale() { return original.getLocale(); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironmentTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironmentTest.java index 99710d92f..0835a22df 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironmentTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/WrapperProcessingEnvironmentTest.java @@ -20,48 +20,37 @@ */ package com.inrupt.rdf.wrapping.processor; +import static java.beans.Introspector.getBeanInfo; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.hamcrest.beans.PropertyUtil.propertyDescriptorsFor; import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Answers.RETURNS_DEEP_STUBS; +import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; -import java.util.Locale; -import java.util.Map; import java.util.stream.Stream; -import javax.annotation.processing.Filer; -import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.SourceVersion; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; import org.hamcrest.Matcher; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; @DisplayName("Wrapper processing environment") +@ExtendWith(MockitoExtension.class) class WrapperProcessingEnvironmentTest { - private static final ProcessingEnvironment original = mock(ProcessingEnvironment.class); - private static final ProcessingEnvironment wrapper = new WrapperProcessingEnvironment(original); + // Stubs suffice as we're testing only for reference equality + @Mock(answer = RETURNS_DEEP_STUBS) + ProcessingEnvironment original; - @BeforeAll - static void beforeAll() { - // Mocks suffice as we're testing only for reference equality - when(original.getOptions()).thenReturn(mock(Map.class)); - when(original.getMessager()).thenReturn(mock(Messager.class)); - when(original.getFiler()).thenReturn(mock(Filer.class)); - when(original.getElementUtils()).thenReturn(mock(Elements.class)); - when(original.getTypeUtils()).thenReturn(mock(Types.class)); - when(original.getSourceVersion()).thenReturn(mock(SourceVersion.class)); - when(original.getLocale()).thenReturn(mock(Locale.class)); - } + @InjectMocks + WrapperProcessingEnvironment wrapper; @DisplayName("returns original value for property") @ParameterizedTest(name = "{0}") @@ -78,7 +67,8 @@ void roundtrips(final String propertyName, final PropertyDescriptor descriptor) assertThat("Property differs", wrapper, roundtripsProperty); } - static Stream propertiesOfWrapper() { - return Stream.of(propertyDescriptorsFor(wrapper, Object.class)).map(d -> arguments(d.getName(), d)); + static Stream propertiesOfWrapper() throws IntrospectionException { + return Stream.of(getBeanInfo(WrapperProcessingEnvironment.class, Object.class).getPropertyDescriptors()) + .map(d -> arguments(d.getName(), d)); } } From 1e9880482ca99542631d302f9cfac3ccd0f373d6 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 25 Feb 2024 13:21:14 +0000 Subject: [PATCH 093/141] Tidy manager test --- .../rdf/wrapping/processor/ManagerTest.java | 99 +++++++++---------- 1 file changed, 47 insertions(+), 52 deletions(-) diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java index 20ae068e0..a6fa14f52 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java @@ -79,79 +79,74 @@ void wrapDataset() { assertDoesNotThrow(() -> wrap(dataset, OkDataset.class)); } -} -interface NoImplementation { -} + interface NoImplementation { + } -interface ImplementationTypeMismatch { -} + interface ImplementationTypeMismatch { + } -class ImplementationTypeMismatch_$impl { -} + static class ImplementationTypeMismatch_$impl { + } -interface WrapMissing { -} + interface WrapMissing { + } -class WrapMissing_$impl implements WrapMissing { -} + static class WrapMissing_$impl implements WrapMissing { + } -interface WrapVoid { -} + interface WrapVoid { + } -@SuppressWarnings("HideUtilityClassConstructor") // Not really a utility class -class WrapVoid_$impl implements WrapVoid { - public static void wrap(final Model ignored) { + static class WrapVoid_$impl implements WrapVoid { + static void wrap(final Model ignored) { + } } -} -interface WrapInaccessible { -} + interface WrapInaccessible { + } -class WrapInaccessible_$impl implements WrapInaccessible { - private static WrapInaccessible wrap(final Model ignored) { - return null; + static class WrapInaccessible_$impl implements WrapInaccessible { + private static WrapInaccessible wrap(final Model ignored) { + return null; + } } -} -interface WrapThrows { -} + interface WrapThrows { + } -@SuppressWarnings("HideUtilityClassConstructor") // Not really a utility class -class WrapThrows_$impl implements WrapThrows { - public static Object wrap(final Model ignored) { - throw new RuntimeException(); + static class WrapThrows_$impl implements WrapThrows { + static Object wrap(final Model ignored) { + throw new RuntimeException(); + } } -} -interface WrapMismatch { -} + interface WrapMismatch { + } -@SuppressWarnings("HideUtilityClassConstructor") // Not really a utility class -class WrapMismatch_$impl implements WrapMismatch { - public static Object wrap(final Model ignored) { - return new Object(); + static class WrapMismatch_$impl implements WrapMismatch { + static Object wrap(final Model ignored) { + return new Object(); + } } -} -interface OkModel { -} + interface OkModel { + } -@SuppressWarnings("HideUtilityClassConstructor") // Not really a utility class -class OkModel_$impl implements OkModel { - public static OkModel wrap(final Model ignored) { - return new OkModel() { - }; + static class OkModel_$impl implements OkModel { + static OkModel wrap(final Model ignored) { + return new OkModel() { + }; + } } -} -interface OkDataset { -} + interface OkDataset { + } -@SuppressWarnings("HideUtilityClassConstructor") // Not really a utility class -class OkDataset_$impl implements OkDataset { - public static OkDataset wrap(final Dataset ignored) { - return new OkDataset() { - }; + static class OkDataset_$impl implements OkDataset { + static OkDataset wrap(final Dataset ignored) { + return new OkDataset() { + }; + } } } From bcd9f4ffbe85685ea3fbd02608232bbaf806d020 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 25 Feb 2024 13:28:49 +0000 Subject: [PATCH 094/141] Tidy temp E2E test --- .../wrapping/processor/TemporaryE2ETest.java | 204 ++++++++++++++++++ .../com/inrupt/rdf/wrapping/processor/X.java | 80 ------- .../inrupt/rdf/wrapping/processor/XTest.java | 147 ------------- 3 files changed, 204 insertions(+), 227 deletions(-) create mode 100644 processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java delete mode 100644 processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java delete mode 100644 processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java new file mode 100644 index 000000000..2c552d79e --- /dev/null +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java @@ -0,0 +1,204 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.*; +import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import com.github.jsonldjava.shaded.com.google.common.base.Charsets; +import com.inrupt.rdf.wrapping.annotation.*; +import com.inrupt.rdf.wrapping.processor.TemporaryE2ETest.DatasetDefinition.GraphDefinition; +import com.inrupt.rdf.wrapping.processor.TemporaryE2ETest.DatasetDefinition.GraphDefinition.ResourceDefinition1; +import com.inrupt.rdf.wrapping.processor.TemporaryE2ETest.DatasetDefinition.GraphDefinition.ResourceDefinition2; +import com.inrupt.rdf.wrapping.processor.TemporaryE2ETest.DatasetDefinition.GraphDefinition.ResourceDefinition3; + +import java.net.URI; + +import org.apache.commons.io.IOUtils; +import org.apache.jena.query.Dataset; +import org.apache.jena.query.DatasetFactory; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.riot.Lang; +import org.apache.jena.riot.RDFDataMgr; +import org.junit.jupiter.api.Test; + +class TemporaryE2ETest { + @Test + void datasetCanWrap() { + final Dataset dataset = DatasetFactory.create(); + + assertDoesNotThrow(() -> DatasetDefinition.wrap(dataset)); + } + + @Test + void datasetCanGetDefaultGraph() { + final DatasetDefinition x = DatasetDefinition.wrap(DatasetFactory.create()); + + assertDoesNotThrow(x::getDefaultGraph); + } + + @Test + void datasetCanGetNamedGraph() { + final DatasetDefinition x = DatasetDefinition.wrap(DatasetFactory.create()); + + assertDoesNotThrow(x::getNamedGraph); + } + + @Test + void graphCanWrap() { + final Model model = createDefaultModel(); + + assertDoesNotThrow(() -> GraphDefinition.wrap(model)); + } + + @Test + void graphCanGetFirstInstanceOf() { + final Model model = createDefaultModel(); + final GraphDefinition y = GraphDefinition.wrap(model); + + assertDoesNotThrow(y::getResource1); + } + + @Test + void graphCanGetFirstSubjectOf() { + final Model model = createDefaultModel(); + final GraphDefinition y = GraphDefinition.wrap(model); + + assertDoesNotThrow(y::getResource2); + } + + @Test + void graphCanGetFirstObjectOf() { + final Model model = createDefaultModel(); + final GraphDefinition y = GraphDefinition.wrap(model); + + assertDoesNotThrow(y::getResource3); + } + + @Test + void resourceCanGetProperty() { + final Model model = modelFrom("PREFIX : \n" + + "\n" + + "[\n" + + " a :C ;\n" + + "] .\n"); + final GraphDefinition y = GraphDefinition.wrap(model); + final ResourceDefinition1 z = y.getResource1(); + + assertDoesNotThrow(z::getProperty1); + } + + @Test + void e2e() { + final Dataset dataset = datasetFrom("PREFIX : \n" + + "\n" + + "GRAPH {\n" + + " [\n" + + " a :C ;\n" + + " :p :VALUE ;\n" + + " ] .\n" + + "\n" + + " [ :p [] ] .\n" + + "}\n"); + + final DatasetDefinition x = DatasetDefinition.wrap(dataset); + final GraphDefinition y = x.getNamedGraph(); + final ResourceDefinition1 z = y.getResource1(); + final ResourceDefinition1 z2 = y.getResource2(); + final ResourceDefinition1 z3 = y.getResource3(); + final String p = z.getProperty1(); + final URI p2 = z.getProperty2(); + final ResourceDefinition2 p3 = z.getProperty3(); + final ResourceDefinition3 p4 = p3.getProperty(); + + System.out.println(z); + System.out.println(z2); + System.out.println(z3); + System.out.println(p); + System.out.println(p2); + System.out.println(p3); + System.out.println(p4); + } + + private static Dataset datasetFrom(final String rdf) { + final Dataset dataset = DatasetFactory.create(); + RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); + return dataset; + } + + private static Model modelFrom(final String rdf) { + final Model model = createDefaultModel(); + RDFDataMgr.read(model, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); + return model; + } + + @com.inrupt.rdf.wrapping.annotation.Dataset + interface DatasetDefinition { + static DatasetDefinition wrap(final Dataset original) { + return Manager.wrap(original, DatasetDefinition.class); + } + + @DefaultGraph + GraphDefinition getDefaultGraph(); + + @NamedGraph("urn:example:g1") + GraphDefinition getNamedGraph(); + + @Graph + interface GraphDefinition { + static GraphDefinition wrap(final Model original) { + return Manager.wrap(original, GraphDefinition.class); + } + + @OptionalFirstInstanceOfEither({"urn:example:C", "urn:example:Other"}) + ResourceDefinition1 getResource1(); + + @OptionalFirstSubjectOfEither({"urn:example:p", "urn:example:Other"}) + ResourceDefinition1 getResource2(); + + @OptionalFirstObjectOfEither({"urn:example:p", "urn:example:Other"}) + ResourceDefinition1 getResource3(); + + @Resource + interface ResourceDefinition1 { + @Property(predicate = "urn:example:p", mapping = IRI_AS_STRING) + String getProperty1(); + + @Property(predicate = "urn:example:p", mapping = IRI_AS_URI) + URI getProperty2(); + + @Property(predicate = "urn:example:p", mapping = AS) + ResourceDefinition2 getProperty3(); + } + + @Resource + interface ResourceDefinition2 { + @Property(predicate = "urn:example:p", mapping = AS) + ResourceDefinition3 getProperty(); + } + + @Resource + interface ResourceDefinition3 { + } + } + } +} diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java deleted file mode 100644 index 16292bf1c..000000000 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/X.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.processor; - -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.*; - -import com.inrupt.rdf.wrapping.annotation.*; - -import java.net.URI; - -import org.apache.jena.rdf.model.Model; - -@Dataset -interface X { - static X wrap(final org.apache.jena.query.Dataset original) { - return Manager.wrap(original, X.class); - } - - @DefaultGraph - Y getDefaultGraph(); - - @NamedGraph("urn:example:g1") - Y getNamedGraph(); - - @Graph - interface Y { - static Y wrap(final Model original) { - return Manager.wrap(original, Y.class); - } - - @OptionalFirstInstanceOfEither({"urn:example:C", "urn:example:Other"}) - Z getResource(); - - @OptionalFirstSubjectOfEither({"urn:example:p", "urn:example:Other"}) - Z getResource2(); - - @OptionalFirstObjectOfEither({"urn:example:p", "urn:example:Other"}) - Z getResource3(); - - @Resource - interface Z { - @Property(predicate = "urn:example:p", mapping = IRI_AS_STRING) - String getProperty(); - - @Property(predicate = "urn:example:p", mapping = IRI_AS_URI) - URI getProperty2(); - - @Property(predicate = "urn:example:p", mapping = AS) - Z2 getProperty3(); - } - - @Resource - interface Z2 { - @Property(predicate = "urn:example:p", mapping = AS) - Z3 getProperty(); - } - - @Resource - interface Z3 { - } - } -} diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java deleted file mode 100644 index fc8bd85f1..000000000 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/XTest.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.processor; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; - -import com.github.jsonldjava.shaded.com.google.common.base.Charsets; - -import java.net.URI; - -import org.apache.commons.io.IOUtils; -import org.apache.jena.query.Dataset; -import org.apache.jena.query.DatasetFactory; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.ModelFactory; -import org.apache.jena.riot.Lang; -import org.apache.jena.riot.RDFDataMgr; -import org.junit.jupiter.api.Test; - -class XTest { - @Test - void datasetCanWrap() { - final Dataset dataset = DatasetFactory.create(); - - assertDoesNotThrow(() -> X.wrap(dataset)); - } - - @Test - void datasetCanGetDefaultGraph() { - final X x = X.wrap(DatasetFactory.create()); - - assertDoesNotThrow(x::getDefaultGraph); - } - - @Test - void datasetCanGetNamedGraph() { - final X x = X.wrap(DatasetFactory.create()); - - assertDoesNotThrow(x::getNamedGraph); - } - - @Test - void graphCanWrap() { - final Model model = ModelFactory.createDefaultModel(); - - assertDoesNotThrow(() -> X.Y.wrap(model)); - } - - @Test - void graphCanGetFirstInstanceOf() { - final Model model = ModelFactory.createDefaultModel(); - final X.Y y = X.Y.wrap(model); - - assertDoesNotThrow(y::getResource); - } - - @Test - void graphCanGetFirstSubjectOf() { - final Model model = ModelFactory.createDefaultModel(); - final X.Y y = X.Y.wrap(model); - - assertDoesNotThrow(y::getResource2); - } - - @Test - void graphCanGetFirstObjectOf() { - final Model model = ModelFactory.createDefaultModel(); - final X.Y y = X.Y.wrap(model); - - assertDoesNotThrow(y::getResource3); - } - - @Test - void resourceCanGetProperty() { - final Model model = modelFrom("PREFIX : \n" + - "\n" + - "[\n" + - " a :C ;\n" + - "] .\n"); - final X.Y y = X.Y.wrap(model); - final X.Y.Z z = y.getResource(); - - assertDoesNotThrow(z::getProperty); - } - - @Test - void e2e() { - final Dataset dataset = datasetFrom("PREFIX : \n" + - "\n" + - "GRAPH {\n" + - " [\n" + - " a :C ;\n" + - " :p :VALUE ;\n" + - " ] .\n" + - "\n" + - " [ :p [] ] .\n" + - "}\n"); - - final X x = X.wrap(dataset); - final X.Y y = x.getNamedGraph(); - final X.Y.Z z = y.getResource(); - final X.Y.Z z2 = y.getResource2(); - final X.Y.Z z3 = y.getResource3(); - final String p = z.getProperty(); - final URI p2 = z.getProperty2(); - final X.Y.Z2 p3 = z.getProperty3(); - final X.Y.Z3 p4 = p3.getProperty(); - - System.out.println(z); - System.out.println(z2); - System.out.println(z3); - System.out.println(p); - System.out.println(p2); - System.out.println(p3); - System.out.println(p4); - } - - private static Dataset datasetFrom(final String rdf) { - final Dataset dataset = DatasetFactory.create(); - RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); - return dataset; - } - - private static Model modelFrom(final String rdf) { - final Model model = ModelFactory.createDefaultModel(); - RDFDataMgr.read(model, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); - return model; - } -} From 0684c4455038b2732b7d358c000c693c8953b395 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 25 Feb 2024 17:31:22 +0000 Subject: [PATCH 095/141] Fix resource definition property method validation --- .../wrapping/processor/ResourceValidator.java | 16 ++++++++-------- .../rdf/wrapping/processor/ValidatorTest.java | 5 +++-- ...resource complex property method is void.java | 13 +++++++++++++ .../bad/resource property method is void.java | 4 ++-- 4 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/bad/resource complex property method is void.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 5264cebbe..4bef6397d 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -20,6 +20,8 @@ */ package com.inrupt.rdf.wrapping.processor; +import static javax.lang.model.type.TypeKind.VOID; + import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.jena.ValueMappings; @@ -50,20 +52,17 @@ protected void validateInternal() { private void requireNonVoidReturnType() { myInterface.membersAnnotatedWith(Property.class) - .forEach(method -> { - final TypeElement returnType = myInterface.getEnv().type(method.getReturnType()); - - if (returnType == null) { + .filter(method -> method.getReturnType().getKind() == VOID) + .forEach(method -> errors.add(new ValidationError( method, "Property method [%s] must not be void", - method.getSimpleName())); - } - }); + method.getSimpleName()))); } private void requireCompatiblePrimitiveReturnType() { myInterface.primitiveMappingPropertyMethods() + .filter(method -> method.getReturnType().getKind() != VOID) .forEach(method -> { final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); @@ -84,9 +83,10 @@ private void requireCompatiblePrimitiveReturnType() { private void requireCompatibleComplexReturnType() { myInterface.complexMappingPropertyMethods() + .filter(method -> method.getReturnType().getKind() != VOID) .forEach(method -> { final TypeElement returnType = myInterface.getEnv().type(method.getReturnType()); - if (returnType != null && returnType.getAnnotation(Resource.class) == null) { + if (returnType == null || returnType.getAnnotation(Resource.class) == null) { errors.add(new ValidationError( method, "Method %s on interface %s must return @Resource interface", diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 2b5d09e4b..7b124284d 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -93,8 +93,9 @@ private static Stream compilationErrorOnInvalid() { arguments("resource property method is default", CANNOT_BE_STATIC_OR_DEFAULT), arguments("resource instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), arguments("resource property method return type not assignable", "must be assignable from return type"), - arguments("resource property method is void", "must not be void"), - arguments("resource complex property method is not resource", MUST_RETURN_RESOURCE_INTERFACE) + arguments("resource property method is void", MUST_NOT_BE_VOID), + arguments("resource complex property method is not resource", MUST_RETURN_RESOURCE_INTERFACE), + arguments("resource complex property method is void", MUST_NOT_BE_VOID) ); } diff --git a/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java b/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java new file mode 100644 index 000000000..c11f12657 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + @Property(predicate = "x", mapping = AS) + void x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is void.java b/processor/src/test/resources/validationExamples/bad/resource property method is void.java index c11f12657..28fe77e2a 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is void.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is void.java @@ -1,13 +1,13 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", mapping = AS) + @Property(predicate = "x", mapping = IRI_AS_STRING) void x(); } From de24e91d986bd3eda6c5730a43f3b63f8cfcb561 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 25 Feb 2024 17:49:39 +0000 Subject: [PATCH 096/141] Validate that dataset graph methods are not void --- .../rdf/wrapping/processor/DatasetValidator.java | 3 +++ .../rdf/wrapping/processor/ResourceValidator.java | 12 +----------- .../com/inrupt/rdf/wrapping/processor/Validator.java | 12 ++++++++++++ .../inrupt/rdf/wrapping/processor/ValidatorTest.java | 3 +++ .../bad/dataset default graph method is void.java | 12 ++++++++++++ .../bad/dataset named graph method is void.java | 11 +++++++++++ 6 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/bad/dataset default graph method is void.java create mode 100644 processor/src/test/resources/validationExamples/bad/dataset named graph method is void.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java index 1481668c6..a0cc992d4 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java @@ -42,6 +42,9 @@ protected void validateInternal() { requireNonMemberMethods(DefaultGraph.class, NamedGraph.class); + requireNonVoidReturnType(DefaultGraph.class); + requireNonVoidReturnType(NamedGraph.class); + requireAnnotatedReturnType(DefaultGraph.class, Graph.class); requireAnnotatedReturnType(NamedGraph.class, Graph.class); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 4bef6397d..c6176ac0a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -45,21 +45,11 @@ protected void validateInternal() { requireNonMemberMethods(Property.class); - requireNonVoidReturnType(); + requireNonVoidReturnType(Property.class); requireCompatiblePrimitiveReturnType(); requireCompatibleComplexReturnType(); } - private void requireNonVoidReturnType() { - myInterface.membersAnnotatedWith(Property.class) - .filter(method -> method.getReturnType().getKind() == VOID) - .forEach(method -> - errors.add(new ValidationError( - method, - "Property method [%s] must not be void", - method.getSimpleName()))); - } - private void requireCompatiblePrimitiveReturnType() { myInterface.primitiveMappingPropertyMethods() .filter(method -> method.getReturnType().getKind() != VOID) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index fd7d31ebd..9041a6ad6 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -21,6 +21,7 @@ package com.inrupt.rdf.wrapping.processor; import static javax.lang.model.element.Modifier.STATIC; +import static javax.lang.model.type.TypeKind.VOID; import java.lang.annotation.Annotation; import java.util.ArrayList; @@ -134,6 +135,7 @@ protected void requireAnnotatedReturnType( myInterface.getEnv().type(method.getReturnType()).getAnnotation(required) == null; myInterface.getEnv().methodsOf(myInterface.getType()) + .filter(method -> method.getReturnType().getKind() != VOID) .filter(isAnnotated) .filter(isNotResource) .forEach(method -> errors.add(new ValidationError( @@ -144,4 +146,14 @@ protected void requireAnnotatedReturnType( annotation.getSimpleName(), required.getSimpleName()))); } + + protected void requireNonVoidReturnType(final Class annotation) { + myInterface.membersAnnotatedWith(annotation) + .filter(method -> method.getReturnType().getKind() == VOID) + .forEach(method -> + errors.add(new ValidationError( + method, + "Method [%s] must not be void", + method.getSimpleName()))); + } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 7b124284d..0b50ea45b 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -44,6 +44,7 @@ class ValidatorTest { private static final String MUST_BE_STATIC_OR_DEFAULT = "must be static or default"; private static final String MUST_RETURN_RESOURCE_INTERFACE = "must return @Resource interface"; private static final String MUST_RETURN_GRAPH_INTERFACE = "must return @Graph interface"; + private static final String MUST_NOT_BE_VOID = "must not be void"; private Compiler compiler; @@ -67,11 +68,13 @@ private static Stream compilationErrorOnInvalid() { arguments("dataset is not an interface", MUST_BE_AN_INTERFACE), arguments("dataset extends unacceptable", "can only extend org.apache.jena.query.Dataset"), arguments("dataset default graph method is static", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("dataset default graph method is void", MUST_NOT_BE_VOID), arguments("dataset default graph method is default", CANNOT_BE_STATIC_OR_DEFAULT), arguments("dataset default graph method is not graph", MUST_RETURN_GRAPH_INTERFACE), arguments("dataset named graph method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("dataset named graph method is default", CANNOT_BE_STATIC_OR_DEFAULT), arguments("dataset named graph method is not graph", MUST_RETURN_GRAPH_INTERFACE), + arguments("dataset named graph method is void", MUST_NOT_BE_VOID), arguments("dataset instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), arguments("graph is not an interface", MUST_BE_AN_INTERFACE), diff --git a/processor/src/test/resources/validationExamples/bad/dataset default graph method is void.java b/processor/src/test/resources/validationExamples/bad/dataset default graph method is void.java new file mode 100644 index 000000000..9f6197a06 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset default graph method is void.java @@ -0,0 +1,12 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.DefaultGraph; +import com.inrupt.rdf.wrapping.annotation.NamedGraph; + +@Dataset +interface X { + @DefaultGraph + void x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/dataset named graph method is void.java b/processor/src/test/resources/validationExamples/bad/dataset named graph method is void.java new file mode 100644 index 000000000..15e1aeb93 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/dataset named graph method is void.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.NamedGraph; + +@Dataset +interface X { + @NamedGraph("x") + void x(); +} From 92f3d381c191cced9a87f636091cc2be1ab562b1 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 25 Feb 2024 20:04:34 +0000 Subject: [PATCH 097/141] Validate that graph resource methods are not void --- .../inrupt/rdf/wrapping/processor/GraphValidator.java | 4 ++++ .../inrupt/rdf/wrapping/processor/ValidatorTest.java | 3 +++ .../bad/graph instance of method is void.java | 11 +++++++++++ .../bad/graph object of method is void.java | 11 +++++++++++ .../bad/graph subject of method is void.java | 11 +++++++++++ 5 files changed, 40 insertions(+) create mode 100644 processor/src/test/resources/validationExamples/bad/graph instance of method is void.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph object of method is void.java create mode 100644 processor/src/test/resources/validationExamples/bad/graph subject of method is void.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java index 438634efb..34881236e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java @@ -47,6 +47,10 @@ protected void validateInternal() { OptionalFirstObjectOfEither.class, OptionalFirstSubjectOfEither.class); + requireNonVoidReturnType(OptionalFirstInstanceOfEither.class); + requireNonVoidReturnType(OptionalFirstObjectOfEither.class); + requireNonVoidReturnType(OptionalFirstSubjectOfEither.class); + requireAnnotatedReturnType(OptionalFirstInstanceOfEither.class, Resource.class); requireAnnotatedReturnType(OptionalFirstObjectOfEither.class, Resource.class); requireAnnotatedReturnType(OptionalFirstSubjectOfEither.class, Resource.class); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 0b50ea45b..6e58cb298 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -82,12 +82,15 @@ private static Stream compilationErrorOnInvalid() { arguments("graph instance of method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("graph instance of method is default", CANNOT_BE_STATIC_OR_DEFAULT), arguments("graph instance of method is not resource", MUST_RETURN_RESOURCE_INTERFACE), + arguments("graph instance of method is void", MUST_NOT_BE_VOID), arguments("graph object of method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("graph object of method is default", CANNOT_BE_STATIC_OR_DEFAULT), arguments("graph object of method is not resource", MUST_RETURN_RESOURCE_INTERFACE), + arguments("graph object of method is void", MUST_NOT_BE_VOID), arguments("graph subject of method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("graph subject of method is default", CANNOT_BE_STATIC_OR_DEFAULT), arguments("graph subject of method is not resource", MUST_RETURN_RESOURCE_INTERFACE), + arguments("graph subject of method is void", MUST_NOT_BE_VOID), arguments("graph instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), arguments("resource is not an interface", MUST_BE_AN_INTERFACE), diff --git a/processor/src/test/resources/validationExamples/bad/graph instance of method is void.java b/processor/src/test/resources/validationExamples/bad/graph instance of method is void.java new file mode 100644 index 000000000..487a51ae6 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph instance of method is void.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; + +@Graph +interface X { + @OptionalFirstInstanceOfEither("x") + void x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/graph object of method is void.java b/processor/src/test/resources/validationExamples/bad/graph object of method is void.java new file mode 100644 index 000000000..adb261d3f --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph object of method is void.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; + +@Graph +interface X { + @OptionalFirstObjectOfEither("x") + void x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/graph subject of method is void.java b/processor/src/test/resources/validationExamples/bad/graph subject of method is void.java new file mode 100644 index 000000000..5f9787035 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/graph subject of method is void.java @@ -0,0 +1,11 @@ +// This file is compiled only in test. +package x; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; + +@Graph +interface X { + @OptionalFirstSubjectOfEither("x") + void x(); +} From 0156da4372b006ea954c2618b9bd0611592c7ac2 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 25 Feb 2024 20:06:08 +0000 Subject: [PATCH 098/141] Reminder --- .../com/inrupt/rdf/wrapping/processor/ResourceValidator.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index c6176ac0a..e768e3edc 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -39,6 +39,10 @@ class ResourceValidator extends Validator { protected void validateInternal() { requireInterface(); + // TODO: Allow definitions to extend WrapperResource. That means interface must be extracted from + // WrapperResource so definition can extend it. Also allow definitions to extend other definitions + // (interfaces annotated with @Resource). That requires implementor to follow suit. Both above apply to + // dataset and graph definitions as well limitBaseInterfaces(org.apache.jena.rdf.model.Resource.class); requireMemberMethods(Property.class); From fb9fd3a1a25a5061f0e28d18826819ec95161c05 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 25 Feb 2024 20:28:18 +0000 Subject: [PATCH 099/141] Remove SPI reminder Upon some reading, I don't think that SPI is appropriate to find generated instances of definition interfaces. --- .../src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java index 0c59c7fc9..f5cb578f9 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java @@ -32,7 +32,6 @@ /** * A utility class that aids wrapper interfaces to find generated implementations. */ -// TODO: Should this be SPI? public final class Manager { private Manager() { } From a0381f57aebad9524dae739122fdb2395589c6c2 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 25 Feb 2024 20:52:00 +0000 Subject: [PATCH 100/141] Tidy --- .../inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java index 3272b27ac..f5197bdc6 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java @@ -154,7 +154,7 @@ interface ResourceDefinition { @Property(predicate = P, mapping = LITERAL_AS_INTEGER_OR_NULL) Integer getLiteralAsIntegerOrNull(); - @Property(predicate = P, mapping = Mapping.AS) + @Property(predicate = P, mapping = AS) ResourceDefinition getAs(); } From e13739ea1a36deeb76388ac05d267fceedc79910 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 25 Feb 2024 21:09:50 +0000 Subject: [PATCH 101/141] Introduce dynamic cardinality --- .../rdf/wrapping/annotation/Property.java | 16 ++++ .../wrapping/annotation/CardinalityTest.java | 77 +++++++++++++++++++ .../processor/ResourceImplementor.java | 7 +- .../processor/ResourceDefinitionTest.java | 18 +++-- .../wrapping/processor/TemporaryE2ETest.java | 9 ++- ...mplex property method is not resource.java | 3 +- ...ource complex property method is void.java | 3 +- .../resource property method is default.java | 3 +- .../resource property method is static.java | 3 +- .../bad/resource property method is void.java | 3 +- ...rty method return type not assignable.java | 3 +- ... property method is resource instance.java | 3 +- ...rce complex property method recursive.java | 3 +- ...roperty method is assignable instance.java | 3 +- 14 files changed, 130 insertions(+), 24 deletions(-) create mode 100644 annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java index 83efa79d6..141507406 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java @@ -33,6 +33,8 @@ public @interface Property { String predicate(); + Cardinality cardinality(); + Mapping mapping(); enum Mapping { @@ -54,4 +56,18 @@ public String getMethodName() { return methodName; } } + + enum Cardinality { + ANY_OR_NULL("anyOrNull"); + + private final String methodName; + + Cardinality(final String methodName) { + this.methodName = methodName; + } + + public String getMethodName() { + return methodName; + } + } } diff --git a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java new file mode 100644 index 000000000..55cfa4f74 --- /dev/null +++ b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java @@ -0,0 +1,77 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.annotation; + +import static java.lang.reflect.Modifier.isProtected; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.toList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.describedAs; +import static org.hamcrest.Matchers.in; + +import com.inrupt.rdf.wrapping.annotation.Property.Cardinality; +import com.inrupt.rdf.wrapping.jena.WrapperResource; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.stream.Stream; + +import org.hamcrest.Matcher; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.MethodSource; + +@DisplayName("Cardinality") +class CardinalityTest { + private static final Collection CARDINALITY_METHODS = cardinalityMethods().collect(toList()); + private static final Collection ENUM_CONSTANTS = stream(Cardinality.class.getEnumConstants()) + .map(Cardinality::getMethodName) + .collect(toList()); + + @DisplayName("has equivalent WrapperResource method for enum constant") + @ParameterizedTest(name = "{0}") + @EnumSource(Cardinality.class) + void constantHasEquivalentMethod(final Cardinality mapping) { + final Matcher hasCorrespondingMethod = describedAs("WrapperResource to have corresponding method", + in(CARDINALITY_METHODS)); + + assertThat("Cardinality enum constant without corresponding WrapperResource method", + mapping.getMethodName(), hasCorrespondingMethod); + } + + @DisplayName("has enum constant equivalent to WrapperResource method") + @ParameterizedTest(name = "{0}") + @MethodSource("cardinalityMethods") + void methodHasEquivalentConstant(final String method) { + final Matcher hasCorrespondingConstant = describedAs("Cardinality enum to have corresponding constant", + in(ENUM_CONSTANTS)); + + assertThat("WrapperResource method without corresponding Cardinality enum constant", + method, hasCorrespondingConstant); + } + + private static Stream cardinalityMethods() { + return stream(WrapperResource.class.getDeclaredMethods()) + .filter(method -> isProtected(method.getModifiers())) + .map(Method::getName); + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index d7fefbd57..06ea8a98b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -108,10 +108,11 @@ private void addResourcePropertyMethods() { } private void addPropertyMethod(final ExecutableElement method, final JExpr mapping) { - final String predicateFromAnnotation = method.getAnnotation(Property.class).predicate(); + final Property annotation = method.getAnnotation(Property.class); + final String predicateFromAnnotation = annotation.predicate(); + final String cardinality = annotation.cardinality().getMethodName(); final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); - // TODO: Dynamic cardniality - addMethod(method).body()._return(call("anyOrNull").arg(predicate).arg(mapping)); + addMethod(method).body()._return(call(cardinality).arg(predicate).arg(mapping)); } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java index f5197bdc6..858cbfd1d 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.*; import static java.lang.reflect.Modifier.isPublic; import static java.util.Arrays.stream; @@ -54,6 +55,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +@DisplayName("Resource definition") class ResourceDefinitionTest { private static final String P = "urn:example:p"; private static final String C = "urn:example:c"; @@ -121,7 +123,7 @@ private static Stream e2e() { ); } - @DisplayName("resource definition has equivalent of ValueMappings method") + @DisplayName("mock has equivalent of ValueMappings method") @ParameterizedTest(name = "{0}") @MethodSource void valueMappingsMethods(final String name) { @@ -136,25 +138,25 @@ private static Stream valueMappingsMethods() { @Resource interface ResourceDefinition { - @Property(predicate = P, mapping = LITERAL_AS_STRING) + @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_STRING) String getLiteralAsString(); - @Property(predicate = P, mapping = IRI_AS_URI) + @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = IRI_AS_URI) URI getIriAsUri(); - @Property(predicate = P, mapping = IRI_AS_STRING) + @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) String getIriAsString(); - @Property(predicate = P, mapping = LITERAL_AS_INSTANT) + @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_INSTANT) Instant getLiteralAsInstant(); - @Property(predicate = P, mapping = LITERAL_AS_BOOLEAN) + @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_BOOLEAN) Boolean getLiteralAsBoolean(); - @Property(predicate = P, mapping = LITERAL_AS_INTEGER_OR_NULL) + @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_INTEGER_OR_NULL) Integer getLiteralAsIntegerOrNull(); - @Property(predicate = P, mapping = AS) + @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = AS) ResourceDefinition getAs(); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java index 2c552d79e..c0318f4b2 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.*; import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -180,19 +181,19 @@ static GraphDefinition wrap(final Model original) { @Resource interface ResourceDefinition1 { - @Property(predicate = "urn:example:p", mapping = IRI_AS_STRING) + @Property(predicate = "urn:example:p", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) String getProperty1(); - @Property(predicate = "urn:example:p", mapping = IRI_AS_URI) + @Property(predicate = "urn:example:p", cardinality = ANY_OR_NULL, mapping = IRI_AS_URI) URI getProperty2(); - @Property(predicate = "urn:example:p", mapping = AS) + @Property(predicate = "urn:example:p", cardinality = ANY_OR_NULL, mapping = AS) ResourceDefinition2 getProperty3(); } @Resource interface ResourceDefinition2 { - @Property(predicate = "urn:example:p", mapping = AS) + @Property(predicate = "urn:example:p", cardinality = ANY_OR_NULL, mapping = AS) ResourceDefinition3 getProperty(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java b/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java index aa8f7cfe4..8caced0a9 100644 --- a/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java +++ b/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java @@ -1,6 +1,7 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; import com.inrupt.rdf.wrapping.annotation.Property; @@ -8,6 +9,6 @@ @Resource interface X { - @Property(predicate = "x", mapping = AS) + @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = AS) Object x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java b/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java index c11f12657..7178147bc 100644 --- a/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java +++ b/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java @@ -1,6 +1,7 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; import com.inrupt.rdf.wrapping.annotation.Property; @@ -8,6 +9,6 @@ @Resource interface X { - @Property(predicate = "x", mapping = AS) + @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = AS) void x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is default.java b/processor/src/test/resources/validationExamples/bad/resource property method is default.java index edade6193..19a763cf5 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is default.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is default.java @@ -1,6 +1,7 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; @@ -8,7 +9,7 @@ @Resource interface X { - @Property(predicate = "x", mapping = IRI_AS_STRING) + @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) default Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is static.java b/processor/src/test/resources/validationExamples/bad/resource property method is static.java index de6b44177..57fdd3c2a 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is static.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is static.java @@ -1,6 +1,7 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; @@ -8,7 +9,7 @@ @Resource interface X { - @Property(predicate = "x", mapping = IRI_AS_STRING) + @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) static Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is void.java b/processor/src/test/resources/validationExamples/bad/resource property method is void.java index 28fe77e2a..a12ea4f97 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is void.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is void.java @@ -1,6 +1,7 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; @@ -8,6 +9,6 @@ @Resource interface X { - @Property(predicate = "x", mapping = IRI_AS_STRING) + @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) void x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java b/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java index bf0f8774f..bcf319575 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java @@ -1,6 +1,7 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; @@ -8,6 +9,6 @@ @Resource interface X { - @Property(predicate = "x", mapping = IRI_AS_STRING) + @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) int x(); } diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java b/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java index 3c4f51331..f1f59e2f9 100644 --- a/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java +++ b/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java @@ -1,6 +1,7 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; import com.inrupt.rdf.wrapping.annotation.Property; @@ -8,6 +9,6 @@ @Resource interface X { - @Property(predicate = "x", mapping = AS) + @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = AS) X x(); } diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java index 91f621d63..57b2aeed0 100644 --- a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java +++ b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java @@ -1,6 +1,7 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; import com.inrupt.rdf.wrapping.annotation.Graph; @@ -15,7 +16,7 @@ interface X { @Resource interface Y { - @Property(predicate = "x", mapping = AS) + @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = AS) Y x(); } } diff --git a/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java b/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java index 8f0f40c09..b38045f84 100644 --- a/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java +++ b/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java @@ -1,6 +1,7 @@ // This file is compiled only in test. package x; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; @@ -8,6 +9,6 @@ @Resource interface X { - @Property(predicate = "x", mapping = IRI_AS_STRING) + @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) Object x(); } From 8499e2f2b18fadd1bb57ba92c876a341f77d12d0 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Tue, 27 Feb 2024 22:59:04 +0000 Subject: [PATCH 102/141] Extend and cover cardinality for singular accessors --- .../rdf/wrapping/annotation/Property.java | 5 +- .../ResourceDefinitionCardinalityTest.java | 194 ++++++++++++++++++ ...ava => ResourceDefinitionMappingTest.java} | 2 +- 3 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java rename processor/src/test/java/com/inrupt/rdf/wrapping/processor/{ResourceDefinitionTest.java => ResourceDefinitionMappingTest.java} (99%) diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java index 141507406..5d3a970e1 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java @@ -58,7 +58,10 @@ public String getMethodName() { } enum Cardinality { - ANY_OR_NULL("anyOrNull"); + ANY_OR_NULL("anyOrNull"), + ANY_OR_THROW("anyOrThrow"), + SINGLE_OR_NULL("singleOrNull"), + SINGLE_OR_THROW("singleOrThrow"); private final String methodName; diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java new file mode 100644 index 000000000..f61052e1d --- /dev/null +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java @@ -0,0 +1,194 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.*; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.LITERAL_AS_STRING; +import static java.beans.Introspector.getBeanInfo; +import static java.lang.reflect.Modifier.isProtected; +import static java.util.Arrays.stream; +import static java.util.UUID.randomUUID; +import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel; +import static org.apache.jena.vocabulary.RDF.type; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import com.inrupt.rdf.wrapping.annotation.Graph; +import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Property.Cardinality; +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.jena.WrapperResource; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.shared.PropertyNotFoundException; +import org.hamcrest.Matcher; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +@DisplayName("Resource definition") +class ResourceDefinitionCardinalityTest { + private static final String P = "urn:example:p"; + private static final String C = "urn:example:c"; + private static final Object[] RESOURCE_DEFINITION_METHODS = stream(ResourceDefinition.class.getDeclaredMethods()) + .map(m -> m.getAnnotation(Property.class)) + .map(Property::cardinality) + .map(Cardinality::getMethodName) + .distinct() + .toArray(); + private static final int NONE = 0; + private static final int SINGLE = 1; + private static final int MANY = 2; + public static final String DOES_NOT_THROW = "does not throw"; + public static final String THROWS = "throws"; + + private Model m; + private GraphDefinition wrapped; + + @BeforeEach + void setUp() { + m = createDefaultModel(); + wrapped = GraphDefinition.wrap(m); + } + + @DisplayName("properly converts node with cardinality") + @ParameterizedTest(name = "{2} for cardinality {0} with {1} items") + @MethodSource + void e2e(final Cardinality cardinality, final int number, final String throwing) throws IntrospectionException { + final List values = new ArrayList<>(); + final Class expectedException; + final Matcher asExpected; + // anchor for graph definition + final org.apache.jena.rdf.model.Resource s = m.createResource().addProperty(type, m.createResource(C)); + final ResourceDefinition resource = wrapped.getResource(); + + switch (number) { + case NONE: + asExpected = nullValue(); + expectedException = PropertyNotFoundException.class; + break; + case SINGLE: + asExpected = in(values); + expectedException = null; + break; + default: + case MANY: + asExpected = in(values); + expectedException = IllegalStateException.class; + break; + } + + // Add and remember as many objects as needed + for (int i = 0; i < number; i++) { + final String value = randomUUID().toString(); + values.add(value); + s.addProperty(m.createProperty(P), m.createTypedLiteral(value)); + } + + switch (throwing) { + case THROWS: + final Method getter = findProperty(resource, cardinality); + assertThat( + assertThrows(InvocationTargetException.class, () -> getter.invoke(resource)), + hasProperty("cause", is(instanceOf(expectedException)))); + break; + default: + case DOES_NOT_THROW: + assertThat(resource, hasProperty(cardinality.getMethodName(), is(asExpected))); + } + } + + private static Method findProperty(final ResourceDefinition r, final Cardinality c) throws IntrospectionException { + return stream(getBeanInfo(r.getClass(), Object.class).getPropertyDescriptors()) + .filter(p -> p.getName().equals(c.getMethodName())) + .map(PropertyDescriptor::getReadMethod) + .findAny() + .orElseThrow(RuntimeException::new); + } + + private static Stream e2e() { + return Stream.of( + arguments(ANY_OR_NULL, NONE, DOES_NOT_THROW), + arguments(ANY_OR_NULL, SINGLE, DOES_NOT_THROW), + arguments(ANY_OR_NULL, MANY, DOES_NOT_THROW), + arguments(ANY_OR_THROW, NONE, THROWS), + arguments(ANY_OR_THROW, SINGLE, DOES_NOT_THROW), + arguments(ANY_OR_THROW, MANY, DOES_NOT_THROW), + arguments(SINGLE_OR_NULL, NONE, DOES_NOT_THROW), + arguments(SINGLE_OR_NULL, SINGLE, DOES_NOT_THROW), + arguments(SINGLE_OR_NULL, MANY, THROWS), + arguments(SINGLE_OR_THROW, NONE, THROWS), + arguments(SINGLE_OR_THROW, SINGLE, DOES_NOT_THROW), + arguments(SINGLE_OR_THROW, MANY, THROWS) + ); + } + + @DisplayName("mock has equivalent of ValueMappings method") + @ParameterizedTest(name = "{0}") + @MethodSource + void wrapperResourceMethods(final String name) { + assertThat(RESOURCE_DEFINITION_METHODS, hasItemInArray(name)); + } + + private static Stream wrapperResourceMethods() { + return stream(WrapperResource.class.getDeclaredMethods()) + .filter(m -> isProtected(m.getModifiers())) + .map(Method::getName); + } + + @Resource + interface ResourceDefinition { + @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_STRING) + String getAnyOrNull(); + + @Property(predicate = P, cardinality = ANY_OR_THROW, mapping = LITERAL_AS_STRING) + String getAnyOrThrow(); + + @Property(predicate = P, cardinality = SINGLE_OR_NULL, mapping = LITERAL_AS_STRING) + String getSingleOrNull(); + + @Property(predicate = P, cardinality = SINGLE_OR_THROW, mapping = LITERAL_AS_STRING) + String getSingleOrThrow(); + } + + @Graph + interface GraphDefinition { + static GraphDefinition wrap(final Model original) { + return Manager.wrap(original, GraphDefinition.class); + } + + @OptionalFirstInstanceOfEither(C) + ResourceDefinition getResource(); + } +} diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionMappingTest.java similarity index 99% rename from processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java rename to processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionMappingTest.java index 858cbfd1d..8fd6a01aa 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionMappingTest.java @@ -56,7 +56,7 @@ import org.junit.jupiter.params.provider.MethodSource; @DisplayName("Resource definition") -class ResourceDefinitionTest { +class ResourceDefinitionMappingTest { private static final String P = "urn:example:p"; private static final String C = "urn:example:c"; private static final Object[] RESOURCE_DEFINITION_METHODS = stream(ResourceDefinition.class.getDeclaredMethods()) From 9c5b51047f671d4c2814bd4ad9fd3a2bf80a395c Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Tue, 27 Feb 2024 23:25:21 +0000 Subject: [PATCH 103/141] Temporarily disable premature tests --- .../com/inrupt/rdf/wrapping/annotation/CardinalityTest.java | 2 ++ .../wrapping/processor/ResourceDefinitionCardinalityTest.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java index 55cfa4f74..a51ad7ea2 100644 --- a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java +++ b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java @@ -35,6 +35,7 @@ import java.util.stream.Stream; import org.hamcrest.Matcher; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -58,6 +59,7 @@ void constantHasEquivalentMethod(final Cardinality mapping) { mapping.getMethodName(), hasCorrespondingMethod); } + @Disabled("Not ready yet") // TODO: Enable @DisplayName("has enum constant equivalent to WrapperResource method") @ParameterizedTest(name = "{0}") @MethodSource("cardinalityMethods") diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java index f61052e1d..f60c920d2 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java @@ -52,6 +52,7 @@ import org.apache.jena.shared.PropertyNotFoundException; import org.hamcrest.Matcher; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -154,6 +155,7 @@ private static Stream e2e() { ); } + @Disabled("Not ready yet") // TODO: Enable @DisplayName("mock has equivalent of ValueMappings method") @ParameterizedTest(name = "{0}") @MethodSource From 9fde8acbb24476b52787913b8696edb95d20887e Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 2 Mar 2024 11:46:50 +0000 Subject: [PATCH 104/141] Rename 'interface' to 'definition' --- ...tInterface.java => DatasetDefinition.java} | 4 +- .../processor/DatasetImplementor.java | 10 ++-- .../wrapping/processor/DatasetValidator.java | 4 +- .../{Interface.java => Definition.java} | 12 ++--- ...aphInterface.java => GraphDefinition.java} | 8 +-- .../wrapping/processor/GraphImplementor.java | 14 ++--- .../wrapping/processor/GraphValidator.java | 4 +- .../rdf/wrapping/processor/Implementor.java | 32 +++++------ .../rdf/wrapping/processor/Processor.java | 4 +- ...Interface.java => ResourceDefinition.java} | 8 +-- .../processor/ResourceImplementor.java | 8 +-- .../wrapping/processor/ResourceValidator.java | 16 +++--- .../rdf/wrapping/processor/Validator.java | 54 +++++++++---------- .../wrapping/processor/ImplementorTest.java | 8 +-- 14 files changed, 93 insertions(+), 93 deletions(-) rename processor/src/main/java/com/inrupt/rdf/wrapping/processor/{DatasetInterface.java => DatasetDefinition.java} (93%) rename processor/src/main/java/com/inrupt/rdf/wrapping/processor/{Interface.java => Definition.java} (88%) rename processor/src/main/java/com/inrupt/rdf/wrapping/processor/{GraphInterface.java => GraphDefinition.java} (90%) rename processor/src/main/java/com/inrupt/rdf/wrapping/processor/{ResourceInterface.java => ResourceDefinition.java} (93%) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java similarity index 93% rename from processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java index e1a6b0b87..6d1c08ba1 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java @@ -28,8 +28,8 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; -class DatasetInterface extends Interface { - DatasetInterface(final TypeElement type, final Environment env) { +class DatasetDefinition extends Definition { + DatasetDefinition(final TypeElement type, final Environment env) { super(type, env); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index c7de2ca9a..c20d73611 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -36,8 +36,8 @@ import org.jboss.jdeparser.JMethodDef; import org.jboss.jdeparser.JType; -class DatasetImplementor extends Implementor { - DatasetImplementor(final DatasetInterface definition) { +class DatasetImplementor extends Implementor { + DatasetImplementor(final DatasetDefinition definition) { super(definition); } @@ -70,17 +70,17 @@ private void addConstructor() { } private void addWrap() { - final JMethodDef myWrap = target.method(PUBLIC | STATIC, myInterface.getOriginalInterface(), WRAP); + final JMethodDef myWrap = target.method(PUBLIC | STATIC, definition.getOriginalInterface(), WRAP); myWrap.param(FINAL, Dataset.class, ORIGINAL); myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("asDatasetGraph"))); } private void addDefaultGraphs() { - myInterface.defaultGraphMethods().forEach(method -> addGraph(method, call("getDefaultModel"))); + definition.defaultGraphMethods().forEach(method -> addGraph(method, call("getDefaultModel"))); } private void addNamedGraphs() { - myInterface.namedGraphMethods().forEach(method -> { + definition.namedGraphMethods().forEach(method -> { final String graph = method.getAnnotation(NamedGraph.class).value(); addGraph(method, call("getNamedModel").arg(str(graph))); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java index a0cc992d4..faec10599 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java @@ -26,8 +26,8 @@ import org.apache.jena.query.Dataset; -class DatasetValidator extends Validator { - DatasetValidator(final DatasetInterface definition) { +class DatasetValidator extends Validator { + DatasetValidator(final DatasetDefinition definition) { super(definition); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java similarity index 88% rename from processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java index a5370b7b3..23a3184ff 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Interface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java @@ -34,25 +34,25 @@ import org.jboss.jdeparser.JType; -class Interface { +class Definition { private final TypeElement type; private final Environment env; - Interface(final TypeElement type, final Environment env) { + Definition(final TypeElement type, final Environment env) { this.env = env; this.type = type; } - static Interface definition(final TypeElement type, final Environment env) { + static Definition definition(final TypeElement type, final Environment env) { if (type.getAnnotation(Dataset.class) != null) { - return new DatasetInterface(type, env); + return new DatasetDefinition(type, env); } else if (type.getAnnotation(Graph.class) != null) { - return new GraphInterface(type, env); + return new GraphDefinition(type, env); } else { // Resource // Processor's supported annotations are finite - return new ResourceInterface(type, env); + return new ResourceDefinition(type, env); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java similarity index 90% rename from processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java index c263fbb94..3d803a159 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java @@ -32,8 +32,8 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -class GraphInterface extends Interface { - GraphInterface(final TypeElement type, final Environment env) { +class GraphDefinition extends Definition { + GraphDefinition(final TypeElement type, final Environment env) { super(type, env); } @@ -41,8 +41,8 @@ Stream transitiveResourceTypes() { final Stream children = resourceMethodTypes(); final Stream descendants = resourceMethodTypes() .map(getEnv()::type) - .map(type -> new ResourceInterface(type, getEnv())) - .flatMap(ResourceInterface::transitiveResourceTypes); + .map(type -> new ResourceDefinition(type, getEnv())) + .flatMap(ResourceDefinition::transitiveResourceTypes); return concat(children, descendants) .distinct(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 7073bf205..668723a12 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -42,8 +42,8 @@ import org.jboss.jdeparser.JMethodDef; import org.jboss.jdeparser.JType; -class GraphImplementor extends Implementor { - GraphImplementor(final GraphInterface definition) { +class GraphImplementor extends Implementor { + GraphImplementor(final GraphDefinition definition) { super(definition); } @@ -55,17 +55,17 @@ protected void implementInternal() { addToPersonality(constructor); addWrap(); - myInterface.instanceMethods().forEach(method -> addResourceMethod( + definition.instanceMethods().forEach(method -> addResourceMethod( method, "optionalFirstInstanceOfEither", method.getAnnotation(OptionalFirstInstanceOfEither.class).value())); - myInterface.subjectMethods().forEach(method -> addResourceMethod( + definition.subjectMethods().forEach(method -> addResourceMethod( method, "optionalFirstSubjectOfEither", method.getAnnotation(OptionalFirstSubjectOfEither.class).value())); - myInterface.objectMethods().forEach(method -> addResourceMethod( + definition.objectMethods().forEach(method -> addResourceMethod( method, "optionalFirstObjectOfEither", method.getAnnotation(OptionalFirstObjectOfEither.class).value())); @@ -93,13 +93,13 @@ private JMethodDef addConstructor() { } private void addWrap() { - final JMethodDef myWrap = target.method(PUBLIC | STATIC, myInterface.getOriginalInterface(), WRAP); + final JMethodDef myWrap = target.method(PUBLIC | STATIC, definition.getOriginalInterface(), WRAP); myWrap.param(FINAL, Model.class, ORIGINAL); myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("getGraph"))); } private void addToPersonality(final JMethodDef constructor) { - myInterface.transitiveResourceTypes().forEach(type -> { + definition.transitiveResourceTypes().forEach(type -> { final JType implementation = asImplementation(type); constructor diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java index 34881236e..3d9678503 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java @@ -27,8 +27,8 @@ import org.apache.jena.rdf.model.Model; -class GraphValidator extends Validator { - GraphValidator(final GraphInterface definition) { +class GraphValidator extends Validator { + GraphValidator(final GraphDefinition definition) { super(definition); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 93c3a7771..77b5066d9 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -34,20 +34,20 @@ import org.jboss.jdeparser.*; -abstract class Implementor { +abstract class Implementor { protected static final String ORIGINAL = "original"; static final String WRAP = "wrap"; protected final JSources sources; protected final JSourceFile sourceFile; - protected final T myInterface; + protected final T definition; protected JClassDef target; - protected Implementor(final T myInterface) { - this.myInterface = myInterface; + protected Implementor(final T definition) { + this.definition = definition; - final TypeElement type = myInterface.getType(); - final Environment env = myInterface.getEnv(); + final TypeElement type = definition.getType(); + final Environment env = definition.getEnv(); final String packageName = env.getElementUtils().getPackageOf(type).getQualifiedName().toString(); @@ -58,7 +58,7 @@ protected Implementor(final T myInterface) { private String getImplementationClass() { final String originalBinaryName = - myInterface.getEnv().getElementUtils().getBinaryName(myInterface.getType()).toString(); + definition.getEnv().getElementUtils().getBinaryName(definition.getType()).toString(); final String qualifiedName = asImplementation(originalBinaryName); final int lastDot = originalBinaryName.lastIndexOf('.'); return qualifiedName.substring(lastDot + 1); @@ -76,23 +76,23 @@ void implement() { protected abstract void implementInternal(); - static Implementor implementor(final Interface definition) { - if (definition instanceof DatasetInterface) { - return new DatasetImplementor((DatasetInterface) definition); + static Implementor implementor(final Definition definition) { + if (definition instanceof DatasetDefinition) { + return new DatasetImplementor((DatasetDefinition) definition); - } else if (definition instanceof GraphInterface) { - return new GraphImplementor((GraphInterface) definition); + } else if (definition instanceof GraphDefinition) { + return new GraphImplementor((GraphDefinition) definition); } else { // Resource // Processor's supported annotations are finite - return new ResourceImplementor((ResourceInterface) definition); + return new ResourceImplementor((ResourceDefinition) definition); } } protected void addClass(final Class clazz) { target = sourceFile._class(PUBLIC, getImplementationClass()); target._extends(clazz); - target._implements(myInterface.getOriginalInterface()); + target._implements(definition.getOriginalInterface()); target.docComment().text("Warning, this class consists of generated code."); target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); @@ -109,8 +109,8 @@ protected JMethodDef addMethod(final ExecutableElement method) { } protected JType asImplementation(final TypeMirror original) { - final TypeElement returnType = myInterface.getEnv().type(original); - final String originalBinaryName = myInterface.getEnv() + final TypeElement returnType = definition.getEnv().type(original); + final String originalBinaryName = definition.getEnv() .getElementUtils() .getBinaryName(returnType) .toString(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java index 6aa5613eb..73872dbeb 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java @@ -21,7 +21,7 @@ package com.inrupt.rdf.wrapping.processor; import static com.inrupt.rdf.wrapping.processor.Implementor.implementor; -import static com.inrupt.rdf.wrapping.processor.Interface.definition; +import static com.inrupt.rdf.wrapping.processor.Definition.definition; import static com.inrupt.rdf.wrapping.processor.Validator.validator; import static java.util.stream.Collectors.toSet; import static javax.lang.model.SourceVersion.RELEASE_8; @@ -65,7 +65,7 @@ public boolean process(final Set annotations, final Round // All our annotations are @Target(TYPE), so they're all TypeElements final TypeElement type = (TypeElement) element; - final Interface definition = definition(type, env); + final Definition definition = definition(type, env); implementors.add(implementor(definition)); validationErrors.addAll(validator(definition).validate()); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java similarity index 93% rename from processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index dfff929b7..e338c72a0 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceInterface.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -34,8 +34,8 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -class ResourceInterface extends Interface { - ResourceInterface(final TypeElement type, final Environment env) { +class ResourceDefinition extends Definition { + ResourceDefinition(final TypeElement type, final Environment env) { super(type, env); } @@ -59,7 +59,7 @@ Stream transitiveResourceTypes() { final Queue outstanding = new LinkedList<>(); final Set results = new HashSet<>(); - ResourceInterface current = this; + ResourceDefinition current = this; while (true) { current.resourcePropertyMethods() .map(ExecutableElement::getReturnType) @@ -73,7 +73,7 @@ Stream transitiveResourceTypes() { final TypeMirror next = outstanding.remove(); final TypeElement nextType = getEnv().type(next); - current = new ResourceInterface(nextType, getEnv()); + current = new ResourceDefinition(nextType, getEnv()); } return results.stream(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 06ea8a98b..4d4c34a5e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -39,10 +39,10 @@ import org.jboss.jdeparser.JMethodDef; import org.jboss.jdeparser.JType; -class ResourceImplementor extends Implementor { +class ResourceImplementor extends Implementor { static final String FACTORY = "factory"; - ResourceImplementor(final ResourceInterface definition) { + ResourceImplementor(final ResourceDefinition definition) { super(definition); } @@ -90,7 +90,7 @@ private void addConstructor() { } private void addPrimitivePropertyMethods() { - myInterface.primitivePropertyMethods().forEach(method -> { + definition.primitivePropertyMethods().forEach(method -> { final String mappingMethodName = method.getAnnotation(Property.class).mapping().getMethodName(); final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); @@ -99,7 +99,7 @@ private void addPrimitivePropertyMethods() { } private void addResourcePropertyMethods() { - myInterface.resourcePropertyMethods().forEach(method -> { + definition.resourcePropertyMethods().forEach(method -> { final JType implementation = asImplementation(method.getReturnType()); final JCall mapping = $t(ValueMappings.class).call("as").arg(implementation._class()); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index e768e3edc..8beea9246 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -30,8 +30,8 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -class ResourceValidator extends Validator { - ResourceValidator(final ResourceInterface definition) { +class ResourceValidator extends Validator { + ResourceValidator(final ResourceDefinition definition) { super(definition); } @@ -55,13 +55,13 @@ protected void validateInternal() { } private void requireCompatiblePrimitiveReturnType() { - myInterface.primitiveMappingPropertyMethods() + definition.primitiveMappingPropertyMethods() .filter(method -> method.getReturnType().getKind() != VOID) .forEach(method -> { final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); - if (!myInterface.getEnv().getTypeUtils().isAssignable( + if (!definition.getEnv().getTypeUtils().isAssignable( mappingMethodReturnType, method.getReturnType())) { errors.add(new ValidationError( @@ -76,22 +76,22 @@ private void requireCompatiblePrimitiveReturnType() { } private void requireCompatibleComplexReturnType() { - myInterface.complexMappingPropertyMethods() + definition.complexMappingPropertyMethods() .filter(method -> method.getReturnType().getKind() != VOID) .forEach(method -> { - final TypeElement returnType = myInterface.getEnv().type(method.getReturnType()); + final TypeElement returnType = definition.getEnv().type(method.getReturnType()); if (returnType == null || returnType.getAnnotation(Resource.class) == null) { errors.add(new ValidationError( method, "Method %s on interface %s must return @Resource interface", method.getSimpleName(), - myInterface.getType().getSimpleName())); + definition.getType().getSimpleName())); } }); } private TypeMirror returnTypeOfMapper(final String mappingMethod) { - return myInterface.getEnv().methodsOf(ValueMappings.class) + return definition.getEnv().methodsOf(ValueMappings.class) .filter(method -> method.getSimpleName().contentEquals(mappingMethod)) .map(ExecutableElement::getReturnType) .findFirst() diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 9041a6ad6..434e6ac3b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -32,24 +32,24 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.type.TypeMirror; -abstract class Validator { - protected final T myInterface; +abstract class Validator { + protected final T definition; protected final Collection errors = new ArrayList<>(); - protected Validator(final T myInterface) { - this.myInterface = myInterface; + protected Validator(final T definition) { + this.definition = definition; } - static Validator validator(final Interface definition) { - if (definition instanceof DatasetInterface) { - return new DatasetValidator((DatasetInterface) definition); + static Validator validator(final Definition definition) { + if (definition instanceof DatasetDefinition) { + return new DatasetValidator((DatasetDefinition) definition); - } else if (definition instanceof GraphInterface) { - return new GraphValidator((GraphInterface) definition); + } else if (definition instanceof GraphDefinition) { + return new GraphValidator((GraphDefinition) definition); } else { // Resource // Processor's supported annotations are finite - return new ResourceValidator((ResourceInterface) definition); + return new ResourceValidator((ResourceDefinition) definition); } } @@ -67,14 +67,14 @@ protected void requireMemberMethods(final Class annotation final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; - myInterface.getEnv().methodsOf(myInterface.getType()) + definition.getEnv().methodsOf(definition.getType()) .filter(isNotMember) .filter(isAnnotated) .forEach(method -> errors.add(new ValidationError( method, "Method %s on interface %s annotated with @%s cannot be static or default", method.getSimpleName(), - myInterface.getType().getSimpleName(), + definition.getType().getSimpleName(), annotation.getSimpleName()))); } @@ -86,44 +86,44 @@ protected final void requireNonMemberMethods(final Class.. final Predicate isUnannotated = method -> Arrays.stream(annotations).noneMatch(a -> method.getAnnotation(a) != null); - myInterface.getEnv().methodsOf(myInterface.getType()) + definition.getEnv().methodsOf(definition.getType()) .filter(isMember) .filter(isUnannotated) .forEach(method -> errors.add(new ValidationError( method, "Unannotated method %s on interface %s must be static or default", method.getSimpleName(), - myInterface.getType().getSimpleName()))); + definition.getType().getSimpleName()))); } protected void limitBaseInterfaces(final Class allowed) { - if (!myInterface.getType().getKind().isInterface()) { + if (!definition.getType().getKind().isInterface()) { return; } - for (final TypeMirror implemented : myInterface.getType().getInterfaces()) { - if (myInterface.getEnv().isSameType(implemented, allowed)) { + for (final TypeMirror implemented : definition.getType().getInterfaces()) { + if (definition.getEnv().isSameType(implemented, allowed)) { continue; } errors.add(new ValidationError( - myInterface.getType(), + definition.getType(), "Interface %s can only extend %s or nothing", - myInterface.getType().getSimpleName(), + definition.getType().getSimpleName(), allowed.getName())); } } protected void requireInterface() { - if (myInterface.getType().getKind().isInterface()) { + if (definition.getType().getKind().isInterface()) { return; } errors.add(new ValidationError( - myInterface.getType(), + definition.getType(), "Element %s must be an interface but was a %s", - myInterface.getType().getSimpleName(), - myInterface.getType().getKind())); + definition.getType().getSimpleName(), + definition.getType().getKind())); } protected void requireAnnotatedReturnType( @@ -132,9 +132,9 @@ protected void requireAnnotatedReturnType( final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; final Predicate isNotResource = method -> - myInterface.getEnv().type(method.getReturnType()).getAnnotation(required) == null; + definition.getEnv().type(method.getReturnType()).getAnnotation(required) == null; - myInterface.getEnv().methodsOf(myInterface.getType()) + definition.getEnv().methodsOf(definition.getType()) .filter(method -> method.getReturnType().getKind() != VOID) .filter(isAnnotated) .filter(isNotResource) @@ -142,13 +142,13 @@ protected void requireAnnotatedReturnType( method, "Method %s on interface %s annotated with @%s must return @%s interface", method.getSimpleName(), - myInterface.getType().getSimpleName(), + definition.getType().getSimpleName(), annotation.getSimpleName(), required.getSimpleName()))); } protected void requireNonVoidReturnType(final Class annotation) { - myInterface.membersAnnotatedWith(annotation) + definition.membersAnnotatedWith(annotation) .filter(method -> method.getReturnType().getKind() == VOID) .forEach(method -> errors.add(new ValidationError( diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java index 26dd175a5..c4035e5b0 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java @@ -45,14 +45,14 @@ class ImplementorTest { @DisplayName("fails to implement when filer can't write") void failsToWrite() throws IOException { final TypeElement type = mock(TypeElement.class); - final Interface myInterface = mock(Interface.class); + final Definition definition = mock(Definition.class); final Environment env = mock(Environment.class); final Elements elementUtils = mock(Elements.class); final Name name = mock(Name.class); final PackageElement packageElement = mock(PackageElement.class); final Filer filer = mock(Filer.class); - when(myInterface.getType()).thenReturn(type); - when(myInterface.getEnv()).thenReturn(env); + when(definition.getType()).thenReturn(type); + when(definition.getEnv()).thenReturn(env); when(elementUtils.getBinaryName(any())).thenReturn(name); when(packageElement.getQualifiedName()).thenReturn(name); @@ -61,7 +61,7 @@ void failsToWrite() throws IOException { when(env.getElementUtils()).thenReturn(elementUtils); when(env.getFiler()).thenReturn(filer); - final Implementor mock = new Implementor(myInterface) { + final Implementor mock = new Implementor(definition) { @Override protected void implementInternal() { } From e9365eed9161935c5c2a0fc7e58670dd7ff42b80 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 2 Mar 2024 12:11:57 +0000 Subject: [PATCH 105/141] Use predicates instead of selectors Because Jena deprecated --- .../rdf/wrapping/jena/WrapperModel.java | 60 ++++--------------- 1 file changed, 12 insertions(+), 48 deletions(-) diff --git a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java index 7ccfdd2e4..7bab96cd5 100644 --- a/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java +++ b/jena/src/main/java/com/inrupt/rdf/wrapping/jena/WrapperModel.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.List; +import java.util.function.Predicate; import java.util.stream.Collectors; import org.apache.jena.graph.Graph; @@ -35,7 +36,8 @@ protected WrapperModel(final Graph base) { } protected T optionalFirstInstanceOfEither(final Class view, final String... classes) { - return listStatements(new InstanceOfEitherSelector(classes)) + return listStatements() + .filterKeep(new InstanceOfEither(classes)) .mapWith(Statement::getSubject) .mapWith(subject -> subject.as(view)) .nextOptional() @@ -43,7 +45,8 @@ protected T optionalFirstInstanceOfEither(final Class vie } protected T optionalFirstSubjectOfEither(final Class view, final String... predicates) { - return listStatements(new EitherPredicateSelector(predicates)) + return listStatements() + .filterKeep(new EitherPredicate(predicates)) .mapWith(Statement::getSubject) .mapWith(subject -> subject.as(view)) .nextOptional() @@ -51,17 +54,18 @@ protected T optionalFirstSubjectOfEither(final Class view } protected T optionalFirstObjectOfEither(final Class view, final String... predicates) { - return listStatements(new EitherPredicateSelector(predicates)) + return listStatements() + .filterKeep(new EitherPredicate(predicates)) .mapWith(Statement::getObject) .mapWith(object -> object.as(view)) .nextOptional() .orElse(null); } - private static final class InstanceOfEitherSelector implements Selector { + private static final class InstanceOfEither implements Predicate { private final List classes; - private InstanceOfEitherSelector(final String[] classes) { + private InstanceOfEither(final String[] classes) { this.classes = Arrays .stream(classes) .map(ResourceFactory::createResource) @@ -74,38 +78,18 @@ public boolean test(final Statement statement) { return false; } - if (!getPredicate().equals(statement.getPredicate())) { + if (!RDF.type.equals(statement.getPredicate())) { return false; } return classes.contains(statement.getObject().asResource()); } - - @Override - public Property getPredicate() { - return RDF.type; - } - - @Override - public boolean isSimple() { - return false; - } - - @Override - public Resource getSubject() { - return null; - } - - @Override - public RDFNode getObject() { - return null; - } } - private static final class EitherPredicateSelector implements Selector { + private static final class EitherPredicate implements Predicate { private final List predicates; - private EitherPredicateSelector(final String[] predicates) { + private EitherPredicate(final String[] predicates) { this.predicates = Arrays .stream(predicates) .map(ResourceFactory::createProperty) @@ -116,25 +100,5 @@ private EitherPredicateSelector(final String[] predicates) { public boolean test(final Statement statement) { return predicates.contains(statement.getPredicate()); } - - @Override - public boolean isSimple() { - return false; - } - - @Override - public Resource getSubject() { - return null; - } - - @Override - public Property getPredicate() { - return null; - } - - @Override - public RDFNode getObject() { - return null; - } } } From 1d7831b4ee0c66f2f5f30f3fc98e13dc1c21e365 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 2 Mar 2024 13:16:02 +0000 Subject: [PATCH 106/141] Fix and suppress PMD warnings --- .../rdf/wrapping/processor/GraphImplementor.java | 1 + .../com/inrupt/rdf/wrapping/processor/Manager.java | 3 +-- .../com/inrupt/rdf/wrapping/processor/Processor.java | 2 +- .../rdf/wrapping/processor/ResourceDefinition.java | 12 ++++++++---- .../rdf/wrapping/processor/ImplementorTest.java | 1 + 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 668723a12..9aee56e96 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -110,6 +110,7 @@ private void addToPersonality(final JMethodDef constructor) { }); } + @SuppressWarnings("PMD.UseVarargs") // irrelevant in this utility method private void addResourceMethod(final ExecutableElement method, final String convenience, final String[] values) { final JType implementation = asImplementation(method.getReturnType()); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java index f5cb578f9..bcce0e5b7 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java @@ -55,10 +55,9 @@ private static T wrap(final Object original, final Class definition, fina private static Class findImplementation(final Class definition) { final String implementation = asImplementation(definition.getName()); - final ClassLoader loader = definition.getClassLoader(); try { - return Class.forName(implementation, true, loader); + return Class.forName(implementation); } catch (ClassNotFoundException e) { throw new RuntimeException("implementation not found", e); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java index 73872dbeb..ab7b6c688 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java @@ -20,8 +20,8 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.processor.Implementor.implementor; import static com.inrupt.rdf.wrapping.processor.Definition.definition; +import static com.inrupt.rdf.wrapping.processor.Implementor.implementor; import static com.inrupt.rdf.wrapping.processor.Validator.validator; import static java.util.stream.Collectors.toSet; import static javax.lang.model.SourceVersion.RELEASE_8; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index e338c72a0..302acd231 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -70,15 +70,19 @@ Stream transitiveResourceTypes() { break; } - final TypeMirror next = outstanding.remove(); - final TypeElement nextType = getEnv().type(next); - - current = new ResourceDefinition(nextType, getEnv()); + current = dequeue(outstanding); } return results.stream(); } + private ResourceDefinition dequeue(final Queue outstanding) { + final TypeMirror next = outstanding.remove(); + final TypeElement nextType = getEnv().type(next); + + return new ResourceDefinition(nextType, getEnv()); + } + private Predicate returnTypeIsResource() { return method -> getEnv().type(method.getReturnType()).getAnnotation(Resource.class) != null; } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java index c4035e5b0..ef9d3d05b 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java @@ -61,6 +61,7 @@ void failsToWrite() throws IOException { when(env.getElementUtils()).thenReturn(elementUtils); when(env.getFiler()).thenReturn(filer); + @SuppressWarnings({"rawtypes", "unchecked"}) // For test brevity final Implementor mock = new Implementor(definition) { @Override protected void implementInternal() { From 27f992cd73b26ed2d6ad7c8d237f77e02a01faab Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 3 Mar 2024 11:22:41 +0000 Subject: [PATCH 107/141] Tidy --- .../rdf/wrapping/processor/Definition.java | 22 ++++++-- .../rdf/wrapping/processor/Environment.java | 4 -- .../rdf/wrapping/processor/Implementor.java | 34 +++++------ .../rdf/wrapping/processor/PredicateShim.java | 38 +++++++++++++ .../processor/ResourceDefinition.java | 30 ++++++---- .../wrapping/processor/ResourceValidator.java | 56 +++++++++---------- .../rdf/wrapping/processor/Validator.java | 13 +++-- .../ResourceDefinitionCardinalityTest.java | 22 ++++---- .../wrapping/processor/TemporaryE2ETest.java | 32 ++++++----- 9 files changed, 150 insertions(+), 101 deletions(-) create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/PredicateShim.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java index 23a3184ff..b7b284605 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java @@ -20,21 +20,26 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JTypes.typeOf; +import static javax.lang.model.element.Modifier.STATIC; +import static javax.lang.model.type.TypeKind.VOID; import com.inrupt.rdf.wrapping.annotation.Dataset; import com.inrupt.rdf.wrapping.annotation.Graph; import java.lang.annotation.Annotation; +import java.util.function.Predicate; import java.util.stream.Stream; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; import org.jboss.jdeparser.JType; +import org.jboss.jdeparser.JTypes; class Definition { + static final Predicate isVoid = method -> method.getReturnType().getKind() == VOID; + private final TypeElement type; private final Environment env; @@ -56,6 +61,13 @@ static Definition definition(final TypeElement type, final Environment env) { } } + TypeElement typeOf(final TypeMirror mirror) { + return getEnv().type(mirror); + } + + TypeElement returnTypeOf(final ExecutableElement method) { + return typeOf(method.getReturnType()); + } protected TypeElement getType() { return type; @@ -66,13 +78,13 @@ protected Environment getEnv() { } protected JType getOriginalInterface() { - return typeOf(getType().asType()); + return JTypes.typeOf(getType().asType()); } - protected final Stream membersAnnotatedWith(final Class annotation) { + protected Stream membersAnnotatedWith(final Class annotation) { return getEnv().methodsOf(getType()) .filter(method -> !method.isDefault()) - .filter(method -> !method.getModifiers().contains(Modifier.STATIC)) + .filter(method -> !method.getModifiers().contains(STATIC)) .filter(method -> method.getAnnotation(annotation) != null); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java index 832d7cdf7..8daa99dbc 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java @@ -44,10 +44,6 @@ TypeElement type(final TypeMirror mirror) { return (TypeElement) getTypeUtils().asElement(mirror); } - boolean isVoid(final TypeMirror type) { - return isSameType(type, Void.class); - } - boolean isSameType(final TypeMirror t1, final Class t2) { return getTypeUtils().isSameType(t1, mirror(t2)); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 77b5066d9..c8a3d3735 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -56,14 +56,6 @@ protected Implementor(final T definition) { sourceFile = sources.createSourceFile(packageName, getImplementationClass()); } - private String getImplementationClass() { - final String originalBinaryName = - definition.getEnv().getElementUtils().getBinaryName(definition.getType()).toString(); - final String qualifiedName = asImplementation(originalBinaryName); - final int lastDot = originalBinaryName.lastIndexOf('.'); - return qualifiedName.substring(lastDot + 1); - } - void implement() { implementInternal(); @@ -74,8 +66,6 @@ void implement() { } } - protected abstract void implementInternal(); - static Implementor implementor(final Definition definition) { if (definition instanceof DatasetDefinition) { return new DatasetImplementor((DatasetDefinition) definition); @@ -89,6 +79,12 @@ static Implementor implementor(final Definition definition) { } } + static String asImplementation(final String original) { + return original + "_$impl"; + } + + protected abstract void implementInternal(); + protected void addClass(final Class clazz) { target = sourceFile._class(PUBLIC, getImplementationClass()); target._extends(clazz); @@ -109,16 +105,20 @@ protected JMethodDef addMethod(final ExecutableElement method) { } protected JType asImplementation(final TypeMirror original) { - final TypeElement returnType = definition.getEnv().type(original); - final String originalBinaryName = definition.getEnv() - .getElementUtils() - .getBinaryName(returnType) - .toString(); + final TypeElement returnType = definition.typeOf(original); + final String originalBinaryName = binaryName(returnType); return $t(asImplementation(originalBinaryName)); } - static String asImplementation(final String original) { - return original + "_$impl"; + private String getImplementationClass() { + final String originalBinaryName = binaryName(definition.getType()); + final String qualifiedName = asImplementation(originalBinaryName); + final int lastDot = originalBinaryName.lastIndexOf('.'); + return qualifiedName.substring(lastDot + 1); + } + + private String binaryName(final TypeElement element) { + return definition.getEnv().getElementUtils().getBinaryName(element).toString(); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/PredicateShim.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/PredicateShim.java new file mode 100644 index 000000000..803eaba38 --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/PredicateShim.java @@ -0,0 +1,38 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import java.util.Objects; +import java.util.function.Predicate; + +final class PredicateShim { + /** + * @see Predicate#not(Predicate) + */ + @SuppressWarnings("unchecked") + static Predicate not(final Predicate target) { + Objects.requireNonNull(target); + return (Predicate) target.negate(); + } + + private PredicateShim() { + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index 302acd231..f4a3c0798 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -20,6 +20,9 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; +import static com.inrupt.rdf.wrapping.processor.PredicateShim.not; + import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @@ -35,24 +38,35 @@ import javax.lang.model.type.TypeMirror; class ResourceDefinition extends Definition { + private static final Predicate isComplex = method -> + method.getAnnotation(Property.class).mapping() == AS; + private final Predicate returnsResource = method -> + getEnv().type(method.getReturnType()).getAnnotation(Resource.class) != null; + ResourceDefinition(final TypeElement type, final Environment env) { super(type, env); } Stream primitivePropertyMethods() { - return membersAnnotatedWith(Property.class).filter(returnTypeIsResource().negate()); + return membersAnnotatedWith(Property.class) + .filter(not(returnsResource)); } Stream resourcePropertyMethods() { - return membersAnnotatedWith(Property.class).filter(returnTypeIsResource()); + return membersAnnotatedWith(Property.class) + .filter(returnsResource); } Stream complexMappingPropertyMethods() { - return membersAnnotatedWith(Property.class).filter(isComplexMapping()); + return membersAnnotatedWith(Property.class) + .filter(isComplex) + .filter(not(isVoid)); } Stream primitiveMappingPropertyMethods() { - return membersAnnotatedWith(Property.class).filter(isComplexMapping().negate()); + return membersAnnotatedWith(Property.class) + .filter(not(isComplex)) + .filter(not(isVoid)); } Stream transitiveResourceTypes() { @@ -82,12 +96,4 @@ private ResourceDefinition dequeue(final Queue outstanding) { return new ResourceDefinition(nextType, getEnv()); } - - private Predicate returnTypeIsResource() { - return method -> getEnv().type(method.getReturnType()).getAnnotation(Resource.class) != null; - } - - private Predicate isComplexMapping() { - return method -> method.getAnnotation(Property.class).mapping() == Property.Mapping.AS; - } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 8beea9246..9342e9d01 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -20,8 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static javax.lang.model.type.TypeKind.VOID; - import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.jena.ValueMappings; @@ -55,39 +53,35 @@ protected void validateInternal() { } private void requireCompatiblePrimitiveReturnType() { - definition.primitiveMappingPropertyMethods() - .filter(method -> method.getReturnType().getKind() != VOID) - .forEach(method -> { - final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); - final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); + definition.primitiveMappingPropertyMethods().forEach(method -> { + final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); + final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); - if (!definition.getEnv().getTypeUtils().isAssignable( - mappingMethodReturnType, - method.getReturnType())) { - errors.add(new ValidationError( - method, - "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", - method.getReturnType(), - method.getSimpleName(), - mappingMethodReturnType, - mappingMethod)); - } - }); + if (!definition.getEnv().getTypeUtils().isAssignable( + mappingMethodReturnType, + method.getReturnType())) { + errors.add(new ValidationError( + method, + "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", + method.getReturnType(), + method.getSimpleName(), + mappingMethodReturnType, + mappingMethod)); + } + }); } private void requireCompatibleComplexReturnType() { - definition.complexMappingPropertyMethods() - .filter(method -> method.getReturnType().getKind() != VOID) - .forEach(method -> { - final TypeElement returnType = definition.getEnv().type(method.getReturnType()); - if (returnType == null || returnType.getAnnotation(Resource.class) == null) { - errors.add(new ValidationError( - method, - "Method %s on interface %s must return @Resource interface", - method.getSimpleName(), - definition.getType().getSimpleName())); - } - }); + definition.complexMappingPropertyMethods().forEach(method -> { + final TypeElement returnType = definition.returnTypeOf(method); + if (returnType == null || returnType.getAnnotation(Resource.class) == null) { + errors.add(new ValidationError( + method, + "Method %s on interface %s must return @Resource interface", + method.getSimpleName(), + definition.getType().getSimpleName())); + } + }); } private TypeMirror returnTypeOfMapper(final String mappingMethod) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 434e6ac3b..f73748bec 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -20,8 +20,9 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.processor.Definition.isVoid; +import static com.inrupt.rdf.wrapping.processor.PredicateShim.not; import static javax.lang.model.element.Modifier.STATIC; -import static javax.lang.model.type.TypeKind.VOID; import java.lang.annotation.Annotation; import java.util.ArrayList; @@ -131,13 +132,13 @@ protected void requireAnnotatedReturnType( final Class required) { final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; - final Predicate isNotResource = method -> - definition.getEnv().type(method.getReturnType()).getAnnotation(required) == null; + final Predicate isResource = method -> + definition.returnTypeOf(method).getAnnotation(required) != null; definition.getEnv().methodsOf(definition.getType()) - .filter(method -> method.getReturnType().getKind() != VOID) + .filter(not(isVoid)) .filter(isAnnotated) - .filter(isNotResource) + .filter(not(isResource)) .forEach(method -> errors.add(new ValidationError( method, "Method %s on interface %s annotated with @%s must return @%s interface", @@ -149,7 +150,7 @@ protected void requireAnnotatedReturnType( protected void requireNonVoidReturnType(final Class annotation) { definition.membersAnnotatedWith(annotation) - .filter(method -> method.getReturnType().getKind() == VOID) + .filter(isVoid) .forEach(method -> errors.add(new ValidationError( method, diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java index f60c920d2..fb8c200c8 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java @@ -71,8 +71,8 @@ class ResourceDefinitionCardinalityTest { private static final int NONE = 0; private static final int SINGLE = 1; private static final int MANY = 2; - public static final String DOES_NOT_THROW = "does not throw"; - public static final String THROWS = "throws"; + private static final String DOES_NOT_THROW = "does not throw"; + private static final String THROWS = "throws"; private Model m; private GraphDefinition wrapped; @@ -86,7 +86,7 @@ void setUp() { @DisplayName("properly converts node with cardinality") @ParameterizedTest(name = "{2} for cardinality {0} with {1} items") @MethodSource - void e2e(final Cardinality cardinality, final int number, final String throwing) throws IntrospectionException { + void e2e(final Cardinality cardinality, final int number, final String throwing) throws Exception { final List values = new ArrayList<>(); final Class expectedException; final Matcher asExpected; @@ -130,14 +130,6 @@ void e2e(final Cardinality cardinality, final int number, final String throwing) } } - private static Method findProperty(final ResourceDefinition r, final Cardinality c) throws IntrospectionException { - return stream(getBeanInfo(r.getClass(), Object.class).getPropertyDescriptors()) - .filter(p -> p.getName().equals(c.getMethodName())) - .map(PropertyDescriptor::getReadMethod) - .findAny() - .orElseThrow(RuntimeException::new); - } - private static Stream e2e() { return Stream.of( arguments(ANY_OR_NULL, NONE, DOES_NOT_THROW), @@ -169,6 +161,14 @@ private static Stream wrapperResourceMethods() { .map(Method::getName); } + private static Method findProperty(final ResourceDefinition r, final Cardinality c) throws IntrospectionException { + return stream(getBeanInfo(r.getClass(), Object.class).getPropertyDescriptors()) + .filter(p -> p.getName().equals(c.getMethodName())) + .map(PropertyDescriptor::getReadMethod) + .findAny() + .orElseThrow(RuntimeException::new); + } + @Resource interface ResourceDefinition { @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_STRING) diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java index c0318f4b2..24f54ec35 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java @@ -97,11 +97,12 @@ void graphCanGetFirstObjectOf() { @Test void resourceCanGetProperty() { - final Model model = modelFrom("PREFIX : \n" + - "\n" + - "[\n" + - " a :C ;\n" + - "] .\n"); + final Model model = modelFrom("" + + "PREFIX : \n" + + " \n" + + "[ \n" + + " a :C ; \n" + + "] . \n"); final GraphDefinition y = GraphDefinition.wrap(model); final ResourceDefinition1 z = y.getResource1(); @@ -110,16 +111,17 @@ void resourceCanGetProperty() { @Test void e2e() { - final Dataset dataset = datasetFrom("PREFIX : \n" + - "\n" + - "GRAPH {\n" + - " [\n" + - " a :C ;\n" + - " :p :VALUE ;\n" + - " ] .\n" + - "\n" + - " [ :p [] ] .\n" + - "}\n"); + final Dataset dataset = datasetFrom("" + + "PREFIX : \n" + + " \n" + + "GRAPH { \n" + + " [ \n" + + " a :C ; \n" + + " :p :VALUE ; \n" + + " ] . \n" + + " \n" + + " [ :p [] ] . \n" + + "} \n"); final DatasetDefinition x = DatasetDefinition.wrap(dataset); final GraphDefinition y = x.getNamedGraph(); From 6e396351c48ec85505747dc37618dc36a9035dc7 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 3 Mar 2024 16:49:38 +0000 Subject: [PATCH 108/141] Introduce plural cardinality --- .../rdf/wrapping/annotation/Property.java | 25 +++- .../rdf/wrapping/processor/Environment.java | 10 +- .../processor/ResourceDefinition.java | 9 ++ .../wrapping/processor/ResourceValidator.java | 114 +++++++++++++++--- .../ResourceDefinitionCardinalityTest.java | 56 ++++++++- .../rdf/wrapping/processor/ValidatorTest.java | 15 ++- ...lural property method erasure differs.java | 14 +++ ... plural property method erasure super.java | 14 +++ ...property method type argument differs.java | 16 +++ ...l property method type argument super.java | 16 +++ .../good/resource plural property method.java | 16 +++ 11 files changed, 271 insertions(+), 34 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java create mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method.java diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java index 5d3a970e1..952b16e47 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java @@ -58,19 +58,34 @@ public String getMethodName() { } enum Cardinality { - ANY_OR_NULL("anyOrNull"), - ANY_OR_THROW("anyOrThrow"), - SINGLE_OR_NULL("singleOrNull"), - SINGLE_OR_THROW("singleOrThrow"); + ANY_OR_NULL("anyOrNull", false), + + ANY_OR_THROW("anyOrThrow", false), + + SINGLE_OR_NULL("singleOrNull", false), + + SINGLE_OR_THROW("singleOrThrow", false), + + OBJECT_ITERATOR("objectIterator", true), + + OBJECTS_READ_ONLY("objectsReadOnly", true), + + OBJECT_STREAM("objectStream", true); private final String methodName; + private final boolean plural; - Cardinality(final String methodName) { + Cardinality(final String methodName, final boolean plural) { this.methodName = methodName; + this.plural = plural; } public String getMethodName() { return methodName; } + + public boolean isPlural() { + return plural; + } } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java index 8daa99dbc..3f0563b92 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java @@ -20,8 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import com.inrupt.rdf.wrapping.jena.ValueMappings; - import java.util.stream.Stream; import javax.annotation.processing.ProcessingEnvironment; @@ -45,14 +43,18 @@ TypeElement type(final TypeMirror mirror) { } boolean isSameType(final TypeMirror t1, final Class t2) { - return getTypeUtils().isSameType(t1, mirror(t2)); + return isSameType(t1, mirror(t2)); + } + + boolean isSameType(final TypeMirror t1, final TypeMirror t2) { + return getTypeUtils().isSameType(t1, t2); } Stream methodsOf(final Element element) { return ElementFilter.methodsIn(element.getEnclosedElements()).stream(); } - Stream methodsOf(final Class clazz) { + Stream methodsOf(final Class clazz) { return methodsOf(type(clazz)); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index f4a3c0798..b48f8fe06 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -40,6 +40,8 @@ class ResourceDefinition extends Definition { private static final Predicate isComplex = method -> method.getAnnotation(Property.class).mapping() == AS; + private static final Predicate isPlural = method -> + method.getAnnotation(Property.class).cardinality().isPlural(); private final Predicate returnsResource = method -> getEnv().type(method.getReturnType()).getAnnotation(Resource.class) != null; @@ -60,15 +62,22 @@ Stream resourcePropertyMethods() { Stream complexMappingPropertyMethods() { return membersAnnotatedWith(Property.class) .filter(isComplex) + .filter(not(isPlural)) .filter(not(isVoid)); } Stream primitiveMappingPropertyMethods() { return membersAnnotatedWith(Property.class) .filter(not(isComplex)) + .filter(not(isPlural)) .filter(not(isVoid)); } + Stream pluralPropertyMethods() { + return membersAnnotatedWith(Property.class) + .filter(isPlural); + } + Stream transitiveResourceTypes() { final Queue outstanding = new LinkedList<>(); final Set results = new HashSet<>(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 9342e9d01..e7ecd06ba 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -23,9 +23,15 @@ import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.jena.ValueMappings; +import com.inrupt.rdf.wrapping.jena.WrapperResource; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; class ResourceValidator extends Validator { @@ -50,42 +56,110 @@ protected void validateInternal() { requireNonVoidReturnType(Property.class); requireCompatiblePrimitiveReturnType(); requireCompatibleComplexReturnType(); + + requirePluralErasure(); + requirePluralTypeArgument(); } private void requireCompatiblePrimitiveReturnType() { definition.primitiveMappingPropertyMethods().forEach(method -> { + final TypeMirror thisReturn = method.getReturnType(); + final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); - final TypeMirror mappingMethodReturnType = returnTypeOfMapper(mappingMethod); - - if (!definition.getEnv().getTypeUtils().isAssignable( - mappingMethodReturnType, - method.getReturnType())) { - errors.add(new ValidationError( - method, - "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", - method.getReturnType(), - method.getSimpleName(), - mappingMethodReturnType, - mappingMethod)); + final TypeMirror mappingReturn = returnTypeOf(mappingMethod, ValueMappings.class); + + if (definition.getEnv().getTypeUtils().isAssignable(mappingReturn, thisReturn)) { + return; } + + errors.add(new ValidationError( + method, + "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", + thisReturn, + method.getSimpleName(), + mappingReturn, + mappingMethod)); }); } private void requireCompatibleComplexReturnType() { definition.complexMappingPropertyMethods().forEach(method -> { final TypeElement returnType = definition.returnTypeOf(method); - if (returnType == null || returnType.getAnnotation(Resource.class) == null) { - errors.add(new ValidationError( - method, - "Method %s on interface %s must return @Resource interface", - method.getSimpleName(), - definition.getType().getSimpleName())); + + if (returnType != null && returnType.getAnnotation(Resource.class) != null) { + return; + } + + errors.add(new ValidationError( + method, + "Method %s on interface %s must return @Resource interface", + method.getSimpleName(), + definition.getType().getSimpleName())); + }); + } + + private void requirePluralErasure() { + definition.pluralPropertyMethods().forEach(method -> { + final TypeMirror thisReturn = method.getReturnType(); + final TypeMirror thisErasure = definition.getEnv().getTypeUtils().erasure(thisReturn); + + final String cardinalityMethod = method.getAnnotation(Property.class).cardinality().getMethodName(); + final TypeMirror cardinalityReturn = returnTypeOf(cardinalityMethod, WrapperResource.class); + final TypeMirror cardinalityErasure = + definition.getEnv().getTypeUtils().erasure(cardinalityReturn); + + // TODO: Check subclassing of erasures e.g. Collection & Set + if (definition.getEnv().isSameType(cardinalityErasure, thisErasure)) { + return; } + + errors.add(new ValidationError( + method, + "Return type [%s] of [%s] must have same erasure as return type [%s] of cardinality [%s]", + thisReturn, + method.getSimpleName(), + cardinalityReturn, + cardinalityMethod)); + }); + } + + // TODO: Check bounds of type parameters e.g. String & CharSequence + private void requirePluralTypeArgument() { + definition.pluralPropertyMethods().forEach(method -> { + final DeclaredType thisReturn = (DeclaredType) method.getReturnType(); + final TypeMirror thisErasure = definition.getEnv().getTypeUtils().erasure(thisReturn); + + if (definition.getEnv().isSameType(thisErasure, thisReturn)) { + // Ignore cases where return type of property method is not generic + return; + } + + final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); + final TypeMirror mappingReturn = returnTypeOf(mappingMethod, ValueMappings.class); + + final List mappingTypeArguments = new ArrayList<>(); + mappingTypeArguments.add(definition.typeOf(mappingReturn)); + + final List thisTypeArguments = thisReturn.getTypeArguments().stream() + .map(definition::typeOf) + .collect(Collectors.toList()); + + if (mappingTypeArguments.equals(thisTypeArguments)) { + return; + } + + errors.add(new ValidationError( + method, + "Return type [%s] of [%s] must have same type argument as return type [%s] of mapping [%s]", + thisReturn, + method.getSimpleName(), + mappingReturn, + mappingMethod)); }); } - private TypeMirror returnTypeOfMapper(final String mappingMethod) { - return definition.getEnv().methodsOf(ValueMappings.class) + private TypeMirror returnTypeOf(final String mappingMethod, final Class clazz) { + return definition.getEnv().methodsOf(clazz) .filter(method -> method.getSimpleName().contentEquals(mappingMethod)) .map(ExecutableElement::getReturnType) .findFirst() diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java index fb8c200c8..e7f8dbbee 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java @@ -45,7 +45,9 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; +import java.util.Set; import java.util.stream.Stream; import org.apache.jena.rdf.model.Model; @@ -56,6 +58,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; @DisplayName("Resource definition") @@ -83,10 +86,10 @@ void setUp() { wrapped = GraphDefinition.wrap(m); } - @DisplayName("properly converts node with cardinality") + @DisplayName("properly converts/fails node with cardinality") @ParameterizedTest(name = "{2} for cardinality {0} with {1} items") @MethodSource - void e2e(final Cardinality cardinality, final int number, final String throwing) throws Exception { + void singular(final Cardinality cardinality, final int number, final String throwing) throws Exception { final List values = new ArrayList<>(); final Class expectedException; final Matcher asExpected; @@ -130,7 +133,7 @@ void e2e(final Cardinality cardinality, final int number, final String throwing) } } - private static Stream e2e() { + private static Stream singular() { return Stream.of( arguments(ANY_OR_NULL, NONE, DOES_NOT_THROW), arguments(ANY_OR_NULL, SINGLE, DOES_NOT_THROW), @@ -147,6 +150,44 @@ private static Stream e2e() { ); } + @DisplayName("returns correct items for plural cardinality") + @ParameterizedTest(name = "{0}") + @EnumSource(value = Cardinality.class, names = {"OBJECT_ITERATOR", "OBJECTS_READ_ONLY", "OBJECT_STREAM"}) + @SuppressWarnings("unchecked") + void plural(final Cardinality cardinality) throws Exception { + final List values = new ArrayList<>(); + + // anchor for graph definition + final org.apache.jena.rdf.model.Resource s = m.createResource().addProperty(type, m.createResource(C)); + final ResourceDefinition resource = wrapped.getResource(); + + for (int i = 0; i < 100; i++) { + final String value = randomUUID().toString(); + values.add(value); + s.addProperty(m.createProperty(P), m.createTypedLiteral(value)); + } + + final Object invoke = findProperty(resource, cardinality).invoke(resource); + + final Iterable result; + switch (cardinality) { + case OBJECT_ITERATOR: + result = () -> (Iterator) invoke; + break; + + case OBJECTS_READ_ONLY: + result = (Set) invoke; + break; + + default: + case OBJECT_STREAM: + result = () -> ((Stream) invoke).iterator(); + break; + } + + assertThat(result, containsInAnyOrder(values.toArray())); + } + @Disabled("Not ready yet") // TODO: Enable @DisplayName("mock has equivalent of ValueMappings method") @ParameterizedTest(name = "{0}") @@ -182,6 +223,15 @@ interface ResourceDefinition { @Property(predicate = P, cardinality = SINGLE_OR_THROW, mapping = LITERAL_AS_STRING) String getSingleOrThrow(); + + @Property(predicate = P, cardinality = OBJECT_ITERATOR, mapping = LITERAL_AS_STRING) + Iterator getObjectIterator(); + + @Property(predicate = P, cardinality = OBJECTS_READ_ONLY, mapping = LITERAL_AS_STRING) + Set getObjectsReadOnly(); + + @Property(predicate = P, cardinality = OBJECT_STREAM, mapping = LITERAL_AS_STRING) + Stream getObjectStream(); } @Graph diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 6e58cb298..4d7c18a7b 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -101,7 +101,16 @@ private static Stream compilationErrorOnInvalid() { arguments("resource property method return type not assignable", "must be assignable from return type"), arguments("resource property method is void", MUST_NOT_BE_VOID), arguments("resource complex property method is not resource", MUST_RETURN_RESOURCE_INTERFACE), - arguments("resource complex property method is void", MUST_NOT_BE_VOID) + arguments("resource complex property method is void", MUST_NOT_BE_VOID), + + arguments("resource plural property method erasure differs", "must have same erasure as return type"), + arguments("resource plural property method erasure super", "must have same erasure as return type"), + arguments( + "resource plural property method type argument differs", + "must have same type argument as return type"), + arguments( + "resource plural property method type argument super", + "must have same type argument as return type") ); } @@ -138,7 +147,9 @@ private static Stream compilationSucceeds() { arguments("resource unannotated method is static"), arguments("resource unannotated method is default"), arguments("resource complex property method is resource instance"), - arguments("resource complex property method recursive") + arguments("resource complex property method recursive"), + + arguments("resource plural property method") ); } } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java new file mode 100644 index 000000000..486ec369d --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java @@ -0,0 +1,14 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECT_ITERATOR; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + @Property(predicate = "x", cardinality = OBJECT_ITERATOR, mapping = IRI_AS_STRING) + String x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java new file mode 100644 index 000000000..bfc55364a --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java @@ -0,0 +1,14 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECTS_READ_ONLY; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +@Resource +interface X { + @Property(predicate = "x", cardinality = OBJECTS_READ_ONLY, mapping = IRI_AS_STRING) + Iterable x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java new file mode 100644 index 000000000..d23f1f245 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECT_ITERATOR; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +import java.util.Iterator; + +@Resource +interface X { + @Property(predicate = "x", cardinality = OBJECT_ITERATOR, mapping = IRI_AS_STRING) + Iterator x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java new file mode 100644 index 000000000..3ecdcb842 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECTS_READ_ONLY; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +import java.util.Set; + +@Resource +interface X { + @Property(predicate = "x", cardinality = OBJECTS_READ_ONLY, mapping = IRI_AS_STRING) + Set x(); +} diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method.java b/processor/src/test/resources/validationExamples/good/resource plural property method.java new file mode 100644 index 000000000..3391c62aa --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource plural property method.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECT_ITERATOR; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Resource; + +import java.util.Iterator; + +@Resource +interface X { + @Property(predicate = "x", cardinality = OBJECT_ITERATOR, mapping = IRI_AS_STRING) + Iterator x(); +} From ce5c0bc1a400024c2a718b620febedfa8c01554c Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 3 Mar 2024 18:47:37 +0000 Subject: [PATCH 109/141] Improve end-to-end test --- .../rdf/wrapping/processor/E2ETest.java | 179 +++++++++++++++ .../wrapping/processor/TemporaryE2ETest.java | 207 ------------------ 2 files changed, 179 insertions(+), 207 deletions(-) create mode 100644 processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java delete mode 100644 processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java new file mode 100644 index 000000000..b2243c9a2 --- /dev/null +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -0,0 +1,179 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import static com.github.jsonldjava.shaded.com.google.common.base.Charsets.UTF_8; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.*; +import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.*; +import static com.inrupt.rdf.wrapping.processor.E2ETest.*; +import static java.util.UUID.randomUUID; +import static org.apache.commons.io.IOUtils.toInputStream; +import static org.apache.jena.riot.Lang.TRIG; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThrows; + +import com.inrupt.rdf.wrapping.annotation.*; + +import java.net.URI; +import java.util.Set; +import java.util.UUID; + +import org.apache.jena.query.DatasetFactory; +import org.apache.jena.riot.RDFDataMgr; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class E2ETest { + private static final String NS = "urn:example:"; + private static final URI U = URI.create(NS); + static final String G = NS + "g"; + static final String LABEL = NS + "label"; + static final String CHILD = NS + "child"; + static final String IRI = NS + "iri"; + static final String THROWING = NS + "throwing"; + static final String MANY = NS + "many"; + static final String C = NS + "C"; + static final UUID STATIC = randomUUID(); + + private static final String RDF = "" + + " BASE \n" + + " PREFIX : <> \n" + + " \n" + + " [ \n" + + " a :C ; \n" + + " :label 1 ; \n" + + " :iri <> ; \n" + + " :many 2, 3 ; \n" + + " :child [ \n" + + " :label 4 ; \n" + + " :iri <> ; \n" + + " ] ; \n" + + " ] . \n" + + " \n" + + " GRAPH :g { \n" + + " [ \n" + + " a :C ; \n" + + " :label 5 ; \n" + + " ] . \n" + + " } \n"; + private static final org.apache.jena.query.Dataset DATASET = DatasetFactory.create(); + + @BeforeEach + void setUp() { + RDFDataMgr.read(DATASET, toInputStream(RDF, UTF_8), TRIG); + } + + @Test + void test() { + final MyDataset myDataset = MyDataset.wrap(DATASET); + + assertThat(myDataset.anonymous().instance().label(), is(1)); + assertThat(myDataset.anonymous().instance().uri(), is(U)); + assertThat(myDataset.anonymous().instance().many(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().child().label(), is(4)); + assertThrows(Throwable.class, () -> myDataset.anonymous().instance().throwing()); + assertThat(myDataset.anonymous().instance().childLabel(), is(4)); + assertThat(myDataset.anonymous().subject().label(), is(1)); + assertThat(myDataset.anonymous().object().label(), is(4)); + assertThat(myDataset.anonymous().label(), is(1)); + assertThat(myDataset.named().instance().label(), is(5)); + assertThat(myDataset.label(), is(5)); + + assertThat(MyDataset.constant(), is(STATIC)); + assertThat(MyGraph.constant(), is(STATIC)); + assertThat(MyResource.constant(), is(STATIC)); + } +} + +@Dataset +interface MyDataset { + static MyDataset wrap(final org.apache.jena.query.Dataset original) { + return Manager.wrap(original, MyDataset.class); + } + + @DefaultGraph + MyGraph anonymous(); + + @NamedGraph(G) + MyGraph named(); + + // Dataset definitions support static methods. + static UUID constant() { + return STATIC; + } + + // Dataset definitions support default methods. + default Integer label() { + return named().instance().label(); + } +} + +@Graph +interface MyGraph { + @OptionalFirstInstanceOfEither(C) + MyResource instance(); + + @OptionalFirstSubjectOfEither(CHILD) + MyResource subject(); + + @OptionalFirstObjectOfEither(CHILD) + MyResource object(); + + // Graph definitions support static methods. + static UUID constant() { + return STATIC; + } + + // Graph definitions support default methods. + default Integer label() { + return instance().label(); + } +} + +@Resource +interface MyResource { + @Property(predicate = LABEL, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_INTEGER_OR_NULL) + Integer label(); + + @Property(predicate = IRI, cardinality = ANY_OR_NULL, mapping = IRI_AS_URI) + URI uri(); + + @Property(predicate = CHILD, cardinality = ANY_OR_NULL, mapping = AS) + MyResource child(); + + @Property(predicate = THROWING, cardinality = ANY_OR_THROW, mapping = LITERAL_AS_STRING) + String throwing(); + + @Property(predicate = MANY, cardinality = OBJECTS_READ_ONLY, mapping = LITERAL_AS_INTEGER_OR_NULL) + Set many(); + + // Resource definitions support static methods. + static UUID constant() { + return STATIC; + } + + // Resource definitions support default methods. + default Integer childLabel() { + return child().label(); + } +} diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java deleted file mode 100644 index 24f54ec35..000000000 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/TemporaryE2ETest.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.processor; - -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.*; -import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; - -import com.github.jsonldjava.shaded.com.google.common.base.Charsets; -import com.inrupt.rdf.wrapping.annotation.*; -import com.inrupt.rdf.wrapping.processor.TemporaryE2ETest.DatasetDefinition.GraphDefinition; -import com.inrupt.rdf.wrapping.processor.TemporaryE2ETest.DatasetDefinition.GraphDefinition.ResourceDefinition1; -import com.inrupt.rdf.wrapping.processor.TemporaryE2ETest.DatasetDefinition.GraphDefinition.ResourceDefinition2; -import com.inrupt.rdf.wrapping.processor.TemporaryE2ETest.DatasetDefinition.GraphDefinition.ResourceDefinition3; - -import java.net.URI; - -import org.apache.commons.io.IOUtils; -import org.apache.jena.query.Dataset; -import org.apache.jena.query.DatasetFactory; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.riot.Lang; -import org.apache.jena.riot.RDFDataMgr; -import org.junit.jupiter.api.Test; - -class TemporaryE2ETest { - @Test - void datasetCanWrap() { - final Dataset dataset = DatasetFactory.create(); - - assertDoesNotThrow(() -> DatasetDefinition.wrap(dataset)); - } - - @Test - void datasetCanGetDefaultGraph() { - final DatasetDefinition x = DatasetDefinition.wrap(DatasetFactory.create()); - - assertDoesNotThrow(x::getDefaultGraph); - } - - @Test - void datasetCanGetNamedGraph() { - final DatasetDefinition x = DatasetDefinition.wrap(DatasetFactory.create()); - - assertDoesNotThrow(x::getNamedGraph); - } - - @Test - void graphCanWrap() { - final Model model = createDefaultModel(); - - assertDoesNotThrow(() -> GraphDefinition.wrap(model)); - } - - @Test - void graphCanGetFirstInstanceOf() { - final Model model = createDefaultModel(); - final GraphDefinition y = GraphDefinition.wrap(model); - - assertDoesNotThrow(y::getResource1); - } - - @Test - void graphCanGetFirstSubjectOf() { - final Model model = createDefaultModel(); - final GraphDefinition y = GraphDefinition.wrap(model); - - assertDoesNotThrow(y::getResource2); - } - - @Test - void graphCanGetFirstObjectOf() { - final Model model = createDefaultModel(); - final GraphDefinition y = GraphDefinition.wrap(model); - - assertDoesNotThrow(y::getResource3); - } - - @Test - void resourceCanGetProperty() { - final Model model = modelFrom("" + - "PREFIX : \n" + - " \n" + - "[ \n" + - " a :C ; \n" + - "] . \n"); - final GraphDefinition y = GraphDefinition.wrap(model); - final ResourceDefinition1 z = y.getResource1(); - - assertDoesNotThrow(z::getProperty1); - } - - @Test - void e2e() { - final Dataset dataset = datasetFrom("" + - "PREFIX : \n" + - " \n" + - "GRAPH { \n" + - " [ \n" + - " a :C ; \n" + - " :p :VALUE ; \n" + - " ] . \n" + - " \n" + - " [ :p [] ] . \n" + - "} \n"); - - final DatasetDefinition x = DatasetDefinition.wrap(dataset); - final GraphDefinition y = x.getNamedGraph(); - final ResourceDefinition1 z = y.getResource1(); - final ResourceDefinition1 z2 = y.getResource2(); - final ResourceDefinition1 z3 = y.getResource3(); - final String p = z.getProperty1(); - final URI p2 = z.getProperty2(); - final ResourceDefinition2 p3 = z.getProperty3(); - final ResourceDefinition3 p4 = p3.getProperty(); - - System.out.println(z); - System.out.println(z2); - System.out.println(z3); - System.out.println(p); - System.out.println(p2); - System.out.println(p3); - System.out.println(p4); - } - - private static Dataset datasetFrom(final String rdf) { - final Dataset dataset = DatasetFactory.create(); - RDFDataMgr.read(dataset, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); - return dataset; - } - - private static Model modelFrom(final String rdf) { - final Model model = createDefaultModel(); - RDFDataMgr.read(model, IOUtils.toInputStream(rdf, Charsets.UTF_8), Lang.TRIG); - return model; - } - - @com.inrupt.rdf.wrapping.annotation.Dataset - interface DatasetDefinition { - static DatasetDefinition wrap(final Dataset original) { - return Manager.wrap(original, DatasetDefinition.class); - } - - @DefaultGraph - GraphDefinition getDefaultGraph(); - - @NamedGraph("urn:example:g1") - GraphDefinition getNamedGraph(); - - @Graph - interface GraphDefinition { - static GraphDefinition wrap(final Model original) { - return Manager.wrap(original, GraphDefinition.class); - } - - @OptionalFirstInstanceOfEither({"urn:example:C", "urn:example:Other"}) - ResourceDefinition1 getResource1(); - - @OptionalFirstSubjectOfEither({"urn:example:p", "urn:example:Other"}) - ResourceDefinition1 getResource2(); - - @OptionalFirstObjectOfEither({"urn:example:p", "urn:example:Other"}) - ResourceDefinition1 getResource3(); - - @Resource - interface ResourceDefinition1 { - @Property(predicate = "urn:example:p", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) - String getProperty1(); - - @Property(predicate = "urn:example:p", cardinality = ANY_OR_NULL, mapping = IRI_AS_URI) - URI getProperty2(); - - @Property(predicate = "urn:example:p", cardinality = ANY_OR_NULL, mapping = AS) - ResourceDefinition2 getProperty3(); - } - - @Resource - interface ResourceDefinition2 { - @Property(predicate = "urn:example:p", cardinality = ANY_OR_NULL, mapping = AS) - ResourceDefinition3 getProperty(); - } - - @Resource - interface ResourceDefinition3 { - } - } - } -} From 18e34ef069caa63f36cb87ec3d9f64985fb73315 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 9 Mar 2024 09:39:11 +0000 Subject: [PATCH 110/141] Introducing mutation --- .../rdf/wrapping/annotation/Property.java | 54 ++++++++++--- .../wrapping/annotation/NodeMappingTest.java | 78 +++++++++++++++++++ ...MappingTest.java => ValueMappingTest.java} | 19 ++--- .../processor/ResourceDefinition.java | 13 +++- .../processor/ResourceImplementor.java | 33 ++++++-- .../wrapping/processor/ResourceValidator.java | 21 ++++- .../rdf/wrapping/processor/E2ETest.java | 19 +++-- .../ResourceDefinitionCardinalityTest.java | 16 ++-- ...> ResourceDefinitionValueMappingTest.java} | 31 ++++---- ...mplex property method is not resource.java | 5 +- ...ource complex property method is void.java | 5 +- ...lural property method erasure differs.java | 4 +- ... plural property method erasure super.java | 4 +- ...property method type argument differs.java | 4 +- ...l property method type argument super.java | 4 +- .../resource property method is default.java | 5 +- .../resource property method is static.java | 5 +- .../bad/resource property method is void.java | 5 +- ...rty method return type not assignable.java | 5 +- ... property method is resource instance.java | 5 +- ...rce complex property method recursive.java | 5 +- .../good/resource plural property method.java | 4 +- ...roperty method is assignable instance.java | 5 +- 23 files changed, 246 insertions(+), 103 deletions(-) create mode 100644 annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/NodeMappingTest.java rename annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/{MappingTest.java => ValueMappingTest.java} (87%) rename processor/src/test/java/com/inrupt/rdf/wrapping/processor/{ResourceDefinitionMappingTest.java => ResourceDefinitionValueMappingTest.java} (84%) diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java index 952b16e47..2c7facf52 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java @@ -20,6 +20,9 @@ */ package com.inrupt.rdf.wrapping.annotation; +import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; +import static com.inrupt.rdf.wrapping.annotation.Property.NodeMapping.IDENTITY; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.AS; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -33,11 +36,13 @@ public @interface Property { String predicate(); - Cardinality cardinality(); + Cardinality cardinality() default ANY_OR_NULL; - Mapping mapping(); + ValueMapping valueMapping() default AS; - enum Mapping { + NodeMapping nodeMapping() default IDENTITY; + + enum ValueMapping { AS("as"), IRI_AS_STRING("iriAsString"), IRI_AS_URI("iriAsUri"), @@ -48,7 +53,24 @@ enum Mapping { private final String methodName; - Mapping(final String methodName) { + ValueMapping(final String methodName) { + this.methodName = methodName; + } + + public String getMethodName() { + return methodName; + } + } + + enum NodeMapping { + AS_STRING_LITERAL("asStringLiteral"), + AS_IRI("asIri"), + AS_TYPED_LITERAL("asTypedLiteral"), + IDENTITY("identity"); + + private final String methodName; + + NodeMapping(final String methodName) { this.methodName = methodName; } @@ -58,26 +80,30 @@ public String getMethodName() { } enum Cardinality { - ANY_OR_NULL("anyOrNull", false), + ANY_OR_NULL("anyOrNull", false, false), - ANY_OR_THROW("anyOrThrow", false), + ANY_OR_THROW("anyOrThrow", false, false), - SINGLE_OR_NULL("singleOrNull", false), + SINGLE_OR_NULL("singleOrNull", false, false), - SINGLE_OR_THROW("singleOrThrow", false), + SINGLE_OR_THROW("singleOrThrow", false, false), - OBJECT_ITERATOR("objectIterator", true), + OBJECT_ITERATOR("objectIterator", true, false), - OBJECTS_READ_ONLY("objectsReadOnly", true), + OBJECTS_READ_ONLY("objectsReadOnly", true, false), - OBJECT_STREAM("objectStream", true); + OBJECT_STREAM("objectStream", true, false), + + OVERWRITE("overwrite", false, true); private final String methodName; private final boolean plural; + private final boolean setter; - Cardinality(final String methodName, final boolean plural) { + Cardinality(final String methodName, final boolean plural, final boolean setter) { this.methodName = methodName; this.plural = plural; + this.setter = setter; } public String getMethodName() { @@ -87,5 +113,9 @@ public String getMethodName() { public boolean isPlural() { return plural; } + + public boolean isSetter() { + return setter; + } } } diff --git a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/NodeMappingTest.java b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/NodeMappingTest.java new file mode 100644 index 000000000..9ee914615 --- /dev/null +++ b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/NodeMappingTest.java @@ -0,0 +1,78 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.annotation; + +import static java.lang.reflect.Modifier.isPublic; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.toList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.describedAs; +import static org.hamcrest.Matchers.in; + +import com.inrupt.rdf.wrapping.annotation.Property.NodeMapping; +import com.inrupt.rdf.wrapping.jena.NodeMappings; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.stream.Stream; + +import org.hamcrest.Matcher; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.MethodSource; + +@DisplayName("Node mapping") +class NodeMappingTest { + private static final Collection MAPPING_METHODS = mappingMethods().collect(toList()); + private static final Collection ENUM_CONSTANTS = stream(NodeMapping.class.getEnumConstants()) + .map(NodeMapping::getMethodName) + .collect(toList()); + + @DisplayName("has equivalent NodeMappings method for enum constant") + @ParameterizedTest(name = "{0}") + @EnumSource(NodeMapping.class) + void constantHasEquivalentMethod(final NodeMapping nodeMapping) { + final Matcher hasCorrespondingMethod = describedAs("NodeMappings to have corresponding method", + in(MAPPING_METHODS)); + + assertThat("Mapping enum constant without corresponding NodeMappings method", + nodeMapping.getMethodName(), hasCorrespondingMethod); + } + + @DisplayName("has enum constant equivalent to NodeMappings method") + @ParameterizedTest(name = "{0}") + @MethodSource("mappingMethods") + void methodHasEquivalentConstant(final String method) { + final Matcher hasCorrespondingConstant = describedAs("Mapping enum to have corresponding constant", + in(ENUM_CONSTANTS)); + + assertThat("NodeMappings method without corresponding Mapping enum constant", + method, hasCorrespondingConstant); + } + + private static Stream mappingMethods() { + return stream(NodeMappings.class.getDeclaredMethods()) + .filter(method -> isPublic(method.getModifiers())) + .map(Method::getName) + .distinct(); + } +} diff --git a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/ValueMappingTest.java similarity index 87% rename from annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java rename to annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/ValueMappingTest.java index d502c087e..0aa0f27c2 100644 --- a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/MappingTest.java +++ b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/ValueMappingTest.java @@ -20,7 +20,6 @@ */ package com.inrupt.rdf.wrapping.annotation; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping; import static java.lang.reflect.Modifier.isPublic; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toList; @@ -28,6 +27,7 @@ import static org.hamcrest.Matchers.describedAs; import static org.hamcrest.Matchers.in; +import com.inrupt.rdf.wrapping.annotation.Property.ValueMapping; import com.inrupt.rdf.wrapping.jena.ValueMappings; import java.lang.reflect.Method; @@ -40,22 +40,22 @@ import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; -@DisplayName("Mapping") -class MappingTest { +@DisplayName("Value mapping") +class ValueMappingTest { private static final Collection MAPPING_METHODS = mappingMethods().collect(toList()); - private static final Collection ENUM_CONSTANTS = stream(Mapping.class.getEnumConstants()) - .map(Mapping::getMethodName) + private static final Collection ENUM_CONSTANTS = stream(ValueMapping.class.getEnumConstants()) + .map(ValueMapping::getMethodName) .collect(toList()); @DisplayName("has equivalent ValueMappings method for enum constant") @ParameterizedTest(name = "{0}") - @EnumSource(Mapping.class) - void constantHasEquivalentMethod(final Mapping mapping) { + @EnumSource(ValueMapping.class) + void constantHasEquivalentMethod(final ValueMapping valueMapping) { final Matcher hasCorrespondingMethod = describedAs("ValueMappings to have corresponding method", in(MAPPING_METHODS)); assertThat("Mapping enum constant without corresponding ValueMappings method", - mapping.getMethodName(), hasCorrespondingMethod); + valueMapping.getMethodName(), hasCorrespondingMethod); } @DisplayName("has enum constant equivalent to ValueMappings method") @@ -72,6 +72,7 @@ void methodHasEquivalentConstant(final String method) { private static Stream mappingMethods() { return stream(ValueMappings.class.getDeclaredMethods()) .filter(method -> isPublic(method.getModifiers())) - .map(Method::getName); + .map(Method::getName) + .distinct(); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index b48f8fe06..42ed4cac3 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.AS; import static com.inrupt.rdf.wrapping.processor.PredicateShim.not; import com.inrupt.rdf.wrapping.annotation.Property; @@ -39,11 +39,13 @@ class ResourceDefinition extends Definition { private static final Predicate isComplex = method -> - method.getAnnotation(Property.class).mapping() == AS; + method.getAnnotation(Property.class).valueMapping() == AS; private static final Predicate isPlural = method -> method.getAnnotation(Property.class).cardinality().isPlural(); private final Predicate returnsResource = method -> getEnv().type(method.getReturnType()).getAnnotation(Resource.class) != null; + static final Predicate isSetter = method -> + method.getAnnotation(Property.class).cardinality().isSetter(); ResourceDefinition(final TypeElement type, final Environment env) { super(type, env); @@ -51,11 +53,13 @@ class ResourceDefinition extends Definition { Stream primitivePropertyMethods() { return membersAnnotatedWith(Property.class) + .filter(not(isSetter)) .filter(not(returnsResource)); } Stream resourcePropertyMethods() { return membersAnnotatedWith(Property.class) + .filter(not(isSetter)) .filter(returnsResource); } @@ -66,6 +70,11 @@ Stream complexMappingPropertyMethods() { .filter(not(isVoid)); } + Stream setterPropertyMethods() { + return membersAnnotatedWith(Property.class) + .filter(isSetter); + } + Stream primitiveMappingPropertyMethods() { return membersAnnotatedWith(Property.class) .filter(not(isComplex)) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 4d4c34a5e..0c87072b6 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -25,19 +25,18 @@ import static org.jboss.jdeparser.JTypes.$t; import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.jena.NodeMappings; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; import com.inrupt.rdf.wrapping.jena.ValueMappings; import com.inrupt.rdf.wrapping.jena.WrapperResource; import javax.annotation.Generated; import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.graph.Node; -import org.jboss.jdeparser.JCall; -import org.jboss.jdeparser.JExpr; -import org.jboss.jdeparser.JMethodDef; -import org.jboss.jdeparser.JType; +import org.jboss.jdeparser.*; class ResourceImplementor extends Implementor { static final String FACTORY = "factory"; @@ -54,6 +53,7 @@ protected void implementInternal() { addConstructor(); addPrimitivePropertyMethods(); addResourcePropertyMethods(); + addOverwrite(); } private void addImports() { @@ -64,7 +64,8 @@ private void addImports() { ._import(EnhGraph.class) ._import(org.apache.jena.enhanced.Implementation.class) ._import(Node.class) - ._import(ValueMappings.class); + ._import(ValueMappings.class) + ._import(NodeMappings.class); } private void addClass() { @@ -91,7 +92,7 @@ private void addConstructor() { private void addPrimitivePropertyMethods() { definition.primitivePropertyMethods().forEach(method -> { - final String mappingMethodName = method.getAnnotation(Property.class).mapping().getMethodName(); + final String mappingMethodName = method.getAnnotation(Property.class).valueMapping().getMethodName(); final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); addPropertyMethod(method, mapping); @@ -107,6 +108,26 @@ private void addResourcePropertyMethods() { }); } + // TODO: Validate + // TODO: Cover + // TODO: Other mutators + private void addOverwrite() { + definition.setterPropertyMethods().forEach(method -> { + final Property annotation = method.getAnnotation(Property.class); + final String predicateFromAnnotation = annotation.predicate(); + final String cardinality = annotation.cardinality().getMethodName(); + final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); + final JMethodDef m = addMethod(method); + + final String mappingMethodName = annotation.nodeMapping().getMethodName(); + final JExpr mapping = $t(NodeMappings.class).methodRef(mappingMethodName); + + final VariableElement variableElement = method.getParameters().get(0); + final JParamDeclaration value = m.param(FINAL, JTypes.typeOf(variableElement.asType()), "value"); + m.body().call(cardinality).arg(predicate).arg($v(value)).arg(mapping); + }); + } + private void addPropertyMethod(final ExecutableElement method, final JExpr mapping) { final Property annotation = method.getAnnotation(Property.class); final String predicateFromAnnotation = annotation.predicate(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index e7ecd06ba..aecc6dc2d 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -20,6 +20,10 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.processor.Definition.isVoid; +import static com.inrupt.rdf.wrapping.processor.PredicateShim.not; +import static com.inrupt.rdf.wrapping.processor.ResourceDefinition.isSetter; + import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.jena.ValueMappings; @@ -53,7 +57,7 @@ protected void validateInternal() { requireNonMemberMethods(Property.class); - requireNonVoidReturnType(Property.class); + requireNonVoidReturnType(); requireCompatiblePrimitiveReturnType(); requireCompatibleComplexReturnType(); @@ -61,11 +65,22 @@ protected void validateInternal() { requirePluralTypeArgument(); } + private void requireNonVoidReturnType() { + definition.membersAnnotatedWith(Property.class) + .filter(not(isSetter)) + .filter(isVoid) + .forEach(method -> + errors.add(new ValidationError( + method, + "Method [%s] must not be void", + method.getSimpleName()))); + } + private void requireCompatiblePrimitiveReturnType() { definition.primitiveMappingPropertyMethods().forEach(method -> { final TypeMirror thisReturn = method.getReturnType(); - final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); + final String mappingMethod = method.getAnnotation(Property.class).valueMapping().getMethodName(); final TypeMirror mappingReturn = returnTypeOf(mappingMethod, ValueMappings.class); if (definition.getEnv().getTypeUtils().isAssignable(mappingReturn, thisReturn)) { @@ -134,7 +149,7 @@ private void requirePluralTypeArgument() { return; } - final String mappingMethod = method.getAnnotation(Property.class).mapping().getMethodName(); + final String mappingMethod = method.getAnnotation(Property.class).valueMapping().getMethodName(); final TypeMirror mappingReturn = returnTypeOf(mappingMethod, ValueMappings.class); final List mappingTypeArguments = new ArrayList<>(); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index b2243c9a2..bb8f42625 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -22,7 +22,8 @@ import static com.github.jsonldjava.shaded.com.google.common.base.Charsets.UTF_8; import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.*; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.*; +import static com.inrupt.rdf.wrapping.annotation.Property.NodeMapping.AS_TYPED_LITERAL; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.*; import static com.inrupt.rdf.wrapping.processor.E2ETest.*; import static java.util.UUID.randomUUID; import static org.apache.commons.io.IOUtils.toInputStream; @@ -102,6 +103,9 @@ void test() { assertThat(MyDataset.constant(), is(STATIC)); assertThat(MyGraph.constant(), is(STATIC)); assertThat(MyResource.constant(), is(STATIC)); + + myDataset.anonymous().instance().overwrite(999); + assertThat(myDataset.anonymous().instance().label(), is(999)); } } @@ -152,21 +156,24 @@ default Integer label() { @Resource interface MyResource { - @Property(predicate = LABEL, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_INTEGER_OR_NULL) + @Property(predicate = LABEL, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Integer label(); - @Property(predicate = IRI, cardinality = ANY_OR_NULL, mapping = IRI_AS_URI) + @Property(predicate = IRI, valueMapping = IRI_AS_URI) URI uri(); - @Property(predicate = CHILD, cardinality = ANY_OR_NULL, mapping = AS) + @Property(predicate = CHILD) MyResource child(); - @Property(predicate = THROWING, cardinality = ANY_OR_THROW, mapping = LITERAL_AS_STRING) + @Property(predicate = THROWING, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) String throwing(); - @Property(predicate = MANY, cardinality = OBJECTS_READ_ONLY, mapping = LITERAL_AS_INTEGER_OR_NULL) + @Property(predicate = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Set many(); + @Property(predicate = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) + void overwrite(Integer value); + // Resource definitions support static methods. static UUID constant() { return STATIC; diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java index e7f8dbbee..0e2be0c6f 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java @@ -21,7 +21,7 @@ package com.inrupt.rdf.wrapping.processor; import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.*; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.LITERAL_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.LITERAL_AS_STRING; import static java.beans.Introspector.getBeanInfo; import static java.lang.reflect.Modifier.isProtected; import static java.util.Arrays.stream; @@ -212,25 +212,25 @@ private static Method findProperty(final ResourceDefinition r, final Cardinality @Resource interface ResourceDefinition { - @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_STRING) + @Property(predicate = P, valueMapping = LITERAL_AS_STRING) String getAnyOrNull(); - @Property(predicate = P, cardinality = ANY_OR_THROW, mapping = LITERAL_AS_STRING) + @Property(predicate = P, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) String getAnyOrThrow(); - @Property(predicate = P, cardinality = SINGLE_OR_NULL, mapping = LITERAL_AS_STRING) + @Property(predicate = P, cardinality = SINGLE_OR_NULL, valueMapping = LITERAL_AS_STRING) String getSingleOrNull(); - @Property(predicate = P, cardinality = SINGLE_OR_THROW, mapping = LITERAL_AS_STRING) + @Property(predicate = P, cardinality = SINGLE_OR_THROW, valueMapping = LITERAL_AS_STRING) String getSingleOrThrow(); - @Property(predicate = P, cardinality = OBJECT_ITERATOR, mapping = LITERAL_AS_STRING) + @Property(predicate = P, cardinality = OBJECT_ITERATOR, valueMapping = LITERAL_AS_STRING) Iterator getObjectIterator(); - @Property(predicate = P, cardinality = OBJECTS_READ_ONLY, mapping = LITERAL_AS_STRING) + @Property(predicate = P, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_STRING) Set getObjectsReadOnly(); - @Property(predicate = P, cardinality = OBJECT_STREAM, mapping = LITERAL_AS_STRING) + @Property(predicate = P, cardinality = OBJECT_STREAM, valueMapping = LITERAL_AS_STRING) Stream getObjectStream(); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionMappingTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java similarity index 84% rename from processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionMappingTest.java rename to processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java index 8fd6a01aa..7bcef15b6 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionMappingTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java @@ -20,8 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.*; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.*; import static java.lang.reflect.Modifier.isPublic; import static java.util.Arrays.stream; import static java.util.UUID.randomUUID; @@ -36,7 +35,7 @@ import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; import com.inrupt.rdf.wrapping.annotation.Property; -import com.inrupt.rdf.wrapping.annotation.Property.Mapping; +import com.inrupt.rdf.wrapping.annotation.Property.ValueMapping; import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.jena.ValueMappings; @@ -56,13 +55,13 @@ import org.junit.jupiter.params.provider.MethodSource; @DisplayName("Resource definition") -class ResourceDefinitionMappingTest { +class ResourceDefinitionValueMappingTest { private static final String P = "urn:example:p"; private static final String C = "urn:example:c"; private static final Object[] RESOURCE_DEFINITION_METHODS = stream(ResourceDefinition.class.getDeclaredMethods()) .map(m -> m.getAnnotation(Property.class)) - .map(Property::mapping) - .map(Mapping::getMethodName) + .map(Property::valueMapping) + .map(ValueMapping::getMethodName) .toArray(); private Model m; @@ -77,14 +76,14 @@ void setUp() { @DisplayName("properly converts node with mapping") @ParameterizedTest(name = "{0}") @MethodSource - void e2e(final Mapping mapping, final RDFNode original, final Object expected) { + void e2e(final ValueMapping valueMapping, final RDFNode original, final Object expected) { final org.apache.jena.rdf.model.Property p = m.createProperty(P); final org.apache.jena.rdf.model.Resource c = m.createResource(C); final Matcher isExpected; final RDFNode o; - if (mapping == AS) { + if (valueMapping == AS) { o = m.createResource().addProperty(p, (String) expected); // Complex properties need a bit more setup isExpected = hasProperty(LITERAL_AS_STRING.getMethodName(), equalTo(expected)); // and matcher } else { @@ -96,7 +95,7 @@ void e2e(final Mapping mapping, final RDFNode original, final Object expected) { .addProperty(type, c) // anchor for graph definition .addProperty(p, o); // what's being wrapped - assertThat(wrapped.getResource(), hasProperty(mapping.getMethodName(), isExpected)); + assertThat(wrapped.getResource(), hasProperty(valueMapping.getMethodName(), isExpected)); } private static Stream e2e() { @@ -138,25 +137,25 @@ private static Stream valueMappingsMethods() { @Resource interface ResourceDefinition { - @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_STRING) + @Property(predicate = P, valueMapping = LITERAL_AS_STRING) String getLiteralAsString(); - @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = IRI_AS_URI) + @Property(predicate = P, valueMapping = IRI_AS_URI) URI getIriAsUri(); - @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) + @Property(predicate = P, valueMapping = IRI_AS_STRING) String getIriAsString(); - @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_INSTANT) + @Property(predicate = P, valueMapping = LITERAL_AS_INSTANT) Instant getLiteralAsInstant(); - @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_BOOLEAN) + @Property(predicate = P, valueMapping = LITERAL_AS_BOOLEAN) Boolean getLiteralAsBoolean(); - @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = LITERAL_AS_INTEGER_OR_NULL) + @Property(predicate = P, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Integer getLiteralAsIntegerOrNull(); - @Property(predicate = P, cardinality = ANY_OR_NULL, mapping = AS) + @Property(predicate = P) ResourceDefinition getAs(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java b/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java index 8caced0a9..593e5539f 100644 --- a/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java +++ b/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java @@ -1,14 +1,11 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; - import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = AS) + @Property(predicate = "x") Object x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java b/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java index 7178147bc..adce667ad 100644 --- a/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java +++ b/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java @@ -1,14 +1,11 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; - import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = AS) + @Property(predicate = "x") void x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java index 486ec369d..76c2ed1d7 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java @@ -2,13 +2,13 @@ package x; import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECT_ITERATOR; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", cardinality = OBJECT_ITERATOR, mapping = IRI_AS_STRING) + @Property(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) String x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java index bfc55364a..1e33882da 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java @@ -2,13 +2,13 @@ package x; import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECTS_READ_ONLY; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", cardinality = OBJECTS_READ_ONLY, mapping = IRI_AS_STRING) + @Property(predicate = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) Iterable x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java index d23f1f245..dcd416b15 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java @@ -2,7 +2,7 @@ package x; import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECT_ITERATOR; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @@ -11,6 +11,6 @@ @Resource interface X { - @Property(predicate = "x", cardinality = OBJECT_ITERATOR, mapping = IRI_AS_STRING) + @Property(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) Iterator x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java index 3ecdcb842..b38ffa2a2 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java @@ -2,7 +2,7 @@ package x; import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECTS_READ_ONLY; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @@ -11,6 +11,6 @@ @Resource interface X { - @Property(predicate = "x", cardinality = OBJECTS_READ_ONLY, mapping = IRI_AS_STRING) + @Property(predicate = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) Set x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is default.java b/processor/src/test/resources/validationExamples/bad/resource property method is default.java index 19a763cf5..d70768911 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is default.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is default.java @@ -1,15 +1,14 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) + @Property(predicate = "x", valueMapping = IRI_AS_STRING) default Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is static.java b/processor/src/test/resources/validationExamples/bad/resource property method is static.java index 57fdd3c2a..da700c823 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is static.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is static.java @@ -1,15 +1,14 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) + @Property(predicate = "x", valueMapping = IRI_AS_STRING) static Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is void.java b/processor/src/test/resources/validationExamples/bad/resource property method is void.java index a12ea4f97..1e390ed85 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is void.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is void.java @@ -1,14 +1,13 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) + @Property(predicate = "x", valueMapping = IRI_AS_STRING) void x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java b/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java index bcf319575..d6c6fbd6d 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java @@ -1,14 +1,13 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) + @Property(predicate = "x", valueMapping = IRI_AS_STRING) int x(); } diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java b/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java index f1f59e2f9..ae554dd72 100644 --- a/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java +++ b/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java @@ -1,14 +1,11 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; - import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = AS) + @Property(predicate = "x") X x(); } diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java index 57b2aeed0..dfb14d257 100644 --- a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java +++ b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java @@ -1,9 +1,6 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.AS; - import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; import com.inrupt.rdf.wrapping.annotation.Property; @@ -16,7 +13,7 @@ interface X { @Resource interface Y { - @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = AS) + @Property(predicate = "x") Y x(); } } diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method.java b/processor/src/test/resources/validationExamples/good/resource plural property method.java index 3391c62aa..3930e5122 100644 --- a/processor/src/test/resources/validationExamples/good/resource plural property method.java +++ b/processor/src/test/resources/validationExamples/good/resource plural property method.java @@ -2,7 +2,7 @@ package x; import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECT_ITERATOR; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @@ -11,6 +11,6 @@ @Resource interface X { - @Property(predicate = "x", cardinality = OBJECT_ITERATOR, mapping = IRI_AS_STRING) + @Property(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) Iterator x(); } diff --git a/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java b/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java index b38045f84..ac8307e45 100644 --- a/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java +++ b/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java @@ -1,14 +1,13 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.Mapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @Resource interface X { - @Property(predicate = "x", cardinality = ANY_OR_NULL, mapping = IRI_AS_STRING) + @Property(predicate = "x", valueMapping = IRI_AS_STRING) Object x(); } From dda90399c1e9e62c669f104d6e974d9499d7d738 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 9 Mar 2024 18:40:31 +0000 Subject: [PATCH 111/141] Overhaul definitions, extract resource property --- .../wrapping/processor/DatasetDefinition.java | 7 +- .../rdf/wrapping/processor/Definition.java | 30 ++++---- .../wrapping/processor/GraphDefinition.java | 5 +- .../rdf/wrapping/processor/Implementor.java | 19 ++++- .../rdf/wrapping/processor/Processor.java | 2 +- .../processor/ResourceDefinition.java | 56 +++++++------- .../processor/ResourceImplementor.java | 47 +++++------- .../processor/ResourcePropertyDefinition.java | 76 +++++++++++++++++++ .../wrapping/processor/ResourceValidator.java | 64 +++++++--------- .../rdf/wrapping/processor/Validator.java | 33 ++++---- .../wrapping/processor/ImplementorTest.java | 2 +- 11 files changed, 210 insertions(+), 131 deletions(-) create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java index 6d1c08ba1..66b760418 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; +import com.inrupt.rdf.wrapping.annotation.Dataset; import com.inrupt.rdf.wrapping.annotation.DefaultGraph; import com.inrupt.rdf.wrapping.annotation.NamedGraph; @@ -28,9 +29,9 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; -class DatasetDefinition extends Definition { - DatasetDefinition(final TypeElement type, final Environment env) { - super(type, env); +class DatasetDefinition extends Definition { + DatasetDefinition(final TypeElement element, final Environment env) { + super(element, env, Dataset.class); } Stream defaultGraphMethods() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java index b7b284605..c7841908e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java @@ -20,7 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static javax.lang.model.element.Modifier.STATIC; import static javax.lang.model.type.TypeKind.VOID; import com.inrupt.rdf.wrapping.annotation.Dataset; @@ -30,6 +29,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; +import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; @@ -37,18 +37,20 @@ import org.jboss.jdeparser.JType; import org.jboss.jdeparser.JTypes; -class Definition { +class Definition { static final Predicate isVoid = method -> method.getReturnType().getKind() == VOID; - private final TypeElement type; - private final Environment env; + protected final T element; + protected final Environment env; + private final Class clazz; - Definition(final TypeElement type, final Environment env) { + Definition(final T element, final Environment env, final Class clazz) { + this.element = element; this.env = env; - this.type = type; + this.clazz = clazz; } - static Definition definition(final TypeElement type, final Environment env) { + static Definition definition(final TypeElement type, final Environment env) { if (type.getAnnotation(Dataset.class) != null) { return new DatasetDefinition(type, env); @@ -69,8 +71,8 @@ TypeElement returnTypeOf(final ExecutableElement method) { return typeOf(method.getReturnType()); } - protected TypeElement getType() { - return type; + protected T getElement() { + return element; } protected Environment getEnv() { @@ -78,13 +80,15 @@ protected Environment getEnv() { } protected JType getOriginalInterface() { - return JTypes.typeOf(getType().asType()); + return JTypes.typeOf(element.asType()); } protected Stream membersAnnotatedWith(final Class annotation) { - return getEnv().methodsOf(getType()) - .filter(method -> !method.isDefault()) - .filter(method -> !method.getModifiers().contains(STATIC)) + return env.methodsOf(element) .filter(method -> method.getAnnotation(annotation) != null); } + + U annotation() { + return element.getAnnotation(clazz); + } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java index 3d803a159..1247f4cd7 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java @@ -22,6 +22,7 @@ import static java.util.stream.Stream.concat; +import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; @@ -32,9 +33,9 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -class GraphDefinition extends Definition { +class GraphDefinition extends Definition { GraphDefinition(final TypeElement type, final Environment env) { - super(type, env); + super(type, env, Graph.class); } Stream transitiveResourceTypes() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index c8a3d3735..891899b43 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -28,13 +28,14 @@ import java.time.Instant; import javax.annotation.Generated; +import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; import org.jboss.jdeparser.*; -abstract class Implementor { +abstract class Implementor> { protected static final String ORIGINAL = "original"; static final String WRAP = "wrap"; @@ -46,7 +47,7 @@ abstract class Implementor { protected Implementor(final T definition) { this.definition = definition; - final TypeElement type = definition.getType(); + final Element type = definition.getElement(); final Environment env = definition.getEnv(); final String packageName = env.getElementUtils().getPackageOf(type).getQualifiedName().toString(); @@ -66,7 +67,7 @@ void implement() { } } - static Implementor implementor(final Definition definition) { + static Implementor implementor(final Definition definition) { if (definition instanceof DatasetDefinition) { return new DatasetImplementor((DatasetDefinition) definition); @@ -104,6 +105,16 @@ protected JMethodDef addMethod(final ExecutableElement method) { return myMethod; } + protected JMethodDef addMethod(final Definition d) { + final String myName = d.element.getSimpleName().toString(); + final JType myType = typeOf(d.element.getReturnType()); + + final JMethodDef myMethod = target.method(PUBLIC, myType, myName); + myMethod.annotate(Override.class); + + return myMethod; + } + protected JType asImplementation(final TypeMirror original) { final TypeElement returnType = definition.typeOf(original); final String originalBinaryName = binaryName(returnType); @@ -112,7 +123,7 @@ protected JType asImplementation(final TypeMirror original) { } private String getImplementationClass() { - final String originalBinaryName = binaryName(definition.getType()); + final String originalBinaryName = binaryName((TypeElement) definition.getElement()); final String qualifiedName = asImplementation(originalBinaryName); final int lastDot = originalBinaryName.lastIndexOf('.'); return qualifiedName.substring(lastDot + 1); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java index ab7b6c688..e620751c0 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java @@ -65,7 +65,7 @@ public boolean process(final Set annotations, final Round // All our annotations are @Target(TYPE), so they're all TypeElements final TypeElement type = (TypeElement) element; - final Definition definition = definition(type, env); + final Definition definition = definition(type, env); implementors.add(implementor(definition)); validationErrors.addAll(validator(definition).validate()); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index 42ed4cac3..3ba5b5619 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -22,6 +22,7 @@ import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.AS; import static com.inrupt.rdf.wrapping.processor.PredicateShim.not; +import static javax.lang.model.type.TypeKind.VOID; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @@ -33,57 +34,54 @@ import java.util.function.Predicate; import java.util.stream.Stream; -import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -class ResourceDefinition extends Definition { - private static final Predicate isComplex = method -> - method.getAnnotation(Property.class).valueMapping() == AS; - private static final Predicate isPlural = method -> - method.getAnnotation(Property.class).cardinality().isPlural(); - private final Predicate returnsResource = method -> - getEnv().type(method.getReturnType()).getAnnotation(Resource.class) != null; - static final Predicate isSetter = method -> - method.getAnnotation(Property.class).cardinality().isSetter(); - - ResourceDefinition(final TypeElement type, final Environment env) { - super(type, env); +class ResourceDefinition extends Definition { + private static final Predicate isComplex = p -> p.valueMapping() == AS; + private static final Predicate isPlural = p -> p.cardinality().isPlural(); + private final Predicate returnsResource = p -> + getEnv().type(p.getReturnType()).getAnnotation(Resource.class) != null; + static final Predicate isSetter = p -> p.cardinality().isSetter(); + static final Predicate isVoid = p -> p.getReturnType().getKind() == VOID; + + ResourceDefinition(final TypeElement element, final Environment env) { + super(element, env, Resource.class); } - Stream primitivePropertyMethods() { - return membersAnnotatedWith(Property.class) + Stream primitiveProperties() { + return properties() .filter(not(isSetter)) .filter(not(returnsResource)); } - Stream resourcePropertyMethods() { - return membersAnnotatedWith(Property.class) + Stream resourceProperties() { + return properties() .filter(not(isSetter)) .filter(returnsResource); } - Stream complexMappingPropertyMethods() { - return membersAnnotatedWith(Property.class) + Stream complexMappingProperties() { + return properties() .filter(isComplex) .filter(not(isPlural)) .filter(not(isVoid)); } - Stream setterPropertyMethods() { - return membersAnnotatedWith(Property.class) + Stream setterProperties() { + return properties() .filter(isSetter); } - Stream primitiveMappingPropertyMethods() { - return membersAnnotatedWith(Property.class) + Stream primitiveMappingProperties() { + return properties() .filter(not(isComplex)) .filter(not(isPlural)) .filter(not(isVoid)); } - Stream pluralPropertyMethods() { - return membersAnnotatedWith(Property.class) + Stream pluralProperties() { + return properties() .filter(isPlural); } @@ -93,8 +91,8 @@ Stream transitiveResourceTypes() { ResourceDefinition current = this; while (true) { - current.resourcePropertyMethods() - .map(ExecutableElement::getReturnType) + current.resourceProperties() + .map(ResourcePropertyDefinition::getReturnType) .filter(results::add) .forEach(outstanding::add); @@ -114,4 +112,8 @@ private ResourceDefinition dequeue(final Queue outstanding) { return new ResourceDefinition(nextType, getEnv()); } + + Stream properties() { + return membersAnnotatedWith(Property.class).map(e -> new ResourcePropertyDefinition(e, env)); + } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 0c87072b6..c00235e8f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -24,15 +24,12 @@ import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.jena.NodeMappings; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; import com.inrupt.rdf.wrapping.jena.ValueMappings; import com.inrupt.rdf.wrapping.jena.WrapperResource; import javax.annotation.Generated; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.VariableElement; import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.graph.Node; @@ -91,20 +88,19 @@ private void addConstructor() { } private void addPrimitivePropertyMethods() { - definition.primitivePropertyMethods().forEach(method -> { - final String mappingMethodName = method.getAnnotation(Property.class).valueMapping().getMethodName(); - final JExpr mapping = $t(ValueMappings.class).methodRef(mappingMethodName); + definition.primitiveProperties().forEach(p -> { + final JExpr mapping = $t(ValueMappings.class).methodRef(p.valueMappingMethod()); - addPropertyMethod(method, mapping); + addPropertyMethod(p, mapping); }); } private void addResourcePropertyMethods() { - definition.resourcePropertyMethods().forEach(method -> { - final JType implementation = asImplementation(method.getReturnType()); + definition.resourceProperties().forEach(p -> { + final JType implementation = asImplementation(p.getReturnType()); final JCall mapping = $t(ValueMappings.class).call("as").arg(implementation._class()); - addPropertyMethod(method, mapping); + addPropertyMethod(p, mapping); }); } @@ -112,28 +108,21 @@ private void addResourcePropertyMethods() { // TODO: Cover // TODO: Other mutators private void addOverwrite() { - definition.setterPropertyMethods().forEach(method -> { - final Property annotation = method.getAnnotation(Property.class); - final String predicateFromAnnotation = annotation.predicate(); - final String cardinality = annotation.cardinality().getMethodName(); - final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); - final JMethodDef m = addMethod(method); - - final String mappingMethodName = annotation.nodeMapping().getMethodName(); - final JExpr mapping = $t(NodeMappings.class).methodRef(mappingMethodName); - - final VariableElement variableElement = method.getParameters().get(0); - final JParamDeclaration value = m.param(FINAL, JTypes.typeOf(variableElement.asType()), "value"); - m.body().call(cardinality).arg(predicate).arg($v(value)).arg(mapping); + definition.setterProperties().forEach(p -> { + final JCall predicate = call("getModel").call("createProperty").arg(str(p.predicate())); + + final JExpr mapping = $t(NodeMappings.class).methodRef(p.nodeMappingMethod()); + + final JMethodDef m = addMethod(p); + final JParamDeclaration value = m.param(FINAL, JTypes.typeOf(p.getValueParamType()), "value"); + + m.body().call(p.cardinalityMethod()).arg(predicate).arg($v(value)).arg(mapping); }); } - private void addPropertyMethod(final ExecutableElement method, final JExpr mapping) { - final Property annotation = method.getAnnotation(Property.class); - final String predicateFromAnnotation = annotation.predicate(); - final String cardinality = annotation.cardinality().getMethodName(); - final JCall predicate = call("getModel").call("createProperty").arg(str(predicateFromAnnotation)); + private void addPropertyMethod(final ResourcePropertyDefinition p, final JExpr mapping) { + final JCall predicate = call("getModel").call("createProperty").arg(str(p.predicate())); - addMethod(method).body()._return(call(cardinality).arg(predicate).arg(mapping)); + addMethod(p).body()._return(call(p.cardinalityMethod()).arg(predicate).arg(mapping)); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java new file mode 100644 index 000000000..aefb698ba --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java @@ -0,0 +1,76 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import com.inrupt.rdf.wrapping.annotation.Property; +import com.inrupt.rdf.wrapping.annotation.Property.Cardinality; +import com.inrupt.rdf.wrapping.annotation.Property.NodeMapping; +import com.inrupt.rdf.wrapping.annotation.Property.ValueMapping; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Name; +import javax.lang.model.type.TypeMirror; + +class ResourcePropertyDefinition extends Definition { + ResourcePropertyDefinition(final ExecutableElement element, final Environment env) { + super(element, env, Property.class); + } + + String predicate() { + return annotation().predicate(); + } + + Cardinality cardinality() { + return annotation().cardinality(); + } + + String cardinalityMethod() { + return annotation().cardinality().getMethodName(); + } + + ValueMapping valueMapping() { + return annotation().valueMapping(); + } + + String valueMappingMethod() { + return annotation().valueMapping().getMethodName(); + } + + NodeMapping nodeMapping() { + return annotation().nodeMapping(); + } + + String nodeMappingMethod() { + return annotation().nodeMapping().getMethodName(); + } + + TypeMirror getReturnType() { + return element.getReturnType(); + } + + Name getName() { + return element.getSimpleName(); + } + + TypeMirror getValueParamType() { + return element.getParameters().get(0).asType(); + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index aecc6dc2d..ec81202de 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -20,9 +20,9 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.processor.Definition.isVoid; import static com.inrupt.rdf.wrapping.processor.PredicateShim.not; import static com.inrupt.rdf.wrapping.processor.ResourceDefinition.isSetter; +import static com.inrupt.rdf.wrapping.processor.ResourceDefinition.isVoid; import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; @@ -66,60 +66,55 @@ protected void validateInternal() { } private void requireNonVoidReturnType() { - definition.membersAnnotatedWith(Property.class) + definition.properties() .filter(not(isSetter)) .filter(isVoid) .forEach(method -> errors.add(new ValidationError( - method, + method.element, "Method [%s] must not be void", - method.getSimpleName()))); + method.getName()))); } private void requireCompatiblePrimitiveReturnType() { - definition.primitiveMappingPropertyMethods().forEach(method -> { - final TypeMirror thisReturn = method.getReturnType(); + definition.primitiveMappingProperties().forEach(p -> { + final TypeMirror mappingReturn = returnTypeOf(p.valueMappingMethod(), ValueMappings.class); - final String mappingMethod = method.getAnnotation(Property.class).valueMapping().getMethodName(); - final TypeMirror mappingReturn = returnTypeOf(mappingMethod, ValueMappings.class); - - if (definition.getEnv().getTypeUtils().isAssignable(mappingReturn, thisReturn)) { + if (definition.getEnv().getTypeUtils().isAssignable(mappingReturn, p.getReturnType())) { return; } errors.add(new ValidationError( - method, + p.element, "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", - thisReturn, - method.getSimpleName(), + p.getReturnType(), + p.getName(), mappingReturn, - mappingMethod)); + p.valueMappingMethod())); }); } private void requireCompatibleComplexReturnType() { - definition.complexMappingPropertyMethods().forEach(method -> { - final TypeElement returnType = definition.returnTypeOf(method); + definition.complexMappingProperties().forEach(p -> { + final TypeElement returnType = definition.returnTypeOf(p.element); if (returnType != null && returnType.getAnnotation(Resource.class) != null) { return; } errors.add(new ValidationError( - method, + p.element, "Method %s on interface %s must return @Resource interface", - method.getSimpleName(), - definition.getType().getSimpleName())); + p.getName(), + definition.getElement().getSimpleName())); }); } private void requirePluralErasure() { - definition.pluralPropertyMethods().forEach(method -> { - final TypeMirror thisReturn = method.getReturnType(); - final TypeMirror thisErasure = definition.getEnv().getTypeUtils().erasure(thisReturn); + definition.pluralProperties().forEach(p -> { + final TypeMirror thisErasure = definition.getEnv().getTypeUtils().erasure(p.getReturnType()); - final String cardinalityMethod = method.getAnnotation(Property.class).cardinality().getMethodName(); - final TypeMirror cardinalityReturn = returnTypeOf(cardinalityMethod, WrapperResource.class); + final TypeMirror cardinalityReturn = returnTypeOf(p.cardinalityMethod(), WrapperResource.class); final TypeMirror cardinalityErasure = definition.getEnv().getTypeUtils().erasure(cardinalityReturn); @@ -129,19 +124,19 @@ private void requirePluralErasure() { } errors.add(new ValidationError( - method, + p.element, "Return type [%s] of [%s] must have same erasure as return type [%s] of cardinality [%s]", - thisReturn, - method.getSimpleName(), + p.getReturnType(), + p.getName(), cardinalityReturn, - cardinalityMethod)); + p.cardinalityMethod())); }); } // TODO: Check bounds of type parameters e.g. String & CharSequence private void requirePluralTypeArgument() { - definition.pluralPropertyMethods().forEach(method -> { - final DeclaredType thisReturn = (DeclaredType) method.getReturnType(); + definition.pluralProperties().forEach(p -> { + final DeclaredType thisReturn = (DeclaredType) p.getReturnType(); final TypeMirror thisErasure = definition.getEnv().getTypeUtils().erasure(thisReturn); if (definition.getEnv().isSameType(thisErasure, thisReturn)) { @@ -149,8 +144,7 @@ private void requirePluralTypeArgument() { return; } - final String mappingMethod = method.getAnnotation(Property.class).valueMapping().getMethodName(); - final TypeMirror mappingReturn = returnTypeOf(mappingMethod, ValueMappings.class); + final TypeMirror mappingReturn = returnTypeOf(p.valueMappingMethod(), ValueMappings.class); final List mappingTypeArguments = new ArrayList<>(); mappingTypeArguments.add(definition.typeOf(mappingReturn)); @@ -164,12 +158,12 @@ private void requirePluralTypeArgument() { } errors.add(new ValidationError( - method, + p.element, "Return type [%s] of [%s] must have same type argument as return type [%s] of mapping [%s]", thisReturn, - method.getSimpleName(), + p.getName(), mappingReturn, - mappingMethod)); + p.valueMappingMethod())); }); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index f73748bec..624f80957 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -31,9 +31,10 @@ import java.util.function.Predicate; import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -abstract class Validator { +abstract class Validator> { protected final T definition; protected final Collection errors = new ArrayList<>(); @@ -41,7 +42,7 @@ protected Validator(final T definition) { this.definition = definition; } - static Validator validator(final Definition definition) { + static Validator validator(final Definition definition) { if (definition instanceof DatasetDefinition) { return new DatasetValidator((DatasetDefinition) definition); @@ -68,14 +69,14 @@ protected void requireMemberMethods(final Class annotation final Predicate isAnnotated = method -> method.getAnnotation(annotation) != null; - definition.getEnv().methodsOf(definition.getType()) + definition.getEnv().methodsOf(definition.getElement()) .filter(isNotMember) .filter(isAnnotated) .forEach(method -> errors.add(new ValidationError( method, "Method %s on interface %s annotated with @%s cannot be static or default", method.getSimpleName(), - definition.getType().getSimpleName(), + definition.getElement().getSimpleName(), annotation.getSimpleName()))); } @@ -87,44 +88,44 @@ protected final void requireNonMemberMethods(final Class.. final Predicate isUnannotated = method -> Arrays.stream(annotations).noneMatch(a -> method.getAnnotation(a) != null); - definition.getEnv().methodsOf(definition.getType()) + definition.getEnv().methodsOf(definition.getElement()) .filter(isMember) .filter(isUnannotated) .forEach(method -> errors.add(new ValidationError( method, "Unannotated method %s on interface %s must be static or default", method.getSimpleName(), - definition.getType().getSimpleName()))); + definition.getElement().getSimpleName()))); } protected void limitBaseInterfaces(final Class allowed) { - if (!definition.getType().getKind().isInterface()) { + if (!definition.getElement().getKind().isInterface()) { return; } - for (final TypeMirror implemented : definition.getType().getInterfaces()) { + for (final TypeMirror implemented : ((TypeElement) definition.getElement()).getInterfaces()) { if (definition.getEnv().isSameType(implemented, allowed)) { continue; } errors.add(new ValidationError( - definition.getType(), + definition.getElement(), "Interface %s can only extend %s or nothing", - definition.getType().getSimpleName(), + definition.getElement().getSimpleName(), allowed.getName())); } } protected void requireInterface() { - if (definition.getType().getKind().isInterface()) { + if (definition.getElement().getKind().isInterface()) { return; } errors.add(new ValidationError( - definition.getType(), + definition.getElement(), "Element %s must be an interface but was a %s", - definition.getType().getSimpleName(), - definition.getType().getKind())); + definition.getElement().getSimpleName(), + definition.getElement().getKind())); } protected void requireAnnotatedReturnType( @@ -135,7 +136,7 @@ protected void requireAnnotatedReturnType( final Predicate isResource = method -> definition.returnTypeOf(method).getAnnotation(required) != null; - definition.getEnv().methodsOf(definition.getType()) + definition.getEnv().methodsOf(definition.getElement()) .filter(not(isVoid)) .filter(isAnnotated) .filter(not(isResource)) @@ -143,7 +144,7 @@ protected void requireAnnotatedReturnType( method, "Method %s on interface %s annotated with @%s must return @%s interface", method.getSimpleName(), - definition.getType().getSimpleName(), + definition.getElement().getSimpleName(), annotation.getSimpleName(), required.getSimpleName()))); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java index ef9d3d05b..5e9bea7e1 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java @@ -51,7 +51,7 @@ void failsToWrite() throws IOException { final Name name = mock(Name.class); final PackageElement packageElement = mock(PackageElement.class); final Filer filer = mock(Filer.class); - when(definition.getType()).thenReturn(type); + when(definition.getElement()).thenReturn(type); when(definition.getEnv()).thenReturn(env); when(elementUtils.getBinaryName(any())).thenReturn(name); From f3369b00e9c7645c3208ed1e7aa887b59f12fbc6 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 9 Mar 2024 19:27:03 +0000 Subject: [PATCH 112/141] Unify dataset properties Extract dataset property definition --- ...DefaultGraph.java => DatasetProperty.java} | 3 +- .../{Property.java => ResourceProperty.java} | 8 ++--- .../wrapping/annotation/CardinalityTest.java | 2 +- .../wrapping/annotation/NodeMappingTest.java | 2 +- .../wrapping/annotation/ValueMappingTest.java | 2 +- .../wrapping/processor/DatasetDefinition.java | 12 ++----- .../processor/DatasetImplementor.java | 28 ++++++--------- .../processor/DatasetPropertyDefinition.java | 22 ++++++------ .../wrapping/processor/DatasetValidator.java | 14 +++----- .../processor/PropertyDefinition.java | 36 +++++++++++++++++++ .../processor/ResourceDefinition.java | 6 ++-- .../processor/ResourcePropertyDefinition.java | 22 +++++------- .../wrapping/processor/ResourceValidator.java | 6 ++-- .../rdf/wrapping/processor/E2ETest.java | 22 ++++++------ .../ResourceDefinitionCardinalityTest.java | 26 +++++++------- .../ResourceDefinitionValueMappingTest.java | 24 ++++++------- .../rdf/wrapping/processor/ValidatorTest.java | 5 --- ...taset default graph method is default.java | 13 ------- ...set default graph method is not graph.java | 11 ------ ...ataset default graph method is static.java | 13 ------- .../dataset default graph method is void.java | 12 ------- ...dataset named graph method is default.java | 4 +-- ...taset named graph method is not graph.java | 4 +-- .../dataset named graph method is static.java | 4 +-- .../dataset named graph method is void.java | 4 +-- ...mplex property method is not resource.java | 4 +-- ...ource complex property method is void.java | 4 +-- ...lural property method erasure differs.java | 8 ++--- ... plural property method erasure super.java | 8 ++--- ...property method type argument differs.java | 8 ++--- ...l property method type argument super.java | 8 ++--- .../resource property method is default.java | 6 ++-- .../resource property method is static.java | 6 ++-- .../bad/resource property method is void.java | 6 ++-- ...rty method return type not assignable.java | 6 ++-- ...efault graph method is graph instance.java | 16 --------- ... named graph method is graph instance.java | 4 +-- ... property method is resource instance.java | 4 +-- ...rce complex property method recursive.java | 4 +-- .../good/resource plural property method.java | 8 ++--- ...roperty method is assignable instance.java | 6 ++-- 41 files changed, 179 insertions(+), 232 deletions(-) rename annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/{DefaultGraph.java => DatasetProperty.java} (95%) rename annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/{Property.java => ResourceProperty.java} (92%) rename annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java => processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetPropertyDefinition.java (71%) create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/PropertyDefinition.java delete mode 100644 processor/src/test/resources/validationExamples/bad/dataset default graph method is default.java delete mode 100644 processor/src/test/resources/validationExamples/bad/dataset default graph method is not graph.java delete mode 100644 processor/src/test/resources/validationExamples/bad/dataset default graph method is static.java delete mode 100644 processor/src/test/resources/validationExamples/bad/dataset default graph method is void.java delete mode 100644 processor/src/test/resources/validationExamples/good/dataset default graph method is graph instance.java diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DatasetProperty.java similarity index 95% rename from annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DatasetProperty.java index b4996ae7e..ae56c4585 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DefaultGraph.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/DatasetProperty.java @@ -30,5 +30,6 @@ @Target(METHOD) @Retention(RUNTIME) @Documented -public @interface DefaultGraph { +public @interface DatasetProperty { + String value() default ""; } diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java similarity index 92% rename from annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java index 2c7facf52..53217ffc5 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/Property.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java @@ -20,9 +20,9 @@ */ package com.inrupt.rdf.wrapping.annotation; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.ANY_OR_NULL; -import static com.inrupt.rdf.wrapping.annotation.Property.NodeMapping.IDENTITY; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.AS; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.ANY_OR_NULL; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.NodeMapping.IDENTITY; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.AS; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -33,7 +33,7 @@ @Target(METHOD) @Retention(RUNTIME) @Documented -public @interface Property { +public @interface ResourceProperty { String predicate(); Cardinality cardinality() default ANY_OR_NULL; diff --git a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java index a51ad7ea2..a1b191ba3 100644 --- a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java +++ b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/CardinalityTest.java @@ -27,7 +27,7 @@ import static org.hamcrest.Matchers.describedAs; import static org.hamcrest.Matchers.in; -import com.inrupt.rdf.wrapping.annotation.Property.Cardinality; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality; import com.inrupt.rdf.wrapping.jena.WrapperResource; import java.lang.reflect.Method; diff --git a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/NodeMappingTest.java b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/NodeMappingTest.java index 9ee914615..f473d0485 100644 --- a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/NodeMappingTest.java +++ b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/NodeMappingTest.java @@ -27,7 +27,7 @@ import static org.hamcrest.Matchers.describedAs; import static org.hamcrest.Matchers.in; -import com.inrupt.rdf.wrapping.annotation.Property.NodeMapping; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty.NodeMapping; import com.inrupt.rdf.wrapping.jena.NodeMappings; import java.lang.reflect.Method; diff --git a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/ValueMappingTest.java b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/ValueMappingTest.java index 0aa0f27c2..0a34a2671 100644 --- a/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/ValueMappingTest.java +++ b/annotation/src/test/java/com/inrupt/rdf/wrapping/annotation/ValueMappingTest.java @@ -27,7 +27,7 @@ import static org.hamcrest.Matchers.describedAs; import static org.hamcrest.Matchers.in; -import com.inrupt.rdf.wrapping.annotation.Property.ValueMapping; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping; import com.inrupt.rdf.wrapping.jena.ValueMappings; import java.lang.reflect.Method; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java index 66b760418..7895eaabb 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java @@ -21,12 +21,10 @@ package com.inrupt.rdf.wrapping.processor; import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.DefaultGraph; -import com.inrupt.rdf.wrapping.annotation.NamedGraph; +import com.inrupt.rdf.wrapping.annotation.DatasetProperty; import java.util.stream.Stream; -import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; class DatasetDefinition extends Definition { @@ -34,11 +32,7 @@ class DatasetDefinition extends Definition { super(element, env, Dataset.class); } - Stream defaultGraphMethods() { - return membersAnnotatedWith(DefaultGraph.class); - } - - Stream namedGraphMethods() { - return membersAnnotatedWith(NamedGraph.class); + Stream properties() { + return membersAnnotatedWith(DatasetProperty.class).map(m -> new DatasetPropertyDefinition(m, env)); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index c20d73611..31504577c 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -24,10 +24,7 @@ import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; -import com.inrupt.rdf.wrapping.annotation.NamedGraph; - import javax.annotation.Generated; -import javax.lang.model.element.ExecutableElement; import org.apache.jena.query.Dataset; import org.apache.jena.sparql.core.DatasetGraph; @@ -47,8 +44,7 @@ protected void implementInternal() { addClass(); addConstructor(); addWrap(); - addDefaultGraphs(); - addNamedGraphs(); + addGraphs(); } private void addImports() { @@ -75,21 +71,19 @@ private void addWrap() { myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("asDatasetGraph"))); } - private void addDefaultGraphs() { - definition.defaultGraphMethods().forEach(method -> addGraph(method, call("getDefaultModel"))); - } - - private void addNamedGraphs() { - definition.namedGraphMethods().forEach(method -> { - final String graph = method.getAnnotation(NamedGraph.class).value(); - - addGraph(method, call("getNamedModel").arg(str(graph))); + private void addGraphs() { + definition.properties().forEach(p -> { + if (p.graphName().isEmpty()) { + addGraph(p, call("getDefaultModel")); + } else { + addGraph(p, call("getNamedModel").arg(str(p.graphName()))); + } }); } - private void addGraph(final ExecutableElement method, final JExpr expr) { - final JType implementation = asImplementation(method.getReturnType()); + private void addGraph(final DatasetPropertyDefinition d, final JExpr expr) { + final JType implementation = asImplementation(d.getReturnType()); - addMethod(method).body()._return(implementation.call(WRAP).arg(expr)); + addMethod(d).body()._return(implementation.call(WRAP).arg(expr)); } } diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetPropertyDefinition.java similarity index 71% rename from annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetPropertyDefinition.java index f4ad8fd3a..7cd5c7df5 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/NamedGraph.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetPropertyDefinition.java @@ -18,18 +18,18 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.annotation; +package com.inrupt.rdf.wrapping.processor; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; +import com.inrupt.rdf.wrapping.annotation.DatasetProperty; -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; +import javax.lang.model.element.ExecutableElement; -@Target(METHOD) -@Retention(RUNTIME) -@Documented -public @interface NamedGraph { - String value(); +class DatasetPropertyDefinition extends PropertyDefinition { + DatasetPropertyDefinition(final ExecutableElement element, final Environment env) { + super(element, env, DatasetProperty.class); + } + + String graphName() { + return annotation().value(); + } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java index faec10599..c808837c0 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetValidator.java @@ -20,9 +20,8 @@ */ package com.inrupt.rdf.wrapping.processor; -import com.inrupt.rdf.wrapping.annotation.DefaultGraph; +import com.inrupt.rdf.wrapping.annotation.DatasetProperty; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.NamedGraph; import org.apache.jena.query.Dataset; @@ -37,15 +36,12 @@ protected void validateInternal() { limitBaseInterfaces(Dataset.class); - requireMemberMethods(DefaultGraph.class); - requireMemberMethods(NamedGraph.class); + requireMemberMethods(DatasetProperty.class); - requireNonMemberMethods(DefaultGraph.class, NamedGraph.class); + requireNonMemberMethods(DatasetProperty.class); - requireNonVoidReturnType(DefaultGraph.class); - requireNonVoidReturnType(NamedGraph.class); + requireNonVoidReturnType(DatasetProperty.class); - requireAnnotatedReturnType(DefaultGraph.class, Graph.class); - requireAnnotatedReturnType(NamedGraph.class, Graph.class); + requireAnnotatedReturnType(DatasetProperty.class, Graph.class); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/PropertyDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/PropertyDefinition.java new file mode 100644 index 000000000..0daaa5a83 --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/PropertyDefinition.java @@ -0,0 +1,36 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +import java.lang.annotation.Annotation; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.type.TypeMirror; + +abstract class PropertyDefinition extends Definition { + PropertyDefinition(final ExecutableElement element, final Environment env, final Class clazz) { + super(element, env, clazz); + } + + TypeMirror getReturnType() { + return element.getReturnType(); + } +} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index 3ba5b5619..3bcc9be0a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -20,12 +20,12 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.AS; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.AS; import static com.inrupt.rdf.wrapping.processor.PredicateShim.not; import static javax.lang.model.type.TypeKind.VOID; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; import java.util.HashSet; import java.util.LinkedList; @@ -114,6 +114,6 @@ private ResourceDefinition dequeue(final Queue outstanding) { } Stream properties() { - return membersAnnotatedWith(Property.class).map(e -> new ResourcePropertyDefinition(e, env)); + return membersAnnotatedWith(ResourceProperty.class).map(e -> new ResourcePropertyDefinition(e, env)); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java index aefb698ba..cb31c2ec4 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java @@ -20,18 +20,18 @@ */ package com.inrupt.rdf.wrapping.processor; -import com.inrupt.rdf.wrapping.annotation.Property; -import com.inrupt.rdf.wrapping.annotation.Property.Cardinality; -import com.inrupt.rdf.wrapping.annotation.Property.NodeMapping; -import com.inrupt.rdf.wrapping.annotation.Property.ValueMapping; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty.NodeMapping; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Name; import javax.lang.model.type.TypeMirror; -class ResourcePropertyDefinition extends Definition { +class ResourcePropertyDefinition extends PropertyDefinition { ResourcePropertyDefinition(final ExecutableElement element, final Environment env) { - super(element, env, Property.class); + super(element, env, ResourceProperty.class); } String predicate() { @@ -43,7 +43,7 @@ Cardinality cardinality() { } String cardinalityMethod() { - return annotation().cardinality().getMethodName(); + return cardinality().getMethodName(); } ValueMapping valueMapping() { @@ -51,7 +51,7 @@ ValueMapping valueMapping() { } String valueMappingMethod() { - return annotation().valueMapping().getMethodName(); + return valueMapping().getMethodName(); } NodeMapping nodeMapping() { @@ -59,11 +59,7 @@ NodeMapping nodeMapping() { } String nodeMappingMethod() { - return annotation().nodeMapping().getMethodName(); - } - - TypeMirror getReturnType() { - return element.getReturnType(); + return nodeMapping().getMethodName(); } Name getName() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index ec81202de..14c41051f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -24,8 +24,8 @@ import static com.inrupt.rdf.wrapping.processor.ResourceDefinition.isSetter; import static com.inrupt.rdf.wrapping.processor.ResourceDefinition.isVoid; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; import com.inrupt.rdf.wrapping.jena.ValueMappings; import com.inrupt.rdf.wrapping.jena.WrapperResource; @@ -53,9 +53,9 @@ protected void validateInternal() { // dataset and graph definitions as well limitBaseInterfaces(org.apache.jena.rdf.model.Resource.class); - requireMemberMethods(Property.class); + requireMemberMethods(ResourceProperty.class); - requireNonMemberMethods(Property.class); + requireNonMemberMethods(ResourceProperty.class); requireNonVoidReturnType(); requireCompatiblePrimitiveReturnType(); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index bb8f42625..982de3aa9 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -21,9 +21,9 @@ package com.inrupt.rdf.wrapping.processor; import static com.github.jsonldjava.shaded.com.google.common.base.Charsets.UTF_8; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.*; -import static com.inrupt.rdf.wrapping.annotation.Property.NodeMapping.AS_TYPED_LITERAL; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.*; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.*; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.NodeMapping.AS_TYPED_LITERAL; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.*; import static com.inrupt.rdf.wrapping.processor.E2ETest.*; import static java.util.UUID.randomUUID; import static org.apache.commons.io.IOUtils.toInputStream; @@ -115,10 +115,10 @@ static MyDataset wrap(final org.apache.jena.query.Dataset original) { return Manager.wrap(original, MyDataset.class); } - @DefaultGraph + @DatasetProperty MyGraph anonymous(); - @NamedGraph(G) + @DatasetProperty(G) MyGraph named(); // Dataset definitions support static methods. @@ -156,22 +156,22 @@ default Integer label() { @Resource interface MyResource { - @Property(predicate = LABEL, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + @ResourceProperty(predicate = LABEL, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Integer label(); - @Property(predicate = IRI, valueMapping = IRI_AS_URI) + @ResourceProperty(predicate = IRI, valueMapping = IRI_AS_URI) URI uri(); - @Property(predicate = CHILD) + @ResourceProperty(predicate = CHILD) MyResource child(); - @Property(predicate = THROWING, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(predicate = THROWING, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) String throwing(); - @Property(predicate = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + @ResourceProperty(predicate = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Set many(); - @Property(predicate = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) + @ResourceProperty(predicate = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) void overwrite(Integer value); // Resource definitions support static methods. diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java index 0e2be0c6f..43814aeac 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java @@ -20,8 +20,8 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.*; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.LITERAL_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.*; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.LITERAL_AS_STRING; import static java.beans.Introspector.getBeanInfo; import static java.lang.reflect.Modifier.isProtected; import static java.util.Arrays.stream; @@ -35,9 +35,9 @@ import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; -import com.inrupt.rdf.wrapping.annotation.Property; -import com.inrupt.rdf.wrapping.annotation.Property.Cardinality; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality; import com.inrupt.rdf.wrapping.jena.WrapperResource; import java.beans.IntrospectionException; @@ -66,8 +66,8 @@ class ResourceDefinitionCardinalityTest { private static final String P = "urn:example:p"; private static final String C = "urn:example:c"; private static final Object[] RESOURCE_DEFINITION_METHODS = stream(ResourceDefinition.class.getDeclaredMethods()) - .map(m -> m.getAnnotation(Property.class)) - .map(Property::cardinality) + .map(m -> m.getAnnotation(ResourceProperty.class)) + .map(ResourceProperty::cardinality) .map(Cardinality::getMethodName) .distinct() .toArray(); @@ -212,25 +212,25 @@ private static Method findProperty(final ResourceDefinition r, final Cardinality @Resource interface ResourceDefinition { - @Property(predicate = P, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(predicate = P, valueMapping = LITERAL_AS_STRING) String getAnyOrNull(); - @Property(predicate = P, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(predicate = P, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) String getAnyOrThrow(); - @Property(predicate = P, cardinality = SINGLE_OR_NULL, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(predicate = P, cardinality = SINGLE_OR_NULL, valueMapping = LITERAL_AS_STRING) String getSingleOrNull(); - @Property(predicate = P, cardinality = SINGLE_OR_THROW, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(predicate = P, cardinality = SINGLE_OR_THROW, valueMapping = LITERAL_AS_STRING) String getSingleOrThrow(); - @Property(predicate = P, cardinality = OBJECT_ITERATOR, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(predicate = P, cardinality = OBJECT_ITERATOR, valueMapping = LITERAL_AS_STRING) Iterator getObjectIterator(); - @Property(predicate = P, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(predicate = P, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_STRING) Set getObjectsReadOnly(); - @Property(predicate = P, cardinality = OBJECT_STREAM, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(predicate = P, cardinality = OBJECT_STREAM, valueMapping = LITERAL_AS_STRING) Stream getObjectStream(); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java index 7bcef15b6..be1188104 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java @@ -20,7 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.*; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.*; import static java.lang.reflect.Modifier.isPublic; import static java.util.Arrays.stream; import static java.util.UUID.randomUUID; @@ -34,9 +34,9 @@ import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; -import com.inrupt.rdf.wrapping.annotation.Property; -import com.inrupt.rdf.wrapping.annotation.Property.ValueMapping; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping; import com.inrupt.rdf.wrapping.jena.ValueMappings; import java.lang.reflect.Method; @@ -59,8 +59,8 @@ class ResourceDefinitionValueMappingTest { private static final String P = "urn:example:p"; private static final String C = "urn:example:c"; private static final Object[] RESOURCE_DEFINITION_METHODS = stream(ResourceDefinition.class.getDeclaredMethods()) - .map(m -> m.getAnnotation(Property.class)) - .map(Property::valueMapping) + .map(m -> m.getAnnotation(ResourceProperty.class)) + .map(ResourceProperty::valueMapping) .map(ValueMapping::getMethodName) .toArray(); @@ -137,25 +137,25 @@ private static Stream valueMappingsMethods() { @Resource interface ResourceDefinition { - @Property(predicate = P, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(predicate = P, valueMapping = LITERAL_AS_STRING) String getLiteralAsString(); - @Property(predicate = P, valueMapping = IRI_AS_URI) + @ResourceProperty(predicate = P, valueMapping = IRI_AS_URI) URI getIriAsUri(); - @Property(predicate = P, valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = P, valueMapping = IRI_AS_STRING) String getIriAsString(); - @Property(predicate = P, valueMapping = LITERAL_AS_INSTANT) + @ResourceProperty(predicate = P, valueMapping = LITERAL_AS_INSTANT) Instant getLiteralAsInstant(); - @Property(predicate = P, valueMapping = LITERAL_AS_BOOLEAN) + @ResourceProperty(predicate = P, valueMapping = LITERAL_AS_BOOLEAN) Boolean getLiteralAsBoolean(); - @Property(predicate = P, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + @ResourceProperty(predicate = P, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Integer getLiteralAsIntegerOrNull(); - @Property(predicate = P) + @ResourceProperty(predicate = P) ResourceDefinition getAs(); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 4d7c18a7b..c47081014 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -67,10 +67,6 @@ private static Stream compilationErrorOnInvalid() { return Stream.of( arguments("dataset is not an interface", MUST_BE_AN_INTERFACE), arguments("dataset extends unacceptable", "can only extend org.apache.jena.query.Dataset"), - arguments("dataset default graph method is static", CANNOT_BE_STATIC_OR_DEFAULT), - arguments("dataset default graph method is void", MUST_NOT_BE_VOID), - arguments("dataset default graph method is default", CANNOT_BE_STATIC_OR_DEFAULT), - arguments("dataset default graph method is not graph", MUST_RETURN_GRAPH_INTERFACE), arguments("dataset named graph method is static", CANNOT_BE_STATIC_OR_DEFAULT), arguments("dataset named graph method is default", CANNOT_BE_STATIC_OR_DEFAULT), arguments("dataset named graph method is not graph", MUST_RETURN_GRAPH_INTERFACE), @@ -128,7 +124,6 @@ private static Stream compilationSucceeds() { return Stream.of( arguments("dataset extends nothing"), arguments("dataset extends Dataset"), - arguments("dataset default graph method is graph instance"), arguments("dataset named graph method is graph instance"), arguments("dataset unannotated method is static"), arguments("dataset unannotated method is default"), diff --git a/processor/src/test/resources/validationExamples/bad/dataset default graph method is default.java b/processor/src/test/resources/validationExamples/bad/dataset default graph method is default.java deleted file mode 100644 index ad4efb7e5..000000000 --- a/processor/src/test/resources/validationExamples/bad/dataset default graph method is default.java +++ /dev/null @@ -1,13 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.DefaultGraph; - -@Dataset -interface X { - @DefaultGraph - default Object x() { - return null; - } -} diff --git a/processor/src/test/resources/validationExamples/bad/dataset default graph method is not graph.java b/processor/src/test/resources/validationExamples/bad/dataset default graph method is not graph.java deleted file mode 100644 index 8170e7ac2..000000000 --- a/processor/src/test/resources/validationExamples/bad/dataset default graph method is not graph.java +++ /dev/null @@ -1,11 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.DefaultGraph; - -@Dataset -interface X { - @DefaultGraph - Object x(); -} diff --git a/processor/src/test/resources/validationExamples/bad/dataset default graph method is static.java b/processor/src/test/resources/validationExamples/bad/dataset default graph method is static.java deleted file mode 100644 index 91b901b3e..000000000 --- a/processor/src/test/resources/validationExamples/bad/dataset default graph method is static.java +++ /dev/null @@ -1,13 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.DefaultGraph; - -@Dataset -interface X { - @DefaultGraph - static Object x() { - return null; - } -} diff --git a/processor/src/test/resources/validationExamples/bad/dataset default graph method is void.java b/processor/src/test/resources/validationExamples/bad/dataset default graph method is void.java deleted file mode 100644 index 9f6197a06..000000000 --- a/processor/src/test/resources/validationExamples/bad/dataset default graph method is void.java +++ /dev/null @@ -1,12 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.DefaultGraph; -import com.inrupt.rdf.wrapping.annotation.NamedGraph; - -@Dataset -interface X { - @DefaultGraph - void x(); -} diff --git a/processor/src/test/resources/validationExamples/bad/dataset named graph method is default.java b/processor/src/test/resources/validationExamples/bad/dataset named graph method is default.java index 09878d616..2e97215e4 100644 --- a/processor/src/test/resources/validationExamples/bad/dataset named graph method is default.java +++ b/processor/src/test/resources/validationExamples/bad/dataset named graph method is default.java @@ -2,11 +2,11 @@ package x; import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.NamedGraph; +import com.inrupt.rdf.wrapping.annotation.DatasetProperty; @Dataset interface X { - @NamedGraph("x") + @DatasetProperty("x") default Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/dataset named graph method is not graph.java b/processor/src/test/resources/validationExamples/bad/dataset named graph method is not graph.java index 5acbdc370..3e33f0a4b 100644 --- a/processor/src/test/resources/validationExamples/bad/dataset named graph method is not graph.java +++ b/processor/src/test/resources/validationExamples/bad/dataset named graph method is not graph.java @@ -2,10 +2,10 @@ package x; import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.NamedGraph; +import com.inrupt.rdf.wrapping.annotation.DatasetProperty; @Dataset interface X { - @NamedGraph("x") + @DatasetProperty("x") Object x(); } diff --git a/processor/src/test/resources/validationExamples/bad/dataset named graph method is static.java b/processor/src/test/resources/validationExamples/bad/dataset named graph method is static.java index 117b4b22f..d18a8aeec 100644 --- a/processor/src/test/resources/validationExamples/bad/dataset named graph method is static.java +++ b/processor/src/test/resources/validationExamples/bad/dataset named graph method is static.java @@ -2,11 +2,11 @@ package x; import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.NamedGraph; +import com.inrupt.rdf.wrapping.annotation.DatasetProperty; @Dataset interface X { - @NamedGraph("x") + @DatasetProperty("x") static Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/dataset named graph method is void.java b/processor/src/test/resources/validationExamples/bad/dataset named graph method is void.java index 15e1aeb93..aaf9deea2 100644 --- a/processor/src/test/resources/validationExamples/bad/dataset named graph method is void.java +++ b/processor/src/test/resources/validationExamples/bad/dataset named graph method is void.java @@ -2,10 +2,10 @@ package x; import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.NamedGraph; +import com.inrupt.rdf.wrapping.annotation.DatasetProperty; @Dataset interface X { - @NamedGraph("x") + @DatasetProperty("x") void x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java b/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java index 593e5539f..1572bdb1e 100644 --- a/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java +++ b/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java @@ -1,11 +1,11 @@ // This file is compiled only in test. package x; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @Property(predicate = "x") + @ResourceProperty(predicate = "x") Object x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java b/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java index adce667ad..f81b74d43 100644 --- a/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java +++ b/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java @@ -1,11 +1,11 @@ // This file is compiled only in test. package x; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @Property(predicate = "x") + @ResourceProperty(predicate = "x") void x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java index 76c2ed1d7..61da084ff 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java @@ -1,14 +1,14 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECT_ITERATOR; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECT_ITERATOR; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @Property(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) String x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java index 1e33882da..5c3f9e207 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java @@ -1,14 +1,14 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECTS_READ_ONLY; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @Property(predicate = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) Iterable x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java index dcd416b15..a09780585 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java @@ -1,16 +1,16 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECT_ITERATOR; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECT_ITERATOR; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; import java.util.Iterator; @Resource interface X { - @Property(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) Iterator x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java index b38ffa2a2..c13858a6a 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java @@ -1,16 +1,16 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECTS_READ_ONLY; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; import java.util.Set; @Resource interface X { - @Property(predicate = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) Set x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is default.java b/processor/src/test/resources/validationExamples/bad/resource property method is default.java index d70768911..3dd63eabe 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is default.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is default.java @@ -1,14 +1,14 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @Property(predicate = "x", valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = "x", valueMapping = IRI_AS_STRING) default Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is static.java b/processor/src/test/resources/validationExamples/bad/resource property method is static.java index da700c823..dfd98c37c 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is static.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is static.java @@ -1,14 +1,14 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @Property(predicate = "x", valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = "x", valueMapping = IRI_AS_STRING) static Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is void.java b/processor/src/test/resources/validationExamples/bad/resource property method is void.java index 1e390ed85..981231162 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is void.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is void.java @@ -1,13 +1,13 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @Property(predicate = "x", valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = "x", valueMapping = IRI_AS_STRING) void x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java b/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java index d6c6fbd6d..583c27574 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java @@ -1,13 +1,13 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @Property(predicate = "x", valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = "x", valueMapping = IRI_AS_STRING) int x(); } diff --git a/processor/src/test/resources/validationExamples/good/dataset default graph method is graph instance.java b/processor/src/test/resources/validationExamples/good/dataset default graph method is graph instance.java deleted file mode 100644 index ab5324bc8..000000000 --- a/processor/src/test/resources/validationExamples/good/dataset default graph method is graph instance.java +++ /dev/null @@ -1,16 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.DefaultGraph; -import com.inrupt.rdf.wrapping.annotation.Graph; - -@Dataset -interface X { - @DefaultGraph - Y x(); - - @Graph - interface Y { - } -} diff --git a/processor/src/test/resources/validationExamples/good/dataset named graph method is graph instance.java b/processor/src/test/resources/validationExamples/good/dataset named graph method is graph instance.java index f43a4a9ae..44739cd6e 100644 --- a/processor/src/test/resources/validationExamples/good/dataset named graph method is graph instance.java +++ b/processor/src/test/resources/validationExamples/good/dataset named graph method is graph instance.java @@ -2,12 +2,12 @@ package x; import com.inrupt.rdf.wrapping.annotation.Dataset; +import com.inrupt.rdf.wrapping.annotation.DatasetProperty; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.NamedGraph; @Dataset interface X { - @NamedGraph("x") + @DatasetProperty("x") Y x(); @Graph diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java b/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java index ae554dd72..ab8478b7b 100644 --- a/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java +++ b/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java @@ -1,11 +1,11 @@ // This file is compiled only in test. package x; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @Property(predicate = "x") + @ResourceProperty(predicate = "x") X x(); } diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java index dfb14d257..7423c221b 100644 --- a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java +++ b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java @@ -3,8 +3,8 @@ import com.inrupt.rdf.wrapping.annotation.Graph; import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Graph interface X { @@ -13,7 +13,7 @@ interface X { @Resource interface Y { - @Property(predicate = "x") + @ResourceProperty(predicate = "x") Y x(); } } diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method.java b/processor/src/test/resources/validationExamples/good/resource plural property method.java index 3930e5122..820497e97 100644 --- a/processor/src/test/resources/validationExamples/good/resource plural property method.java +++ b/processor/src/test/resources/validationExamples/good/resource plural property method.java @@ -1,16 +1,16 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.Cardinality.OBJECT_ITERATOR; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECT_ITERATOR; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; import java.util.Iterator; @Resource interface X { - @Property(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) Iterator x(); } diff --git a/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java b/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java index ac8307e45..c58cc2a05 100644 --- a/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java +++ b/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java @@ -1,13 +1,13 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.Property.ValueMapping.IRI_AS_STRING; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; -import com.inrupt.rdf.wrapping.annotation.Property; import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @Property(predicate = "x", valueMapping = IRI_AS_STRING) + @ResourceProperty(predicate = "x", valueMapping = IRI_AS_STRING) Object x(); } From 68ee19dea0d70fe5b01059580e7f7bea0b133308 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 9 Mar 2024 20:06:53 +0000 Subject: [PATCH 113/141] Unify graph properties Extract graph property definition --- ...stanceOfEither.java => GraphProperty.java} | 21 +++++++++- .../OptionalFirstSubjectOfEither.java | 35 ---------------- .../wrapping/processor/GraphDefinition.java | 31 +++++--------- .../wrapping/processor/GraphImplementor.java | 40 ++++++------------- .../processor/GraphPropertyDefinition.java | 26 +++++++----- .../wrapping/processor/GraphValidator.java | 21 +++------- .../rdf/wrapping/processor/E2ETest.java | 12 +++--- .../ResourceDefinitionCardinalityTest.java | 5 ++- .../ResourceDefinitionValueMappingTest.java | 5 ++- .../rdf/wrapping/processor/ValidatorTest.java | 20 +++------- .../graph instance of method is default.java | 13 ------ ...ph instance of method is not resource.java | 11 ----- .../graph instance of method is static.java | 13 ------ .../bad/graph instance of method is void.java | 11 ----- ... => graph property method is default.java} | 4 +- ...raph property method is not resource.java} | 4 +- ...a => graph property method is static.java} | 4 +- ...ava => graph property method is void.java} | 4 +- .../graph subject of method is default.java | 13 ------ ...aph subject of method is not resource.java | 11 ----- .../graph subject of method is static.java | 13 ------ .../bad/graph subject of method is void.java | 11 ----- ...stance of method is resource instance.java | 16 -------- ...property method is resource instance.java} | 4 +- ...ubject of method is resource instance.java | 16 -------- ...rce complex property method recursive.java | 4 +- 26 files changed, 91 insertions(+), 277 deletions(-) rename annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/{OptionalFirstInstanceOfEither.java => GraphProperty.java} (72%) delete mode 100644 annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java rename annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java => processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphPropertyDefinition.java (68%) delete mode 100644 processor/src/test/resources/validationExamples/bad/graph instance of method is default.java delete mode 100644 processor/src/test/resources/validationExamples/bad/graph instance of method is not resource.java delete mode 100644 processor/src/test/resources/validationExamples/bad/graph instance of method is static.java delete mode 100644 processor/src/test/resources/validationExamples/bad/graph instance of method is void.java rename processor/src/test/resources/validationExamples/bad/{graph object of method is default.java => graph property method is default.java} (61%) rename processor/src/test/resources/validationExamples/bad/{graph object of method is not resource.java => graph property method is not resource.java} (56%) rename processor/src/test/resources/validationExamples/bad/{graph object of method is static.java => graph property method is static.java} (61%) rename processor/src/test/resources/validationExamples/bad/{graph object of method is void.java => graph property method is void.java} (55%) delete mode 100644 processor/src/test/resources/validationExamples/bad/graph subject of method is default.java delete mode 100644 processor/src/test/resources/validationExamples/bad/graph subject of method is not resource.java delete mode 100644 processor/src/test/resources/validationExamples/bad/graph subject of method is static.java delete mode 100644 processor/src/test/resources/validationExamples/bad/graph subject of method is void.java delete mode 100644 processor/src/test/resources/validationExamples/good/graph instance of method is resource instance.java rename processor/src/test/resources/validationExamples/good/{graph object of method is resource instance.java => graph property method is resource instance.java} (67%) delete mode 100644 processor/src/test/resources/validationExamples/good/graph subject of method is resource instance.java diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstInstanceOfEither.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/GraphProperty.java similarity index 72% rename from annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstInstanceOfEither.java rename to annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/GraphProperty.java index 63ec63c18..0bf1a125b 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstInstanceOfEither.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/GraphProperty.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.annotation; +import static com.inrupt.rdf.wrapping.annotation.GraphProperty.Method.SUBJECT_OF; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -30,6 +31,24 @@ @Target(METHOD) @Retention(RUNTIME) @Documented -public @interface OptionalFirstInstanceOfEither { +public @interface GraphProperty { String[] value(); + + Method method() default SUBJECT_OF; + + enum Method { + SUBJECT_OF("optionalFirstSubjectOfEither"), + OBJECT_OF("optionalFirstObjectOfEither"), + INSTANCE_OF("optionalFirstInstanceOfEither"); + + private final String methodName; + + Method(final String methodName) { + this.methodName = methodName; + } + + public String getMethodName() { + return methodName; + } + } } diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java deleted file mode 100644 index 187c29a8a..000000000 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstSubjectOfEither.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Inrupt Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.inrupt.rdf.wrapping.annotation; - -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -@Target(METHOD) -@Retention(RUNTIME) -@Documented -public @interface OptionalFirstSubjectOfEither { - String[] value(); -} diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java index 1247f4cd7..2ddc1e14e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java @@ -23,13 +23,10 @@ import static java.util.stream.Stream.concat; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; import java.util.stream.Stream; -import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; @@ -38,9 +35,13 @@ class GraphDefinition extends Definition { super(type, env, Graph.class); } + Stream properties() { + return membersAnnotatedWith(GraphProperty.class).map(m -> new GraphPropertyDefinition(m, env)); + } + Stream transitiveResourceTypes() { - final Stream children = resourceMethodTypes(); - final Stream descendants = resourceMethodTypes() + final Stream children = returnTypes(); + final Stream descendants = returnTypes() .map(getEnv()::type) .map(type -> new ResourceDefinition(type, getEnv())) .flatMap(ResourceDefinition::transitiveResourceTypes); @@ -49,21 +50,7 @@ Stream transitiveResourceTypes() { .distinct(); } - Stream instanceMethods() { - return membersAnnotatedWith(OptionalFirstInstanceOfEither.class); - } - - Stream subjectMethods() { - return membersAnnotatedWith(OptionalFirstSubjectOfEither.class); - } - - Stream objectMethods() { - return membersAnnotatedWith(OptionalFirstObjectOfEither.class); - } - - private Stream resourceMethodTypes() { - return concat(concat(instanceMethods(), subjectMethods()), objectMethods()) - .map(ExecutableElement::getReturnType) - .distinct(); + private Stream returnTypes() { + return properties().map(PropertyDefinition::getReturnType); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 9aee56e96..436041cf0 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -26,13 +26,9 @@ import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.$t; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; import com.inrupt.rdf.wrapping.jena.WrapperModel; import javax.annotation.Generated; -import javax.lang.model.element.ExecutableElement; import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; @@ -55,20 +51,7 @@ protected void implementInternal() { addToPersonality(constructor); addWrap(); - definition.instanceMethods().forEach(method -> addResourceMethod( - method, - "optionalFirstInstanceOfEither", - method.getAnnotation(OptionalFirstInstanceOfEither.class).value())); - - definition.subjectMethods().forEach(method -> addResourceMethod( - method, - "optionalFirstSubjectOfEither", - method.getAnnotation(OptionalFirstSubjectOfEither.class).value())); - - definition.objectMethods().forEach(method -> addResourceMethod( - method, - "optionalFirstObjectOfEither", - method.getAnnotation(OptionalFirstObjectOfEither.class).value())); + addResourceMethods(); } private void addImports() { @@ -110,18 +93,19 @@ private void addToPersonality(final JMethodDef constructor) { }); } - @SuppressWarnings("PMD.UseVarargs") // irrelevant in this utility method - private void addResourceMethod(final ExecutableElement method, final String convenience, final String[] values) { - final JType implementation = asImplementation(method.getReturnType()); + private void addResourceMethods() { + definition.properties().forEach(p -> { + final JType implementation = asImplementation(p.getReturnType()); - // Call model wrapper convenience method passing projection class argument - final JCall convenienceCall = call(convenience).arg(implementation._class()); + // Call model wrapper convenience method passing projection class argument + final JCall convenienceCall = call(p.method()).arg(implementation._class()); - // Pass each filter value from the annotation as additional argument - for (final String value : values) { - convenienceCall.arg(JExprs.str(value)); - } + // Pass each filter value from the annotation as additional argument + for (final String value : p.resources()) { + convenienceCall.arg(JExprs.str(value)); + } - addMethod(method).body()._return(convenienceCall); + addMethod(p).body()._return(convenienceCall); + }); } } diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphPropertyDefinition.java similarity index 68% rename from annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java rename to processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphPropertyDefinition.java index f251471f7..ec8f1efa5 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/OptionalFirstObjectOfEither.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphPropertyDefinition.java @@ -18,18 +18,22 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.inrupt.rdf.wrapping.annotation; +package com.inrupt.rdf.wrapping.processor; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; +import javax.lang.model.element.ExecutableElement; -@Target(METHOD) -@Retention(RUNTIME) -@Documented -public @interface OptionalFirstObjectOfEither { - String[] value(); +class GraphPropertyDefinition extends PropertyDefinition { + GraphPropertyDefinition(final ExecutableElement element, final Environment env) { + super(element, env, GraphProperty.class); + } + + String[] resources() { + return annotation().value(); + } + + String method() { + return annotation().method().getMethodName(); + } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java index 3d9678503..0b0eff712 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphValidator.java @@ -20,9 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; import com.inrupt.rdf.wrapping.annotation.Resource; import org.apache.jena.rdf.model.Model; @@ -38,21 +36,12 @@ protected void validateInternal() { limitBaseInterfaces(Model.class); - requireMemberMethods(OptionalFirstInstanceOfEither.class); - requireMemberMethods(OptionalFirstObjectOfEither.class); - requireMemberMethods(OptionalFirstSubjectOfEither.class); + requireMemberMethods(GraphProperty.class); - requireNonMemberMethods( - OptionalFirstInstanceOfEither.class, - OptionalFirstObjectOfEither.class, - OptionalFirstSubjectOfEither.class); + requireNonMemberMethods(GraphProperty.class); - requireNonVoidReturnType(OptionalFirstInstanceOfEither.class); - requireNonVoidReturnType(OptionalFirstObjectOfEither.class); - requireNonVoidReturnType(OptionalFirstSubjectOfEither.class); + requireNonVoidReturnType(GraphProperty.class); - requireAnnotatedReturnType(OptionalFirstInstanceOfEither.class, Resource.class); - requireAnnotatedReturnType(OptionalFirstObjectOfEither.class, Resource.class); - requireAnnotatedReturnType(OptionalFirstSubjectOfEither.class, Resource.class); + requireAnnotatedReturnType(GraphProperty.class, Resource.class); } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index 982de3aa9..31cc83e41 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -21,6 +21,8 @@ package com.inrupt.rdf.wrapping.processor; import static com.github.jsonldjava.shaded.com.google.common.base.Charsets.UTF_8; +import static com.inrupt.rdf.wrapping.annotation.GraphProperty.Method.INSTANCE_OF; +import static com.inrupt.rdf.wrapping.annotation.GraphProperty.Method.OBJECT_OF; import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.*; import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.NodeMapping.AS_TYPED_LITERAL; import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.*; @@ -134,15 +136,15 @@ default Integer label() { @Graph interface MyGraph { - @OptionalFirstInstanceOfEither(C) - MyResource instance(); - - @OptionalFirstSubjectOfEither(CHILD) + @GraphProperty(CHILD) MyResource subject(); - @OptionalFirstObjectOfEither(CHILD) + @GraphProperty(value = CHILD, method = OBJECT_OF) MyResource object(); + @GraphProperty(value = C, method = INSTANCE_OF) + MyResource instance(); + // Graph definitions support static methods. static UUID constant() { return STATIC; diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java index 43814aeac..80e23547f 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.annotation.GraphProperty.Method.INSTANCE_OF; import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.*; import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.LITERAL_AS_STRING; import static java.beans.Introspector.getBeanInfo; @@ -34,7 +35,7 @@ import static org.junit.jupiter.params.provider.Arguments.arguments; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.annotation.ResourceProperty; import com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality; @@ -240,7 +241,7 @@ static GraphDefinition wrap(final Model original) { return Manager.wrap(original, GraphDefinition.class); } - @OptionalFirstInstanceOfEither(C) + @GraphProperty(value = C, method = INSTANCE_OF) ResourceDefinition getResource(); } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java index be1188104..09b6bbe85 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.annotation.GraphProperty.Method.INSTANCE_OF; import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.*; import static java.lang.reflect.Modifier.isPublic; import static java.util.Arrays.stream; @@ -33,7 +34,7 @@ import static org.junit.jupiter.params.provider.Arguments.arguments; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.annotation.ResourceProperty; import com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping; @@ -165,7 +166,7 @@ static GraphDefinition wrap(final Model original) { return Manager.wrap(original, GraphDefinition.class); } - @OptionalFirstInstanceOfEither(C) + @GraphProperty(value = C, method = INSTANCE_OF) ResourceDefinition getResource(); } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index c47081014..12302c05f 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -75,18 +75,10 @@ private static Stream compilationErrorOnInvalid() { arguments("graph is not an interface", MUST_BE_AN_INTERFACE), arguments("graph extends unacceptable", "can only extend org.apache.jena.rdf.model.Model"), - arguments("graph instance of method is static", CANNOT_BE_STATIC_OR_DEFAULT), - arguments("graph instance of method is default", CANNOT_BE_STATIC_OR_DEFAULT), - arguments("graph instance of method is not resource", MUST_RETURN_RESOURCE_INTERFACE), - arguments("graph instance of method is void", MUST_NOT_BE_VOID), - arguments("graph object of method is static", CANNOT_BE_STATIC_OR_DEFAULT), - arguments("graph object of method is default", CANNOT_BE_STATIC_OR_DEFAULT), - arguments("graph object of method is not resource", MUST_RETURN_RESOURCE_INTERFACE), - arguments("graph object of method is void", MUST_NOT_BE_VOID), - arguments("graph subject of method is static", CANNOT_BE_STATIC_OR_DEFAULT), - arguments("graph subject of method is default", CANNOT_BE_STATIC_OR_DEFAULT), - arguments("graph subject of method is not resource", MUST_RETURN_RESOURCE_INTERFACE), - arguments("graph subject of method is void", MUST_NOT_BE_VOID), + arguments("graph property method is static", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph property method is default", CANNOT_BE_STATIC_OR_DEFAULT), + arguments("graph property method is not resource", MUST_RETURN_RESOURCE_INTERFACE), + arguments("graph property method is void", MUST_NOT_BE_VOID), arguments("graph instance method is not annotated", MUST_BE_STATIC_OR_DEFAULT), arguments("resource is not an interface", MUST_BE_AN_INTERFACE), @@ -130,9 +122,7 @@ private static Stream compilationSucceeds() { arguments("graph extends nothing"), arguments("graph extends Model"), - arguments("graph instance of method is resource instance"), - arguments("graph subject of method is resource instance"), - arguments("graph object of method is resource instance"), + arguments("graph property method is resource instance"), arguments("graph unannotated method is static"), arguments("graph unannotated method is default"), diff --git a/processor/src/test/resources/validationExamples/bad/graph instance of method is default.java b/processor/src/test/resources/validationExamples/bad/graph instance of method is default.java deleted file mode 100644 index abbe18502..000000000 --- a/processor/src/test/resources/validationExamples/bad/graph instance of method is default.java +++ /dev/null @@ -1,13 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; - -@Graph -interface X { - @OptionalFirstInstanceOfEither("x") - default Object x() { - return null; - } -} diff --git a/processor/src/test/resources/validationExamples/bad/graph instance of method is not resource.java b/processor/src/test/resources/validationExamples/bad/graph instance of method is not resource.java deleted file mode 100644 index ea7bdcb48..000000000 --- a/processor/src/test/resources/validationExamples/bad/graph instance of method is not resource.java +++ /dev/null @@ -1,11 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; - -@Graph -interface X { - @OptionalFirstInstanceOfEither("x") - Object x(); -} diff --git a/processor/src/test/resources/validationExamples/bad/graph instance of method is static.java b/processor/src/test/resources/validationExamples/bad/graph instance of method is static.java deleted file mode 100644 index 114ca2699..000000000 --- a/processor/src/test/resources/validationExamples/bad/graph instance of method is static.java +++ /dev/null @@ -1,13 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; - -@Graph -interface X { - @OptionalFirstInstanceOfEither("x") - static Object x() { - return null; - } -} diff --git a/processor/src/test/resources/validationExamples/bad/graph instance of method is void.java b/processor/src/test/resources/validationExamples/bad/graph instance of method is void.java deleted file mode 100644 index 487a51ae6..000000000 --- a/processor/src/test/resources/validationExamples/bad/graph instance of method is void.java +++ /dev/null @@ -1,11 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; - -@Graph -interface X { - @OptionalFirstInstanceOfEither("x") - void x(); -} diff --git a/processor/src/test/resources/validationExamples/bad/graph object of method is default.java b/processor/src/test/resources/validationExamples/bad/graph property method is default.java similarity index 61% rename from processor/src/test/resources/validationExamples/bad/graph object of method is default.java rename to processor/src/test/resources/validationExamples/bad/graph property method is default.java index 1642453d0..fa60945a9 100644 --- a/processor/src/test/resources/validationExamples/bad/graph object of method is default.java +++ b/processor/src/test/resources/validationExamples/bad/graph property method is default.java @@ -2,11 +2,11 @@ package x; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; @Graph interface X { - @OptionalFirstObjectOfEither("x") + @GraphProperty("x") default Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/graph object of method is not resource.java b/processor/src/test/resources/validationExamples/bad/graph property method is not resource.java similarity index 56% rename from processor/src/test/resources/validationExamples/bad/graph object of method is not resource.java rename to processor/src/test/resources/validationExamples/bad/graph property method is not resource.java index 32963630c..123513742 100644 --- a/processor/src/test/resources/validationExamples/bad/graph object of method is not resource.java +++ b/processor/src/test/resources/validationExamples/bad/graph property method is not resource.java @@ -2,10 +2,10 @@ package x; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; @Graph interface X { - @OptionalFirstObjectOfEither("x") + @GraphProperty("x") Object x(); } diff --git a/processor/src/test/resources/validationExamples/bad/graph object of method is static.java b/processor/src/test/resources/validationExamples/bad/graph property method is static.java similarity index 61% rename from processor/src/test/resources/validationExamples/bad/graph object of method is static.java rename to processor/src/test/resources/validationExamples/bad/graph property method is static.java index 8749cd7b6..af6d2cb49 100644 --- a/processor/src/test/resources/validationExamples/bad/graph object of method is static.java +++ b/processor/src/test/resources/validationExamples/bad/graph property method is static.java @@ -2,11 +2,11 @@ package x; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; @Graph interface X { - @OptionalFirstObjectOfEither("x") + @GraphProperty("x") static Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/graph object of method is void.java b/processor/src/test/resources/validationExamples/bad/graph property method is void.java similarity index 55% rename from processor/src/test/resources/validationExamples/bad/graph object of method is void.java rename to processor/src/test/resources/validationExamples/bad/graph property method is void.java index adb261d3f..0aaa0dceb 100644 --- a/processor/src/test/resources/validationExamples/bad/graph object of method is void.java +++ b/processor/src/test/resources/validationExamples/bad/graph property method is void.java @@ -2,10 +2,10 @@ package x; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; @Graph interface X { - @OptionalFirstObjectOfEither("x") + @GraphProperty("x") void x(); } diff --git a/processor/src/test/resources/validationExamples/bad/graph subject of method is default.java b/processor/src/test/resources/validationExamples/bad/graph subject of method is default.java deleted file mode 100644 index 886457f49..000000000 --- a/processor/src/test/resources/validationExamples/bad/graph subject of method is default.java +++ /dev/null @@ -1,13 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; - -@Graph -interface X { - @OptionalFirstSubjectOfEither("x") - default Object x() { - return null; - } -} diff --git a/processor/src/test/resources/validationExamples/bad/graph subject of method is not resource.java b/processor/src/test/resources/validationExamples/bad/graph subject of method is not resource.java deleted file mode 100644 index a5a2e94d9..000000000 --- a/processor/src/test/resources/validationExamples/bad/graph subject of method is not resource.java +++ /dev/null @@ -1,11 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; - -@Graph -interface X { - @OptionalFirstSubjectOfEither("x") - Object x(); -} diff --git a/processor/src/test/resources/validationExamples/bad/graph subject of method is static.java b/processor/src/test/resources/validationExamples/bad/graph subject of method is static.java deleted file mode 100644 index bb18a779d..000000000 --- a/processor/src/test/resources/validationExamples/bad/graph subject of method is static.java +++ /dev/null @@ -1,13 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; - -@Graph -interface X { - @OptionalFirstSubjectOfEither("x") - static Object x() { - return null; - } -} diff --git a/processor/src/test/resources/validationExamples/bad/graph subject of method is void.java b/processor/src/test/resources/validationExamples/bad/graph subject of method is void.java deleted file mode 100644 index 5f9787035..000000000 --- a/processor/src/test/resources/validationExamples/bad/graph subject of method is void.java +++ /dev/null @@ -1,11 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; - -@Graph -interface X { - @OptionalFirstSubjectOfEither("x") - void x(); -} diff --git a/processor/src/test/resources/validationExamples/good/graph instance of method is resource instance.java b/processor/src/test/resources/validationExamples/good/graph instance of method is resource instance.java deleted file mode 100644 index 02de4b59f..000000000 --- a/processor/src/test/resources/validationExamples/good/graph instance of method is resource instance.java +++ /dev/null @@ -1,16 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; -import com.inrupt.rdf.wrapping.annotation.Resource; - -@Graph -interface X { - @OptionalFirstInstanceOfEither("x") - Y x(); - - @Resource - interface Y { - } -} diff --git a/processor/src/test/resources/validationExamples/good/graph object of method is resource instance.java b/processor/src/test/resources/validationExamples/good/graph property method is resource instance.java similarity index 67% rename from processor/src/test/resources/validationExamples/good/graph object of method is resource instance.java rename to processor/src/test/resources/validationExamples/good/graph property method is resource instance.java index 466f690d8..e723ef875 100644 --- a/processor/src/test/resources/validationExamples/good/graph object of method is resource instance.java +++ b/processor/src/test/resources/validationExamples/good/graph property method is resource instance.java @@ -2,12 +2,12 @@ package x; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstObjectOfEither; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; import com.inrupt.rdf.wrapping.annotation.Resource; @Graph interface X { - @OptionalFirstObjectOfEither("x") + @GraphProperty("x") Y x(); @Resource diff --git a/processor/src/test/resources/validationExamples/good/graph subject of method is resource instance.java b/processor/src/test/resources/validationExamples/good/graph subject of method is resource instance.java deleted file mode 100644 index f2fa18f1e..000000000 --- a/processor/src/test/resources/validationExamples/good/graph subject of method is resource instance.java +++ /dev/null @@ -1,16 +0,0 @@ -// This file is compiled only in test. -package x; - -import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstSubjectOfEither; -import com.inrupt.rdf.wrapping.annotation.Resource; - -@Graph -interface X { - @OptionalFirstSubjectOfEither("x") - Y x(); - - @Resource - interface Y { - } -} diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java index 7423c221b..de4811416 100644 --- a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java +++ b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java @@ -2,13 +2,13 @@ package x; import com.inrupt.rdf.wrapping.annotation.Graph; -import com.inrupt.rdf.wrapping.annotation.OptionalFirstInstanceOfEither; +import com.inrupt.rdf.wrapping.annotation.GraphProperty; import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Graph interface X { - @OptionalFirstInstanceOfEither("x") + @GraphProperty("x") Y x(); @Resource From 81fbe14cc30d84e809cefef159f0997dcb015731 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 9 Mar 2024 20:10:16 +0000 Subject: [PATCH 114/141] Tidy --- .../com/inrupt/rdf/wrapping/processor/Implementor.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 891899b43..8469ec5fc 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -95,16 +95,6 @@ protected void addClass(final Class clazz) { target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); } - protected JMethodDef addMethod(final ExecutableElement method) { - final String myName = method.getSimpleName().toString(); - final JType myType = typeOf(method.getReturnType()); - - final JMethodDef myMethod = target.method(PUBLIC, myType, myName); - myMethod.annotate(Override.class); - - return myMethod; - } - protected JMethodDef addMethod(final Definition d) { final String myName = d.element.getSimpleName().toString(); final JType myType = typeOf(d.element.getReturnType()); From 21dae581b3762106070d3527f6f977c18b69c5ae Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 10 Mar 2024 14:43:32 +0000 Subject: [PATCH 115/141] Simplify resource property Rename predicate so it's easier in default case. Also simplify validation tests. --- .../rdf/wrapping/annotation/ResourceProperty.java | 2 +- .../processor/ResourcePropertyDefinition.java | 2 +- .../rdf/wrapping/processor/ResourceValidator.java | 2 ++ .../com/inrupt/rdf/wrapping/processor/E2ETest.java | 12 ++++++------ .../ResourceDefinitionCardinalityTest.java | 14 +++++++------- .../ResourceDefinitionValueMappingTest.java | 14 +++++++------- ...ce complex property method is not resource.java | 2 +- .../resource complex property method is void.java | 2 +- ...rce plural property method erasure differs.java | 2 +- ...ource plural property method erasure super.java | 2 +- ...ural property method type argument differs.java | 2 +- ...plural property method type argument super.java | 2 +- .../bad/resource property method is default.java | 4 +--- .../bad/resource property method is static.java | 4 +--- .../bad/resource property method is void.java | 4 +--- ...property method return type not assignable.java | 2 +- ...mplex property method is resource instance.java | 2 +- ...resource complex property method recursive.java | 2 +- .../good/resource plural property method.java | 2 +- ...rce property method is assignable instance.java | 2 +- 20 files changed, 38 insertions(+), 42 deletions(-) diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java index 53217ffc5..6f2bc710d 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java @@ -34,7 +34,7 @@ @Retention(RUNTIME) @Documented public @interface ResourceProperty { - String predicate(); + String value(); Cardinality cardinality() default ANY_OR_NULL; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java index cb31c2ec4..d6b0e31a1 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java @@ -35,7 +35,7 @@ class ResourcePropertyDefinition extends PropertyDefinition { } String predicate() { - return annotation().predicate(); + return annotation().value(); } Cardinality cardinality() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 14c41051f..2255d6363 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -134,6 +134,8 @@ private void requirePluralErasure() { } // TODO: Check bounds of type parameters e.g. String & CharSequence + // TODO: this `@ResourceProperty(value = "x", cardinality = OBJECT_ITERATOR) Iterator x()` produces + // "must have same type argument as return type [com.inrupt.rdf.wrapping.jena.ValueMapping] of mapping [as]" private void requirePluralTypeArgument() { definition.pluralProperties().forEach(p -> { final DeclaredType thisReturn = (DeclaredType) p.getReturnType(); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index 31cc83e41..1244c5bdc 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -158,22 +158,22 @@ default Integer label() { @Resource interface MyResource { - @ResourceProperty(predicate = LABEL, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + @ResourceProperty(value = LABEL, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Integer label(); - @ResourceProperty(predicate = IRI, valueMapping = IRI_AS_URI) + @ResourceProperty(value = IRI, valueMapping = IRI_AS_URI) URI uri(); - @ResourceProperty(predicate = CHILD) + @ResourceProperty(CHILD) MyResource child(); - @ResourceProperty(predicate = THROWING, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(value = THROWING, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) String throwing(); - @ResourceProperty(predicate = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Set many(); - @ResourceProperty(predicate = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) + @ResourceProperty(value = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) void overwrite(Integer value); // Resource definitions support static methods. diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java index 80e23547f..c7ad44da4 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionCardinalityTest.java @@ -213,25 +213,25 @@ private static Method findProperty(final ResourceDefinition r, final Cardinality @Resource interface ResourceDefinition { - @ResourceProperty(predicate = P, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(value = P, valueMapping = LITERAL_AS_STRING) String getAnyOrNull(); - @ResourceProperty(predicate = P, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(value = P, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) String getAnyOrThrow(); - @ResourceProperty(predicate = P, cardinality = SINGLE_OR_NULL, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(value = P, cardinality = SINGLE_OR_NULL, valueMapping = LITERAL_AS_STRING) String getSingleOrNull(); - @ResourceProperty(predicate = P, cardinality = SINGLE_OR_THROW, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(value = P, cardinality = SINGLE_OR_THROW, valueMapping = LITERAL_AS_STRING) String getSingleOrThrow(); - @ResourceProperty(predicate = P, cardinality = OBJECT_ITERATOR, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(value = P, cardinality = OBJECT_ITERATOR, valueMapping = LITERAL_AS_STRING) Iterator getObjectIterator(); - @ResourceProperty(predicate = P, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(value = P, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_STRING) Set getObjectsReadOnly(); - @ResourceProperty(predicate = P, cardinality = OBJECT_STREAM, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(value = P, cardinality = OBJECT_STREAM, valueMapping = LITERAL_AS_STRING) Stream getObjectStream(); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java index 09b6bbe85..3139438de 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java @@ -138,25 +138,25 @@ private static Stream valueMappingsMethods() { @Resource interface ResourceDefinition { - @ResourceProperty(predicate = P, valueMapping = LITERAL_AS_STRING) + @ResourceProperty(value = P, valueMapping = LITERAL_AS_STRING) String getLiteralAsString(); - @ResourceProperty(predicate = P, valueMapping = IRI_AS_URI) + @ResourceProperty(value = P, valueMapping = IRI_AS_URI) URI getIriAsUri(); - @ResourceProperty(predicate = P, valueMapping = IRI_AS_STRING) + @ResourceProperty(value = P, valueMapping = IRI_AS_STRING) String getIriAsString(); - @ResourceProperty(predicate = P, valueMapping = LITERAL_AS_INSTANT) + @ResourceProperty(value = P, valueMapping = LITERAL_AS_INSTANT) Instant getLiteralAsInstant(); - @ResourceProperty(predicate = P, valueMapping = LITERAL_AS_BOOLEAN) + @ResourceProperty(value = P, valueMapping = LITERAL_AS_BOOLEAN) Boolean getLiteralAsBoolean(); - @ResourceProperty(predicate = P, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + @ResourceProperty(value = P, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Integer getLiteralAsIntegerOrNull(); - @ResourceProperty(predicate = P) + @ResourceProperty(P) ResourceDefinition getAs(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java b/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java index 1572bdb1e..acfa9a8f0 100644 --- a/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java +++ b/processor/src/test/resources/validationExamples/bad/resource complex property method is not resource.java @@ -6,6 +6,6 @@ @Resource interface X { - @ResourceProperty(predicate = "x") + @ResourceProperty("x") Object x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java b/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java index f81b74d43..a37c31eff 100644 --- a/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java +++ b/processor/src/test/resources/validationExamples/bad/resource complex property method is void.java @@ -6,6 +6,6 @@ @Resource interface X { - @ResourceProperty(predicate = "x") + @ResourceProperty("x") void x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java index 61da084ff..222c269a1 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure differs.java @@ -9,6 +9,6 @@ @Resource interface X { - @ResourceProperty(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) + @ResourceProperty(value = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) String x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java index 5c3f9e207..9b1f58d6f 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java @@ -9,6 +9,6 @@ @Resource interface X { - @ResourceProperty(predicate = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) Iterable x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java index a09780585..9dc523ab8 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument differs.java @@ -11,6 +11,6 @@ @Resource interface X { - @ResourceProperty(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) + @ResourceProperty(value = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) Iterator x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java index c13858a6a..2ee8e6077 100644 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java +++ b/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java @@ -11,6 +11,6 @@ @Resource interface X { - @ResourceProperty(predicate = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) Set x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is default.java b/processor/src/test/resources/validationExamples/bad/resource property method is default.java index 3dd63eabe..77a116550 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is default.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is default.java @@ -1,14 +1,12 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @ResourceProperty(predicate = "x", valueMapping = IRI_AS_STRING) + @ResourceProperty("x") default Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is static.java b/processor/src/test/resources/validationExamples/bad/resource property method is static.java index dfd98c37c..005992ce3 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is static.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is static.java @@ -1,14 +1,12 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @ResourceProperty(predicate = "x", valueMapping = IRI_AS_STRING) + @ResourceProperty("x") static Object x() { return null; } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method is void.java b/processor/src/test/resources/validationExamples/bad/resource property method is void.java index 981231162..a37c31eff 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method is void.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method is void.java @@ -1,13 +1,11 @@ // This file is compiled only in test. package x; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @Resource interface X { - @ResourceProperty(predicate = "x", valueMapping = IRI_AS_STRING) + @ResourceProperty("x") void x(); } diff --git a/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java b/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java index 583c27574..9a837facc 100644 --- a/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java +++ b/processor/src/test/resources/validationExamples/bad/resource property method return type not assignable.java @@ -8,6 +8,6 @@ @Resource interface X { - @ResourceProperty(predicate = "x", valueMapping = IRI_AS_STRING) + @ResourceProperty(value = "x", valueMapping = IRI_AS_STRING) int x(); } diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java b/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java index ab8478b7b..aa014cf4d 100644 --- a/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java +++ b/processor/src/test/resources/validationExamples/good/resource complex property method is resource instance.java @@ -6,6 +6,6 @@ @Resource interface X { - @ResourceProperty(predicate = "x") + @ResourceProperty("x") X x(); } diff --git a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java index de4811416..ccb1fffea 100644 --- a/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java +++ b/processor/src/test/resources/validationExamples/good/resource complex property method recursive.java @@ -13,7 +13,7 @@ interface X { @Resource interface Y { - @ResourceProperty(predicate = "x") + @ResourceProperty("x") Y x(); } } diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method.java b/processor/src/test/resources/validationExamples/good/resource plural property method.java index 820497e97..8b8df5fed 100644 --- a/processor/src/test/resources/validationExamples/good/resource plural property method.java +++ b/processor/src/test/resources/validationExamples/good/resource plural property method.java @@ -11,6 +11,6 @@ @Resource interface X { - @ResourceProperty(predicate = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) + @ResourceProperty(value = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) Iterator x(); } diff --git a/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java b/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java index c58cc2a05..d008667d8 100644 --- a/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java +++ b/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java @@ -8,6 +8,6 @@ @Resource interface X { - @ResourceProperty(predicate = "x", valueMapping = IRI_AS_STRING) + @ResourceProperty(value = "x", valueMapping = IRI_AS_STRING) Object x(); } From 5246404feb01c074002f390e49828175bad20939 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 10 Mar 2024 22:54:56 +0000 Subject: [PATCH 116/141] Describe value mapping complexity --- .../wrapping/annotation/ResourceProperty.java | 22 ++++++++++++------- .../processor/ResourceDefinition.java | 3 +-- .../ResourceDefinitionValueMappingTest.java | 2 +- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java index 6f2bc710d..b502d149b 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java @@ -43,23 +43,29 @@ NodeMapping nodeMapping() default IDENTITY; enum ValueMapping { - AS("as"), - IRI_AS_STRING("iriAsString"), - IRI_AS_URI("iriAsUri"), - LITERAL_AS_BOOLEAN("literalAsBoolean"), - LITERAL_AS_INSTANT("literalAsInstant"), - LITERAL_AS_INTEGER_OR_NULL("literalAsIntegerOrNull"), - LITERAL_AS_STRING("literalAsString"); + AS("as", true), + IRI_AS_STRING("iriAsString", false), + IRI_AS_URI("iriAsUri", false), + LITERAL_AS_BOOLEAN("literalAsBoolean", false), + LITERAL_AS_INSTANT("literalAsInstant", false), + LITERAL_AS_INTEGER_OR_NULL("literalAsIntegerOrNull", false), + LITERAL_AS_STRING("literalAsString", false); private final String methodName; + private final boolean complex; - ValueMapping(final String methodName) { + ValueMapping(final String methodName, final boolean complex) { this.methodName = methodName; + this.complex = complex; } public String getMethodName() { return methodName; } + + public boolean isComplex() { + return complex; + } } enum NodeMapping { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index 3bcc9be0a..af927bfc3 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -20,7 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.AS; import static com.inrupt.rdf.wrapping.processor.PredicateShim.not; import static javax.lang.model.type.TypeKind.VOID; @@ -38,7 +37,7 @@ import javax.lang.model.type.TypeMirror; class ResourceDefinition extends Definition { - private static final Predicate isComplex = p -> p.valueMapping() == AS; + private static final Predicate isComplex = p -> p.valueMapping().isComplex(); private static final Predicate isPlural = p -> p.cardinality().isPlural(); private final Predicate returnsResource = p -> getEnv().type(p.getReturnType()).getAnnotation(Resource.class) != null; diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java index 3139438de..ad703d9f2 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ResourceDefinitionValueMappingTest.java @@ -84,7 +84,7 @@ void e2e(final ValueMapping valueMapping, final RDFNode original, final Object e final Matcher isExpected; final RDFNode o; - if (valueMapping == AS) { + if (valueMapping.isComplex()) { o = m.createResource().addProperty(p, (String) expected); // Complex properties need a bit more setup isExpected = hasProperty(LITERAL_AS_STRING.getMethodName(), equalTo(expected)); // and matcher } else { From c470b86b6e7ce2929ad5e1f09e9c92279cc09f8a Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 10 Mar 2024 23:50:51 +0000 Subject: [PATCH 117/141] Tolerate variance in plural resource properties --- .../processor/ResourceDefinition.java | 3 +- .../processor/ResourceImplementor.java | 1 + .../wrapping/processor/ResourceValidator.java | 53 ++++++++++------- .../rdf/wrapping/processor/E2ETest.java | 57 ++++++++++++++++++- .../rdf/wrapping/processor/ValidatorTest.java | 12 ++-- ...source plural property method extends.java | 16 ++++++ .../resource plural property method raw.java | 16 ++++++ ...resource plural property method super.java | 16 ++++++ ...l property method type argument super.java | 0 ...ource plural property method wildcard.java | 16 ++++++ 10 files changed, 163 insertions(+), 27 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method extends.java create mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method raw.java create mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method super.java rename processor/src/test/resources/validationExamples/{bad => good}/resource plural property method type argument super.java (100%) create mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method wildcard.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index af927bfc3..e0e3c4bf8 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -79,8 +79,9 @@ Stream primitiveMappingProperties() { .filter(not(isVoid)); } - Stream pluralProperties() { + Stream primitivePluralProperties() { return properties() + .filter(not(isComplex)) .filter(isPlural); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index c00235e8f..5223ba3e1 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -51,6 +51,7 @@ protected void implementInternal() { addPrimitivePropertyMethods(); addResourcePropertyMethods(); addOverwrite(); + // TODO: plural complex } private void addImports() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 2255d6363..a3ab0e3f4 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -29,14 +29,14 @@ import com.inrupt.rdf.wrapping.jena.ValueMappings; import com.inrupt.rdf.wrapping.jena.WrapperResource; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; +import java.util.Objects; +import java.util.stream.Stream; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.WildcardType; class ResourceValidator extends Validator { ResourceValidator(final ResourceDefinition definition) { @@ -63,6 +63,7 @@ protected void validateInternal() { requirePluralErasure(); requirePluralTypeArgument(); + // TODO: plural complex } private void requireNonVoidReturnType() { @@ -111,7 +112,7 @@ private void requireCompatibleComplexReturnType() { } private void requirePluralErasure() { - definition.pluralProperties().forEach(p -> { + definition.primitivePluralProperties().forEach(p -> { final TypeMirror thisErasure = definition.getEnv().getTypeUtils().erasure(p.getReturnType()); final TypeMirror cardinalityReturn = returnTypeOf(p.cardinalityMethod(), WrapperResource.class); @@ -133,35 +134,49 @@ private void requirePluralErasure() { }); } - // TODO: Check bounds of type parameters e.g. String & CharSequence - // TODO: this `@ResourceProperty(value = "x", cardinality = OBJECT_ITERATOR) Iterator x()` produces - // "must have same type argument as return type [com.inrupt.rdf.wrapping.jena.ValueMapping] of mapping [as]" private void requirePluralTypeArgument() { - definition.pluralProperties().forEach(p -> { + definition.primitivePluralProperties().forEach(p -> { final DeclaredType thisReturn = (DeclaredType) p.getReturnType(); - final TypeMirror thisErasure = definition.getEnv().getTypeUtils().erasure(thisReturn); - if (definition.getEnv().isSameType(thisErasure, thisReturn)) { - // Ignore cases where return type of property method is not generic + // raw generic or not generic + if (thisReturn.getTypeArguments().isEmpty()) { return; } - final TypeMirror mappingReturn = returnTypeOf(p.valueMappingMethod(), ValueMappings.class); + final boolean hasWildcard = thisReturn.getTypeArguments().stream().anyMatch(WildcardType.class::isInstance); - final List mappingTypeArguments = new ArrayList<>(); - mappingTypeArguments.add(definition.typeOf(mappingReturn)); + // wildcard + if (hasWildcard && thisReturn.getTypeArguments().stream() + .filter(WildcardType.class::isInstance) + .map(WildcardType.class::cast) + .flatMap(wildcard -> Stream.of(wildcard.getSuperBound(), wildcard.getExtendsBound())) + .allMatch(Objects::isNull)) { + return; + } - final List thisTypeArguments = thisReturn.getTypeArguments().stream() - .map(definition::typeOf) - .collect(Collectors.toList()); + final TypeMirror mappingReturn = returnTypeOf(p.valueMappingMethod(), ValueMappings.class); + + // extends or super + if (thisReturn.getTypeArguments().stream() + .filter(WildcardType.class::isInstance) + .map(WildcardType.class::cast) + .flatMap(wildcard -> Stream.of(wildcard.getSuperBound(), wildcard.getExtendsBound())) + .filter(Objects::nonNull) + .anyMatch(x -> definition.getEnv().getTypeUtils().isAssignable(mappingReturn, x))) { + return; + } - if (mappingTypeArguments.equals(thisTypeArguments)) { + // concrete + if (thisReturn.getTypeArguments().stream() + .filter(not(WildcardType.class::isInstance)) + .anyMatch(x -> definition.getEnv().getTypeUtils().isAssignable(mappingReturn, x))) { return; } errors.add(new ValidationError( p.element, - "Return type [%s] of [%s] must have same type argument as return type [%s] of mapping [%s]", + "Return type [%s] of [%s] must have type argument assignable from " + + "type argument of return type [%s] of mapping [%s]", thisReturn, p.getName(), mappingReturn, diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index 1244c5bdc..52feac4a5 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -77,6 +77,7 @@ class E2ETest { " [ \n" + " a :C ; \n" + " :label 5 ; \n" + + " :many 5, 6; \n" + " ] . \n" + " } \n"; private static final org.apache.jena.query.Dataset DATASET = DatasetFactory.create(); @@ -92,7 +93,13 @@ void test() { assertThat(myDataset.anonymous().instance().label(), is(1)); assertThat(myDataset.anonymous().instance().uri(), is(U)); - assertThat(myDataset.anonymous().instance().many(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many1(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many2(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many3(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many4(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many5(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many6(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many7(), contains(2, 3)); assertThat(myDataset.anonymous().instance().child().label(), is(4)); assertThrows(Throwable.class, () -> myDataset.anonymous().instance().throwing()); assertThat(myDataset.anonymous().instance().childLabel(), is(4)); @@ -171,7 +178,53 @@ interface MyResource { String throwing(); @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) - Set many(); + Set many1(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Set many2(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Set many3(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Set many4(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Set many5(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Set many6(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Set many7(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Set many8(); + +// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY) +// Set many7(); +// +// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY) +// Set many8(); +// +// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY) +// Set many9(); + + +// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) +// Collection many21(); +// +// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) +// Collection many22(); +// +// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) +// Collection many23(); +// +// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) +// Collection many24(); +// +// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) +// Collection many25(); @ResourceProperty(value = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) void overwrite(Integer value); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 12302c05f..8e3377ddb 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -95,10 +95,7 @@ private static Stream compilationErrorOnInvalid() { arguments("resource plural property method erasure super", "must have same erasure as return type"), arguments( "resource plural property method type argument differs", - "must have same type argument as return type"), - arguments( - "resource plural property method type argument super", - "must have same type argument as return type") + "must have type argument assignable from type argument of return type") ); } @@ -134,7 +131,12 @@ private static Stream compilationSucceeds() { arguments("resource complex property method is resource instance"), arguments("resource complex property method recursive"), - arguments("resource plural property method") + arguments("resource plural property method"), + arguments("resource plural property method raw"), + arguments("resource plural property method extends"), + arguments("resource plural property method super"), + arguments("resource plural property method wildcard"), + arguments("resource plural property method type argument super") ); } } diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method extends.java b/processor/src/test/resources/validationExamples/good/resource plural property method extends.java new file mode 100644 index 000000000..4df8b9a85 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource plural property method extends.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +import java.util.Set; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x(); +} diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method raw.java b/processor/src/test/resources/validationExamples/good/resource plural property method raw.java new file mode 100644 index 000000000..84d939867 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource plural property method raw.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +import java.util.Set; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x(); +} diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method super.java b/processor/src/test/resources/validationExamples/good/resource plural property method super.java new file mode 100644 index 000000000..5724fe475 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource plural property method super.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +import java.util.Set; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java b/processor/src/test/resources/validationExamples/good/resource plural property method type argument super.java similarity index 100% rename from processor/src/test/resources/validationExamples/bad/resource plural property method type argument super.java rename to processor/src/test/resources/validationExamples/good/resource plural property method type argument super.java diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method wildcard.java b/processor/src/test/resources/validationExamples/good/resource plural property method wildcard.java new file mode 100644 index 000000000..4eed8994a --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource plural property method wildcard.java @@ -0,0 +1,16 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +import java.util.Set; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x(); +} From a46bccc37a7d1b910d3eb504bc0be3d1df25ff52 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Tue, 12 Mar 2024 22:10:47 +0000 Subject: [PATCH 118/141] Tolerate assignable return types for plural primitive resource properties --- .../wrapping/processor/ResourceValidator.java | 3 +- .../rdf/wrapping/processor/E2ETest.java | 65 ++++++++++--------- .../rdf/wrapping/processor/ValidatorTest.java | 9 +-- ... plural property method erasure super.java | 14 ---- .../resource plural primitive property.java | 62 ++++++++++++++++++ ...source plural property method extends.java | 16 ----- .../resource plural property method raw.java | 16 ----- ...resource plural property method super.java | 16 ----- ...l property method type argument super.java | 16 ----- ...ource plural property method wildcard.java | 16 ----- .../good/resource plural property method.java | 16 ----- ...roperty method is assignable instance.java | 13 ---- 12 files changed, 100 insertions(+), 162 deletions(-) delete mode 100644 processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java create mode 100644 processor/src/test/resources/validationExamples/good/resource plural primitive property.java delete mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method extends.java delete mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method raw.java delete mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method super.java delete mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method type argument super.java delete mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method wildcard.java delete mode 100644 processor/src/test/resources/validationExamples/good/resource plural property method.java delete mode 100644 processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index a3ab0e3f4..00df7ca14 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -119,8 +119,7 @@ private void requirePluralErasure() { final TypeMirror cardinalityErasure = definition.getEnv().getTypeUtils().erasure(cardinalityReturn); - // TODO: Check subclassing of erasures e.g. Collection & Set - if (definition.getEnv().isSameType(cardinalityErasure, thisErasure)) { + if (definition.getEnv().getTypeUtils().isAssignable(cardinalityErasure, thisErasure)) { return; } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index 52feac4a5..20741cd3a 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -38,6 +38,7 @@ import com.inrupt.rdf.wrapping.annotation.*; import java.net.URI; +import java.util.Collection; import java.util.Set; import java.util.UUID; @@ -93,13 +94,20 @@ void test() { assertThat(myDataset.anonymous().instance().label(), is(1)); assertThat(myDataset.anonymous().instance().uri(), is(U)); - assertThat(myDataset.anonymous().instance().many1(), contains(2, 3)); assertThat(myDataset.anonymous().instance().many2(), contains(2, 3)); assertThat(myDataset.anonymous().instance().many3(), contains(2, 3)); assertThat(myDataset.anonymous().instance().many4(), contains(2, 3)); assertThat(myDataset.anonymous().instance().many5(), contains(2, 3)); assertThat(myDataset.anonymous().instance().many6(), contains(2, 3)); assertThat(myDataset.anonymous().instance().many7(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many8(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many10(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many11(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many12(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many13(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many14(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many15(), contains(2, 3)); + assertThat(myDataset.anonymous().instance().many16(), contains(2, 3)); assertThat(myDataset.anonymous().instance().child().label(), is(4)); assertThrows(Throwable.class, () -> myDataset.anonymous().instance().throwing()); assertThat(myDataset.anonymous().instance().childLabel(), is(4)); @@ -178,53 +186,52 @@ interface MyResource { String throwing(); @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) - Set many1(); + Set many1(); @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Set many2(); @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) - Set many3(); + Set many3(); @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) - Set many4(); + Set many4(); @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Set many5(); @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) - Set many6(); + Set many6(); @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) - Set many7(); + Set many7(); @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) - Set many8(); + Set many8(); -// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY) -// Set many7(); -// -// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY) -// Set many8(); -// -// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY) -// Set many9(); + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Collection many9(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Collection many10(); + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Collection many11(); -// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) -// Collection many21(); -// -// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) -// Collection many22(); -// -// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) -// Collection many23(); -// -// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) -// Collection many24(); -// -// @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) -// Collection many25(); + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Collection many12(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Collection many13(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Collection many14(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Collection many15(); + + @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) + Collection many16(); @ResourceProperty(value = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) void overwrite(Integer value); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 8e3377ddb..5994ee299 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -92,7 +92,6 @@ private static Stream compilationErrorOnInvalid() { arguments("resource complex property method is void", MUST_NOT_BE_VOID), arguments("resource plural property method erasure differs", "must have same erasure as return type"), - arguments("resource plural property method erasure super", "must have same erasure as return type"), arguments( "resource plural property method type argument differs", "must have type argument assignable from type argument of return type") @@ -125,18 +124,12 @@ private static Stream compilationSucceeds() { arguments("resource extends nothing"), arguments("resource extends Resource"), - arguments("resource property method is assignable instance"), arguments("resource unannotated method is static"), arguments("resource unannotated method is default"), arguments("resource complex property method is resource instance"), arguments("resource complex property method recursive"), - arguments("resource plural property method"), - arguments("resource plural property method raw"), - arguments("resource plural property method extends"), - arguments("resource plural property method super"), - arguments("resource plural property method wildcard"), - arguments("resource plural property method type argument super") + arguments("resource plural primitive property") ); } } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java b/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java deleted file mode 100644 index 9b1f58d6f..000000000 --- a/processor/src/test/resources/validationExamples/bad/resource plural property method erasure super.java +++ /dev/null @@ -1,14 +0,0 @@ -// This file is compiled only in test. -package x; - -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - -import com.inrupt.rdf.wrapping.annotation.Resource; -import com.inrupt.rdf.wrapping.annotation.ResourceProperty; - -@Resource -interface X { - @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) - Iterable x(); -} diff --git a/processor/src/test/resources/validationExamples/good/resource plural primitive property.java b/processor/src/test/resources/validationExamples/good/resource plural primitive property.java new file mode 100644 index 000000000..c472b190d --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource plural primitive property.java @@ -0,0 +1,62 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +import java.util.Collection; +import java.util.Set; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x1(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x2(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x3(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x4(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x5(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x6(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x7(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Set x8(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Collection x9(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Collection x10(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Collection x11(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Collection x12(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Collection x13(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Collection x14(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Collection x15(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) + Collection x16(); +} diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method extends.java b/processor/src/test/resources/validationExamples/good/resource plural property method extends.java deleted file mode 100644 index 4df8b9a85..000000000 --- a/processor/src/test/resources/validationExamples/good/resource plural property method extends.java +++ /dev/null @@ -1,16 +0,0 @@ -// This file is compiled only in test. -package x; - -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - -import com.inrupt.rdf.wrapping.annotation.Resource; -import com.inrupt.rdf.wrapping.annotation.ResourceProperty; - -import java.util.Set; - -@Resource -interface X { - @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) - Set x(); -} diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method raw.java b/processor/src/test/resources/validationExamples/good/resource plural property method raw.java deleted file mode 100644 index 84d939867..000000000 --- a/processor/src/test/resources/validationExamples/good/resource plural property method raw.java +++ /dev/null @@ -1,16 +0,0 @@ -// This file is compiled only in test. -package x; - -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - -import com.inrupt.rdf.wrapping.annotation.Resource; -import com.inrupt.rdf.wrapping.annotation.ResourceProperty; - -import java.util.Set; - -@Resource -interface X { - @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) - Set x(); -} diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method super.java b/processor/src/test/resources/validationExamples/good/resource plural property method super.java deleted file mode 100644 index 5724fe475..000000000 --- a/processor/src/test/resources/validationExamples/good/resource plural property method super.java +++ /dev/null @@ -1,16 +0,0 @@ -// This file is compiled only in test. -package x; - -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - -import com.inrupt.rdf.wrapping.annotation.Resource; -import com.inrupt.rdf.wrapping.annotation.ResourceProperty; - -import java.util.Set; - -@Resource -interface X { - @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) - Set x(); -} diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method type argument super.java b/processor/src/test/resources/validationExamples/good/resource plural property method type argument super.java deleted file mode 100644 index 2ee8e6077..000000000 --- a/processor/src/test/resources/validationExamples/good/resource plural property method type argument super.java +++ /dev/null @@ -1,16 +0,0 @@ -// This file is compiled only in test. -package x; - -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - -import com.inrupt.rdf.wrapping.annotation.Resource; -import com.inrupt.rdf.wrapping.annotation.ResourceProperty; - -import java.util.Set; - -@Resource -interface X { - @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) - Set x(); -} diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method wildcard.java b/processor/src/test/resources/validationExamples/good/resource plural property method wildcard.java deleted file mode 100644 index 4eed8994a..000000000 --- a/processor/src/test/resources/validationExamples/good/resource plural property method wildcard.java +++ /dev/null @@ -1,16 +0,0 @@ -// This file is compiled only in test. -package x; - -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - -import com.inrupt.rdf.wrapping.annotation.Resource; -import com.inrupt.rdf.wrapping.annotation.ResourceProperty; - -import java.util.Set; - -@Resource -interface X { - @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY, valueMapping = IRI_AS_STRING) - Set x(); -} diff --git a/processor/src/test/resources/validationExamples/good/resource plural property method.java b/processor/src/test/resources/validationExamples/good/resource plural property method.java deleted file mode 100644 index 8b8df5fed..000000000 --- a/processor/src/test/resources/validationExamples/good/resource plural property method.java +++ /dev/null @@ -1,16 +0,0 @@ -// This file is compiled only in test. -package x; - -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECT_ITERATOR; -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - -import com.inrupt.rdf.wrapping.annotation.Resource; -import com.inrupt.rdf.wrapping.annotation.ResourceProperty; - -import java.util.Iterator; - -@Resource -interface X { - @ResourceProperty(value = "x", cardinality = OBJECT_ITERATOR, valueMapping = IRI_AS_STRING) - Iterator x(); -} diff --git a/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java b/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java deleted file mode 100644 index d008667d8..000000000 --- a/processor/src/test/resources/validationExamples/good/resource property method is assignable instance.java +++ /dev/null @@ -1,13 +0,0 @@ -// This file is compiled only in test. -package x; - -import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.IRI_AS_STRING; - -import com.inrupt.rdf.wrapping.annotation.Resource; -import com.inrupt.rdf.wrapping.annotation.ResourceProperty; - -@Resource -interface X { - @ResourceProperty(value = "x", valueMapping = IRI_AS_STRING) - Object x(); -} From a9113669207d992a2281ef161a4544d536849579 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Tue, 12 Mar 2024 22:27:58 +0000 Subject: [PATCH 119/141] Simplify resource definition --- .../wrapping/processor/ResourceDefinition.java | 16 ++++++++++------ .../wrapping/processor/ResourceValidator.java | 15 +++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index e0e3c4bf8..ac4d64ec4 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -39,10 +39,8 @@ class ResourceDefinition extends Definition { private static final Predicate isComplex = p -> p.valueMapping().isComplex(); private static final Predicate isPlural = p -> p.cardinality().isPlural(); - private final Predicate returnsResource = p -> - getEnv().type(p.getReturnType()).getAnnotation(Resource.class) != null; - static final Predicate isSetter = p -> p.cardinality().isSetter(); - static final Predicate isVoid = p -> p.getReturnType().getKind() == VOID; + private final Predicate isSetter = p -> p.cardinality().isSetter(); + private final Predicate isVoid = p -> p.getReturnType().getKind() == VOID; ResourceDefinition(final TypeElement element, final Environment env) { super(element, env, Resource.class); @@ -51,13 +49,13 @@ class ResourceDefinition extends Definition { Stream primitiveProperties() { return properties() .filter(not(isSetter)) - .filter(not(returnsResource)); + .filter(not(isComplex)); } Stream resourceProperties() { return properties() .filter(not(isSetter)) - .filter(returnsResource); + .filter(isComplex); } Stream complexMappingProperties() { @@ -85,6 +83,12 @@ Stream primitivePluralProperties() { .filter(isPlural); } + Stream voidGetters() { + return properties() + .filter(not(isSetter)) + .filter(isVoid); + } + Stream transitiveResourceTypes() { final Queue outstanding = new LinkedList<>(); final Set results = new HashSet<>(); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 00df7ca14..9ac95ed76 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -21,8 +21,6 @@ package com.inrupt.rdf.wrapping.processor; import static com.inrupt.rdf.wrapping.processor.PredicateShim.not; -import static com.inrupt.rdf.wrapping.processor.ResourceDefinition.isSetter; -import static com.inrupt.rdf.wrapping.processor.ResourceDefinition.isVoid; import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @@ -67,14 +65,11 @@ protected void validateInternal() { } private void requireNonVoidReturnType() { - definition.properties() - .filter(not(isSetter)) - .filter(isVoid) - .forEach(method -> - errors.add(new ValidationError( - method.element, - "Method [%s] must not be void", - method.getName()))); + definition.voidGetters().forEach(method -> + errors.add(new ValidationError( + method.element, + "Method [%s] must not be void", + method.getName()))); } private void requireCompatiblePrimitiveReturnType() { From ff5171cd48492f9333df316ae54d890e3ac116c8 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Tue, 12 Mar 2024 23:50:40 +0000 Subject: [PATCH 120/141] Handle plural complex resource properties --- .../processor/ResourceDefinition.java | 7 ++++ .../processor/ResourceImplementor.java | 33 ++++++++++++++++--- .../rdf/wrapping/processor/E2ETest.java | 27 ++++++++------- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index ac4d64ec4..f165f797a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -54,6 +54,7 @@ Stream primitiveProperties() { Stream resourceProperties() { return properties() + .filter(not(isPlural)) .filter(not(isSetter)) .filter(isComplex); } @@ -83,6 +84,12 @@ Stream primitivePluralProperties() { .filter(isPlural); } + Stream complexPlurals() { + return properties() + .filter(isComplex) + .filter(isPlural); + } + Stream voidGetters() { return properties() .filter(not(isSetter)) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 5223ba3e1..3d6dc27c1 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -30,6 +30,9 @@ import com.inrupt.rdf.wrapping.jena.WrapperResource; import javax.annotation.Generated; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.WildcardType; import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.graph.Node; @@ -51,7 +54,7 @@ protected void implementInternal() { addPrimitivePropertyMethods(); addResourcePropertyMethods(); addOverwrite(); - // TODO: plural complex + addComplexPlural(); } private void addImports() { @@ -97,11 +100,24 @@ private void addPrimitivePropertyMethods() { } private void addResourcePropertyMethods() { - definition.resourceProperties().forEach(p -> { - final JType implementation = asImplementation(p.getReturnType()); - final JCall mapping = $t(ValueMappings.class).call("as").arg(implementation._class()); + definition.resourceProperties().forEach(p -> + addComplex(p, p.getReturnType())); + } - addPropertyMethod(p, mapping); + // TODO: Validate + // TODO: Cover + private void addComplexPlural() { + definition.complexPlurals().forEach(p -> { + final DeclaredType thisReturn = (DeclaredType) p.getReturnType(); + + final TypeMirror typeArg = thisReturn.getTypeArguments().stream() + .filter(WildcardType.class::isInstance) + .map(WildcardType.class::cast) + .map(WildcardType::getExtendsBound) + .findAny() + .orElse(null); + + addComplex(p, typeArg); }); } @@ -121,6 +137,13 @@ private void addOverwrite() { }); } + private void addComplex(final ResourcePropertyDefinition definition, final TypeMirror type) { + final JType implementation = asImplementation(type); + final JCall mapping = $t(ValueMappings.class).call("as").arg(implementation._class()); + + addPropertyMethod(definition, mapping); + } + private void addPropertyMethod(final ResourcePropertyDefinition p, final JExpr mapping) { final JCall predicate = call("getModel").call("createProperty").arg(str(p.predicate())); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index 20741cd3a..08ba1aaa2 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -31,8 +31,7 @@ import static org.apache.commons.io.IOUtils.toInputStream; import static org.apache.jena.riot.Lang.TRIG; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThrows; import com.inrupt.rdf.wrapping.annotation.*; @@ -92,7 +91,7 @@ void setUp() { void test() { final MyDataset myDataset = MyDataset.wrap(DATASET); - assertThat(myDataset.anonymous().instance().label(), is(1)); + assertThat(myDataset.anonymous().instance().getLabel(), is(1)); assertThat(myDataset.anonymous().instance().uri(), is(U)); assertThat(myDataset.anonymous().instance().many2(), contains(2, 3)); assertThat(myDataset.anonymous().instance().many3(), contains(2, 3)); @@ -108,13 +107,14 @@ void test() { assertThat(myDataset.anonymous().instance().many14(), contains(2, 3)); assertThat(myDataset.anonymous().instance().many15(), contains(2, 3)); assertThat(myDataset.anonymous().instance().many16(), contains(2, 3)); - assertThat(myDataset.anonymous().instance().child().label(), is(4)); + assertThat(myDataset.anonymous().instance().child().getLabel(), is(4)); + assertThat(myDataset.anonymous().instance().children(), contains(hasProperty("label", is(4)))); assertThrows(Throwable.class, () -> myDataset.anonymous().instance().throwing()); assertThat(myDataset.anonymous().instance().childLabel(), is(4)); - assertThat(myDataset.anonymous().subject().label(), is(1)); - assertThat(myDataset.anonymous().object().label(), is(4)); + assertThat(myDataset.anonymous().subject().getLabel(), is(1)); + assertThat(myDataset.anonymous().object().getLabel(), is(4)); assertThat(myDataset.anonymous().label(), is(1)); - assertThat(myDataset.named().instance().label(), is(5)); + assertThat(myDataset.named().instance().getLabel(), is(5)); assertThat(myDataset.label(), is(5)); assertThat(MyDataset.constant(), is(STATIC)); @@ -122,7 +122,7 @@ void test() { assertThat(MyResource.constant(), is(STATIC)); myDataset.anonymous().instance().overwrite(999); - assertThat(myDataset.anonymous().instance().label(), is(999)); + assertThat(myDataset.anonymous().instance().getLabel(), is(999)); } } @@ -145,7 +145,7 @@ static UUID constant() { // Dataset definitions support default methods. default Integer label() { - return named().instance().label(); + return named().instance().getLabel(); } } @@ -167,14 +167,14 @@ static UUID constant() { // Graph definitions support default methods. default Integer label() { - return instance().label(); + return instance().getLabel(); } } @Resource interface MyResource { @ResourceProperty(value = LABEL, valueMapping = LITERAL_AS_INTEGER_OR_NULL) - Integer label(); + Integer getLabel(); @ResourceProperty(value = IRI, valueMapping = IRI_AS_URI) URI uri(); @@ -182,6 +182,9 @@ interface MyResource { @ResourceProperty(CHILD) MyResource child(); + @ResourceProperty(value = CHILD, cardinality = OBJECTS_READ_ONLY) + Set children(); + @ResourceProperty(value = THROWING, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) String throwing(); @@ -243,6 +246,6 @@ static UUID constant() { // Resource definitions support default methods. default Integer childLabel() { - return child().label(); + return child().getLabel(); } } From c8017697fedabd676f9a204df9831039ba1a2a81 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 17 Mar 2024 14:56:56 +0000 Subject: [PATCH 121/141] Validate plural complex resource properties --- .../processor/ResourceImplementor.java | 8 +- .../wrapping/processor/ResourceValidator.java | 128 +++++++++++++++++- .../rdf/wrapping/processor/E2ETest.java | 8 +- .../rdf/wrapping/processor/ValidatorTest.java | 9 +- .../resource plural complex incompatible.java | 15 ++ .../bad/resource plural complex specific.java | 15 ++ .../resource plural complex unbounded.java | 15 ++ .../resource plural plural complex raw.java | 15 ++ .../resource plural complex property.java | 19 +++ 9 files changed, 220 insertions(+), 12 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/bad/resource plural complex incompatible.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource plural complex specific.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource plural complex unbounded.java create mode 100644 processor/src/test/resources/validationExamples/bad/resource plural plural complex raw.java create mode 100644 processor/src/test/resources/validationExamples/good/resource plural complex property.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 3d6dc27c1..689018e24 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -104,18 +104,16 @@ private void addResourcePropertyMethods() { addComplex(p, p.getReturnType())); } - // TODO: Validate // TODO: Cover private void addComplexPlural() { definition.complexPlurals().forEach(p -> { final DeclaredType thisReturn = (DeclaredType) p.getReturnType(); final TypeMirror typeArg = thisReturn.getTypeArguments().stream() - .filter(WildcardType.class::isInstance) - .map(WildcardType.class::cast) + .map(WildcardType.class::cast) // safe due to validator .map(WildcardType::getExtendsBound) - .findAny() - .orElse(null); + .findFirst() + .get(); // safe due to validator addComplex(p, typeArg); }); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 9ac95ed76..9efd14ee4 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -21,6 +21,7 @@ package com.inrupt.rdf.wrapping.processor; import static com.inrupt.rdf.wrapping.processor.PredicateShim.not; +import static javax.lang.model.type.TypeKind.WILDCARD; import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.annotation.ResourceProperty; @@ -61,7 +62,10 @@ protected void validateInternal() { requirePluralErasure(); requirePluralTypeArgument(); - // TODO: plural complex + requirePluralComplexNotRaw(); + requirePluralComplexWildcard(); + requirePluralComplexExtend(); + requirePluralCompatible(); } private void requireNonVoidReturnType() { @@ -132,12 +136,14 @@ private void requirePluralTypeArgument() { definition.primitivePluralProperties().forEach(p -> { final DeclaredType thisReturn = (DeclaredType) p.getReturnType(); - // raw generic or not generic + // Ignore return types lacking generic type arguments if (thisReturn.getTypeArguments().isEmpty()) { return; } - final boolean hasWildcard = thisReturn.getTypeArguments().stream().anyMatch(WildcardType.class::isInstance); + final boolean hasWildcard = thisReturn.getTypeArguments().stream() + .map(TypeMirror::getKind) + .anyMatch(WILDCARD::equals); // wildcard if (hasWildcard && thisReturn.getTypeArguments().stream() @@ -178,6 +184,122 @@ private void requirePluralTypeArgument() { }); } + private void requirePluralComplexNotRaw() { + definition.complexPlurals().forEach(p -> { + final DeclaredType thisReturn = (DeclaredType) p.getReturnType(); + + // Require return types to be generic and not raw. + if (!thisReturn.getTypeArguments().isEmpty()) { + return; + } + + errors.add(new ValidationError( + p.element, + "Return type [%s] of [%s] cannot be raw", + thisReturn, + p.getName())); + }); + } + + private void requirePluralComplexWildcard() { + definition.complexPlurals().forEach(p -> { + final DeclaredType thisReturn = (DeclaredType) p.getReturnType(); + + // Ignore return types lacking generic type arguments + if (thisReturn.getTypeArguments().isEmpty()) { + return; + } + + // Require return type generic arguments to be wildcards. + if (thisReturn.getTypeArguments().stream() + .map(TypeMirror::getKind) + .allMatch(WILDCARD::equals)) { + return; + } + + errors.add(new ValidationError( + p.element, + "Return type [%s] of [%s] must have wildcard type argument", + thisReturn, + p.getName())); + }); + } + + private void requirePluralComplexExtend() { + definition.complexPlurals().forEach(p -> { + final DeclaredType thisReturn = (DeclaredType) p.getReturnType(); + + // Ignore return types lacking generic type arguments + if (thisReturn.getTypeArguments().isEmpty()) { + return; + } + + // Ignore return types with non-wildcard type arguments + if (thisReturn.getTypeArguments().stream() + .map(TypeMirror::getKind) + .anyMatch(not(WILDCARD::equals))) { + return; + } + + // Require return type generic arguments to have upper bounds. + if (thisReturn.getTypeArguments().stream() + .map(WildcardType.class::cast) + .map(WildcardType::getExtendsBound) + .allMatch(Objects::nonNull)) { + return; + } + + errors.add(new ValidationError( + p.element, + "Return type [%s] of [%s] must have upper bounded type argument", + thisReturn, + p.getName())); + }); + } + + private void requirePluralCompatible() { + definition.complexPlurals().forEach(p -> { + final DeclaredType thisReturn = (DeclaredType) p.getReturnType(); + + // Ignore return types lacking generic type arguments + if (thisReturn.getTypeArguments().isEmpty()) { + return; + } + + // Ignore return types with non-wildcard type arguments + if (thisReturn.getTypeArguments().stream() + .map(TypeMirror::getKind) + .anyMatch(not(WILDCARD::equals))) { + return; + } + + // Ignore return types with type arguments that are not upper bounded + if (thisReturn.getTypeArguments().stream() + .map(WildcardType.class::cast) + .map(WildcardType::getExtendsBound) + .anyMatch(Objects::isNull)) { + return; + } + + // Require return type generic argument upper bounds to be appropriately annotated, because they will be + // used by implementor to calculate projection class for value mapping of complex plural resource + // properties. + if (thisReturn.getTypeArguments().stream() + .map(WildcardType.class::cast) + .map(WildcardType::getExtendsBound) + .map(definition::typeOf) + .map(a -> a.getAnnotation(Resource.class)) + .allMatch(Objects::nonNull)) { + return; + } + + errors.add(new ValidationError( + p.element, + "Plural complex resource property must return a generic type whose argument has upper bound " + + "annotated with @Resource")); + }); + } + private TypeMirror returnTypeOf(final String mappingMethod, final Class clazz) { return definition.getEnv().methodsOf(clazz) .filter(method -> method.getSimpleName().contentEquals(mappingMethod)) diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index 08ba1aaa2..f14f9d994 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -108,7 +108,8 @@ void test() { assertThat(myDataset.anonymous().instance().many15(), contains(2, 3)); assertThat(myDataset.anonymous().instance().many16(), contains(2, 3)); assertThat(myDataset.anonymous().instance().child().getLabel(), is(4)); - assertThat(myDataset.anonymous().instance().children(), contains(hasProperty("label", is(4)))); + assertThat(myDataset.anonymous().instance().children1(), contains(hasProperty("label", is(4)))); + assertThat(myDataset.anonymous().instance().children2(), contains(hasProperty("label", is(4)))); assertThrows(Throwable.class, () -> myDataset.anonymous().instance().throwing()); assertThat(myDataset.anonymous().instance().childLabel(), is(4)); assertThat(myDataset.anonymous().subject().getLabel(), is(1)); @@ -183,7 +184,10 @@ interface MyResource { MyResource child(); @ResourceProperty(value = CHILD, cardinality = OBJECTS_READ_ONLY) - Set children(); + Set children1(); + + @ResourceProperty(value = CHILD, cardinality = OBJECTS_READ_ONLY) + Collection children2(); @ResourceProperty(value = THROWING, cardinality = ANY_OR_THROW, valueMapping = LITERAL_AS_STRING) String throwing(); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 5994ee299..3fbb775a1 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -94,7 +94,11 @@ private static Stream compilationErrorOnInvalid() { arguments("resource plural property method erasure differs", "must have same erasure as return type"), arguments( "resource plural property method type argument differs", - "must have type argument assignable from type argument of return type") + "must have type argument assignable from type argument of return type"), + arguments("resource plural plural complex raw", "cannot be raw"), + arguments("resource plural complex specific", "must have wildcard type argument"), + arguments("resource plural complex unbounded", "must have upper bounded type argument"), + arguments("resource plural complex incompatible", "argument has upper bound annotated with @Resource") ); } @@ -129,7 +133,8 @@ private static Stream compilationSucceeds() { arguments("resource complex property method is resource instance"), arguments("resource complex property method recursive"), - arguments("resource plural primitive property") + arguments("resource plural primitive property"), + arguments("resource plural complex property") ); } } diff --git a/processor/src/test/resources/validationExamples/bad/resource plural complex incompatible.java b/processor/src/test/resources/validationExamples/bad/resource plural complex incompatible.java new file mode 100644 index 000000000..376d8aec9 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource plural complex incompatible.java @@ -0,0 +1,15 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +import java.util.Set; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY) + Set x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/resource plural complex specific.java b/processor/src/test/resources/validationExamples/bad/resource plural complex specific.java new file mode 100644 index 000000000..d44ad4760 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource plural complex specific.java @@ -0,0 +1,15 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +import java.util.Set; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY) + Set x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/resource plural complex unbounded.java b/processor/src/test/resources/validationExamples/bad/resource plural complex unbounded.java new file mode 100644 index 000000000..f75ce6756 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource plural complex unbounded.java @@ -0,0 +1,15 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +import java.util.Set; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY) + Set x(); +} diff --git a/processor/src/test/resources/validationExamples/bad/resource plural plural complex raw.java b/processor/src/test/resources/validationExamples/bad/resource plural plural complex raw.java new file mode 100644 index 000000000..bcc8f3cf1 --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource plural plural complex raw.java @@ -0,0 +1,15 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +import java.util.Set; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY) + Set x(); +} diff --git a/processor/src/test/resources/validationExamples/good/resource plural complex property.java b/processor/src/test/resources/validationExamples/good/resource plural complex property.java new file mode 100644 index 000000000..804ad5d4a --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource plural complex property.java @@ -0,0 +1,19 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OBJECTS_READ_ONLY; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +import java.util.Collection; +import java.util.Set; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY) + Set x1(); + + @ResourceProperty(value = "x", cardinality = OBJECTS_READ_ONLY) + Collection x2(); +} From 4fa2646079c400eaa1c15c2ee2b7854b1828d304 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 17 Mar 2024 16:54:11 +0000 Subject: [PATCH 122/141] Handle all mutators --- .../rdf/wrapping/annotation/ResourceProperty.java | 6 +++++- .../rdf/wrapping/processor/ResourceImplementor.java | 5 ++--- .../com/inrupt/rdf/wrapping/processor/E2ETest.java | 10 ++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java index b502d149b..1ec89bcc1 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java @@ -100,7 +100,11 @@ enum Cardinality { OBJECT_STREAM("objectStream", true, false), - OVERWRITE("overwrite", false, true); + OVERWRITE("overwrite", false, true), + + OVERWRITE_NULLABLE("overwriteNullable", false, true), + + ADD("add", false, true); private final String methodName; private final boolean plural; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 689018e24..ce8120022 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -53,7 +53,7 @@ protected void implementInternal() { addConstructor(); addPrimitivePropertyMethods(); addResourcePropertyMethods(); - addOverwrite(); + addMutators(); addComplexPlural(); } @@ -121,8 +121,7 @@ private void addComplexPlural() { // TODO: Validate // TODO: Cover - // TODO: Other mutators - private void addOverwrite() { + private void addMutators() { definition.setterProperties().forEach(p -> { final JCall predicate = call("getModel").call("createProperty").arg(str(p.predicate())); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index f14f9d994..56654b307 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -124,6 +124,10 @@ void test() { myDataset.anonymous().instance().overwrite(999); assertThat(myDataset.anonymous().instance().getLabel(), is(999)); + myDataset.anonymous().instance().overwriteNullable((Integer) null); + assertThat(myDataset.anonymous().instance().getLabel(), is(nullValue())); + myDataset.anonymous().instance().add(888); + assertThat(myDataset.anonymous().instance().getLabel(), is(888)); } } @@ -243,6 +247,12 @@ interface MyResource { @ResourceProperty(value = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) void overwrite(Integer value); + @ResourceProperty(value = LABEL, cardinality = OVERWRITE_NULLABLE, nodeMapping = AS_TYPED_LITERAL) + void overwriteNullable(Integer value); + + @ResourceProperty(value = LABEL, cardinality = ADD, nodeMapping = AS_TYPED_LITERAL) + void add(Integer value); + // Resource definitions support static methods. static UUID constant() { return STATIC; From 5c08deb03395ef2191a7d28edf9226450ae08050 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 17 Mar 2024 17:00:54 +0000 Subject: [PATCH 123/141] Handle plural mutators --- .../processor/ResourceImplementor.java | 22 +++++++++++++------ .../rdf/wrapping/processor/E2ETest.java | 16 ++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index ce8120022..15733ff9d 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -22,7 +22,7 @@ import static org.jboss.jdeparser.JExprs.*; import static org.jboss.jdeparser.JMod.*; -import static org.jboss.jdeparser.JTypes.$t; +import static org.jboss.jdeparser.JTypes.typeOf; import com.inrupt.rdf.wrapping.jena.NodeMappings; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; @@ -78,7 +78,7 @@ private void addFactoryField() { STATIC | FINAL, org.apache.jena.enhanced.Implementation.class, FACTORY, - $t(UriOrBlankFactory.class)._new().arg($t(target).methodRef("new"))); + typeOf(UriOrBlankFactory.class)._new().arg(typeOf(target).methodRef("new"))); } private void addConstructor() { @@ -93,7 +93,7 @@ private void addConstructor() { private void addPrimitivePropertyMethods() { definition.primitiveProperties().forEach(p -> { - final JExpr mapping = $t(ValueMappings.class).methodRef(p.valueMappingMethod()); + final JExpr mapping = typeOf(ValueMappings.class).methodRef(p.valueMappingMethod()); addPropertyMethod(p, mapping); }); @@ -125,18 +125,26 @@ private void addMutators() { definition.setterProperties().forEach(p -> { final JCall predicate = call("getModel").call("createProperty").arg(str(p.predicate())); - final JExpr mapping = $t(NodeMappings.class).methodRef(p.nodeMappingMethod()); + final JExpr mapping = typeOf(NodeMappings.class).methodRef(p.nodeMappingMethod()); final JMethodDef m = addMethod(p); - final JParamDeclaration value = m.param(FINAL, JTypes.typeOf(p.getValueParamType()), "value"); + final DeclaredType valueArgType = (DeclaredType)p.getValueParamType(); + final JParamDeclaration value = m.param(FINAL, typeOf(valueArgType), "value"); - m.body().call(p.cardinalityMethod()).arg(predicate).arg($v(value)).arg(mapping); + final JCall call = m.body().call(typeOf(target)._super(), p.cardinalityMethod()); + + valueArgType.getTypeArguments().stream() + .findFirst() + .ifPresent(typeMirror -> + call.typeArg(typeOf(typeMirror))); + + call.arg(predicate).arg($v(value)).arg(mapping); }); } private void addComplex(final ResourcePropertyDefinition definition, final TypeMirror type) { final JType implementation = asImplementation(type); - final JCall mapping = $t(ValueMappings.class).call("as").arg(implementation._class()); + final JCall mapping = typeOf(ValueMappings.class).call("as").arg(implementation._class()); addPropertyMethod(definition, mapping); } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index 56654b307..e424a26cb 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -27,6 +27,7 @@ import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.NodeMapping.AS_TYPED_LITERAL; import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.ValueMapping.*; import static com.inrupt.rdf.wrapping.processor.E2ETest.*; +import static java.util.Collections.singletonList; import static java.util.UUID.randomUUID; import static org.apache.commons.io.IOUtils.toInputStream; import static org.apache.jena.riot.Lang.TRIG; @@ -128,6 +129,12 @@ void test() { assertThat(myDataset.anonymous().instance().getLabel(), is(nullValue())); myDataset.anonymous().instance().add(888); assertThat(myDataset.anonymous().instance().getLabel(), is(888)); + myDataset.anonymous().instance().overwrite(singletonList(777)); + assertThat(myDataset.anonymous().instance().getLabel(), is(777)); + myDataset.anonymous().instance().overwriteNullable((Iterable) null); + assertThat(myDataset.anonymous().instance().getLabel(), is(nullValue())); + myDataset.anonymous().instance().add(singletonList(666)); + assertThat(myDataset.anonymous().instance().getLabel(), is(666)); } } @@ -253,6 +260,15 @@ interface MyResource { @ResourceProperty(value = LABEL, cardinality = ADD, nodeMapping = AS_TYPED_LITERAL) void add(Integer value); + @ResourceProperty(value = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) + void overwrite(Iterable value); + + @ResourceProperty(value = LABEL, cardinality = OVERWRITE_NULLABLE, nodeMapping = AS_TYPED_LITERAL) + void overwriteNullable(Iterable value); + + @ResourceProperty(value = LABEL, cardinality = ADD, nodeMapping = AS_TYPED_LITERAL) + void add(Iterable value); + // Resource definitions support static methods. static UUID constant() { return STATIC; From cc91b054bd25d870d25805fa577692df37a5f35f Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 17 Mar 2024 22:52:45 +0000 Subject: [PATCH 124/141] Handle singular and forbid plural complex mutators --- .../processor/ResourceImplementor.java | 13 ++++++- .../wrapping/processor/ResourceValidator.java | 23 +++++++++++ .../rdf/wrapping/processor/E2ETest.java | 21 +++++++--- .../rdf/wrapping/processor/ValidatorTest.java | 6 ++- .../bad/resource mutator plural complex.java | 13 +++++++ .../good/resource mutator.java | 39 +++++++++++++++++++ 6 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 processor/src/test/resources/validationExamples/bad/resource mutator plural complex.java create mode 100644 processor/src/test/resources/validationExamples/good/resource mutator.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 15733ff9d..4295b9b82 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -24,6 +24,7 @@ import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JTypes.typeOf; +import com.inrupt.rdf.wrapping.annotation.Resource; import com.inrupt.rdf.wrapping.jena.NodeMappings; import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; import com.inrupt.rdf.wrapping.jena.ValueMappings; @@ -36,6 +37,7 @@ import org.apache.jena.enhanced.EnhGraph; import org.apache.jena.graph.Node; +import org.apache.jena.rdf.model.RDFNode; import org.jboss.jdeparser.*; class ResourceImplementor extends Implementor { @@ -128,9 +130,16 @@ private void addMutators() { final JExpr mapping = typeOf(NodeMappings.class).methodRef(p.nodeMappingMethod()); final JMethodDef m = addMethod(p); - final DeclaredType valueArgType = (DeclaredType)p.getValueParamType(); + final DeclaredType valueArgType = (DeclaredType) p.getValueParamType(); final JParamDeclaration value = m.param(FINAL, typeOf(valueArgType), "value"); + final JExpr valueExpr; + if (definition.typeOf(valueArgType).getAnnotation(Resource.class) != null) { + valueExpr = name(value).cast(RDFNode.class); + } else { + valueExpr = name(value); + } + final JCall call = m.body().call(typeOf(target)._super(), p.cardinalityMethod()); valueArgType.getTypeArguments().stream() @@ -138,7 +147,7 @@ private void addMutators() { .ifPresent(typeMirror -> call.typeArg(typeOf(typeMirror))); - call.arg(predicate).arg($v(value)).arg(mapping); + call.arg(predicate).arg(valueExpr).arg(mapping); }); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 9efd14ee4..3f02f029a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -66,6 +66,8 @@ protected void validateInternal() { requirePluralComplexWildcard(); requirePluralComplexExtend(); requirePluralCompatible(); + + requireMutatorNoPluralComplex(); } private void requireNonVoidReturnType() { @@ -300,6 +302,27 @@ private void requirePluralCompatible() { }); } + private void requireMutatorNoPluralComplex() { + definition.setterProperties().forEach(p -> { + final DeclaredType valueArgType = (DeclaredType) p.getValueParamType(); + + // Ignore value params lacking generic type arguments + if (valueArgType.getTypeArguments().isEmpty()) { + return; + } + + // Ignore value params with primitive generic type arguments + if (valueArgType.getTypeArguments().stream() + .map(definition::typeOf) + .map(a -> a.getAnnotation(Resource.class)) + .allMatch(Objects::isNull)) { + return; + } + + errors.add(new ValidationError(p.element, "Plural complex setters are not supported")); + }); + } + private TypeMirror returnTypeOf(final String mappingMethod, final Class clazz) { return definition.getEnv().methodsOf(clazz) .filter(method -> method.getSimpleName().contentEquals(mappingMethod)) diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index e424a26cb..6fd82691b 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -251,21 +251,30 @@ interface MyResource { @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Collection many16(); + @ResourceProperty(value = LABEL, cardinality = OVERWRITE) + void overwrite(MyResource value); + @ResourceProperty(value = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) void overwrite(Integer value); - @ResourceProperty(value = LABEL, cardinality = OVERWRITE_NULLABLE, nodeMapping = AS_TYPED_LITERAL) - void overwriteNullable(Integer value); - - @ResourceProperty(value = LABEL, cardinality = ADD, nodeMapping = AS_TYPED_LITERAL) - void add(Integer value); - @ResourceProperty(value = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) void overwrite(Iterable value); + @ResourceProperty(value = LABEL, cardinality = OVERWRITE_NULLABLE) + void overwriteNullable(MyResource value); + + @ResourceProperty(value = LABEL, cardinality = OVERWRITE_NULLABLE, nodeMapping = AS_TYPED_LITERAL) + void overwriteNullable(Integer value); + @ResourceProperty(value = LABEL, cardinality = OVERWRITE_NULLABLE, nodeMapping = AS_TYPED_LITERAL) void overwriteNullable(Iterable value); + @ResourceProperty(value = LABEL, cardinality = ADD) + void add(MyResource value); + + @ResourceProperty(value = LABEL, cardinality = ADD, nodeMapping = AS_TYPED_LITERAL) + void add(Integer value); + @ResourceProperty(value = LABEL, cardinality = ADD, nodeMapping = AS_TYPED_LITERAL) void add(Iterable value); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java index 3fbb775a1..5fe9f9f16 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ValidatorTest.java @@ -98,7 +98,8 @@ private static Stream compilationErrorOnInvalid() { arguments("resource plural plural complex raw", "cannot be raw"), arguments("resource plural complex specific", "must have wildcard type argument"), arguments("resource plural complex unbounded", "must have upper bounded type argument"), - arguments("resource plural complex incompatible", "argument has upper bound annotated with @Resource") + arguments("resource plural complex incompatible", "argument has upper bound annotated with @Resource"), + arguments("resource mutator plural complex", "Plural complex setters are not supported") ); } @@ -134,7 +135,8 @@ private static Stream compilationSucceeds() { arguments("resource complex property method recursive"), arguments("resource plural primitive property"), - arguments("resource plural complex property") + arguments("resource plural complex property"), + arguments("resource mutator") ); } } diff --git a/processor/src/test/resources/validationExamples/bad/resource mutator plural complex.java b/processor/src/test/resources/validationExamples/bad/resource mutator plural complex.java new file mode 100644 index 000000000..067cc154f --- /dev/null +++ b/processor/src/test/resources/validationExamples/bad/resource mutator plural complex.java @@ -0,0 +1,13 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.OVERWRITE; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OVERWRITE) + void x(final Iterable value); +} diff --git a/processor/src/test/resources/validationExamples/good/resource mutator.java b/processor/src/test/resources/validationExamples/good/resource mutator.java new file mode 100644 index 000000000..1665672b0 --- /dev/null +++ b/processor/src/test/resources/validationExamples/good/resource mutator.java @@ -0,0 +1,39 @@ +// This file is compiled only in test. +package x; + +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.Cardinality.*; +import static com.inrupt.rdf.wrapping.annotation.ResourceProperty.NodeMapping.AS_TYPED_LITERAL; + +import com.inrupt.rdf.wrapping.annotation.Resource; +import com.inrupt.rdf.wrapping.annotation.ResourceProperty; + +@Resource +interface X { + @ResourceProperty(value = "x", cardinality = OVERWRITE) + void overwrite(final X value); + + @ResourceProperty(value = "x", cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) + void overwrite(final Integer value); + + @ResourceProperty(value = "x", cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) + void overwrite(final Iterable value); + + @ResourceProperty(value = "x", cardinality = OVERWRITE_NULLABLE) + void overwriteNullable(final X value); + + @ResourceProperty(value = "x", cardinality = OVERWRITE_NULLABLE, nodeMapping = AS_TYPED_LITERAL) + void overwriteNullable(final Integer value); + + @ResourceProperty(value = "x", cardinality = OVERWRITE_NULLABLE, nodeMapping = AS_TYPED_LITERAL) + void overwriteNullable(final Iterable value); + + + @ResourceProperty(value = "x", cardinality = ADD) + void add(final X value); + + @ResourceProperty(value = "x", cardinality = ADD, nodeMapping = AS_TYPED_LITERAL) + void add(final Integer value); + + @ResourceProperty(value = "x", cardinality = ADD, nodeMapping = AS_TYPED_LITERAL) + void add(final Iterable value); +} From fc5f76eece00fb5ecf930460924d3e458756e5da Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 17 Mar 2024 22:55:00 +0000 Subject: [PATCH 125/141] Tidy --- .../wrapping/processor/DatasetDefinition.java | 2 +- .../rdf/wrapping/processor/Definition.java | 4 +-- .../wrapping/processor/GraphDefinition.java | 2 +- .../rdf/wrapping/processor/Implementor.java | 4 +-- .../processor/PropertyDefinition.java | 2 +- .../processor/ResourceDefinition.java | 2 +- .../processor/ResourcePropertyDefinition.java | 4 +-- .../wrapping/processor/ResourceValidator.java | 26 ++++++++----------- .../wrapping/processor/ValidationError.java | 4 +++ .../rdf/wrapping/processor/Validator.java | 5 ++-- 10 files changed, 28 insertions(+), 27 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java index 7895eaabb..36cdb1f0b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetDefinition.java @@ -33,6 +33,6 @@ class DatasetDefinition extends Definition { } Stream properties() { - return membersAnnotatedWith(DatasetProperty.class).map(m -> new DatasetPropertyDefinition(m, env)); + return membersAnnotatedWith(DatasetProperty.class).map(m -> new DatasetPropertyDefinition(m, getEnv())); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java index c7841908e..994739eac 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java @@ -40,8 +40,8 @@ class Definition { static final Predicate isVoid = method -> method.getReturnType().getKind() == VOID; - protected final T element; - protected final Environment env; + private final T element; + private final Environment env; private final Class clazz; Definition(final T element, final Environment env, final Class clazz) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java index 2ddc1e14e..bf59a2887 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java @@ -36,7 +36,7 @@ class GraphDefinition extends Definition { } Stream properties() { - return membersAnnotatedWith(GraphProperty.class).map(m -> new GraphPropertyDefinition(m, env)); + return membersAnnotatedWith(GraphProperty.class).map(m -> new GraphPropertyDefinition(m, getEnv())); } Stream transitiveResourceTypes() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 8469ec5fc..1874b4258 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -96,8 +96,8 @@ protected void addClass(final Class clazz) { } protected JMethodDef addMethod(final Definition d) { - final String myName = d.element.getSimpleName().toString(); - final JType myType = typeOf(d.element.getReturnType()); + final String myName = d.getElement().getSimpleName().toString(); + final JType myType = typeOf(d.getElement().getReturnType()); final JMethodDef myMethod = target.method(PUBLIC, myType, myName); myMethod.annotate(Override.class); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/PropertyDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/PropertyDefinition.java index 0daaa5a83..aa754856b 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/PropertyDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/PropertyDefinition.java @@ -31,6 +31,6 @@ abstract class PropertyDefinition extends Definition outstanding) { } Stream properties() { - return membersAnnotatedWith(ResourceProperty.class).map(e -> new ResourcePropertyDefinition(e, env)); + return membersAnnotatedWith(ResourceProperty.class).map(e -> new ResourcePropertyDefinition(e, getEnv())); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java index d6b0e31a1..1c0552bfe 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java @@ -63,10 +63,10 @@ String nodeMappingMethod() { } Name getName() { - return element.getSimpleName(); + return getElement().getSimpleName(); } TypeMirror getValueParamType() { - return element.getParameters().get(0).asType(); + return getElement().getParameters().get(0).asType(); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 3f02f029a..5e02a96c2 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -46,10 +46,6 @@ class ResourceValidator extends Validator { protected void validateInternal() { requireInterface(); - // TODO: Allow definitions to extend WrapperResource. That means interface must be extracted from - // WrapperResource so definition can extend it. Also allow definitions to extend other definitions - // (interfaces annotated with @Resource). That requires implementor to follow suit. Both above apply to - // dataset and graph definitions as well limitBaseInterfaces(org.apache.jena.rdf.model.Resource.class); requireMemberMethods(ResourceProperty.class); @@ -73,7 +69,7 @@ protected void validateInternal() { private void requireNonVoidReturnType() { definition.voidGetters().forEach(method -> errors.add(new ValidationError( - method.element, + method, "Method [%s] must not be void", method.getName()))); } @@ -87,7 +83,7 @@ private void requireCompatiblePrimitiveReturnType() { } errors.add(new ValidationError( - p.element, + p, "Return type [%s] of [%s] must be assignable from return type [%s] of mapping [%s]", p.getReturnType(), p.getName(), @@ -98,14 +94,14 @@ private void requireCompatiblePrimitiveReturnType() { private void requireCompatibleComplexReturnType() { definition.complexMappingProperties().forEach(p -> { - final TypeElement returnType = definition.returnTypeOf(p.element); + final TypeElement returnType = definition.returnTypeOf(p.getElement()); if (returnType != null && returnType.getAnnotation(Resource.class) != null) { return; } errors.add(new ValidationError( - p.element, + p, "Method %s on interface %s must return @Resource interface", p.getName(), definition.getElement().getSimpleName())); @@ -125,7 +121,7 @@ private void requirePluralErasure() { } errors.add(new ValidationError( - p.element, + p, "Return type [%s] of [%s] must have same erasure as return type [%s] of cardinality [%s]", p.getReturnType(), p.getName(), @@ -176,7 +172,7 @@ private void requirePluralTypeArgument() { } errors.add(new ValidationError( - p.element, + p, "Return type [%s] of [%s] must have type argument assignable from " + "type argument of return type [%s] of mapping [%s]", thisReturn, @@ -196,7 +192,7 @@ private void requirePluralComplexNotRaw() { } errors.add(new ValidationError( - p.element, + p, "Return type [%s] of [%s] cannot be raw", thisReturn, p.getName())); @@ -220,7 +216,7 @@ private void requirePluralComplexWildcard() { } errors.add(new ValidationError( - p.element, + p, "Return type [%s] of [%s] must have wildcard type argument", thisReturn, p.getName())); @@ -252,7 +248,7 @@ private void requirePluralComplexExtend() { } errors.add(new ValidationError( - p.element, + p, "Return type [%s] of [%s] must have upper bounded type argument", thisReturn, p.getName())); @@ -296,7 +292,7 @@ private void requirePluralCompatible() { } errors.add(new ValidationError( - p.element, + p, "Plural complex resource property must return a generic type whose argument has upper bound " + "annotated with @Resource")); }); @@ -319,7 +315,7 @@ private void requireMutatorNoPluralComplex() { return; } - errors.add(new ValidationError(p.element, "Plural complex setters are not supported")); + errors.add(new ValidationError(p, "Plural complex setters are not supported")); }); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java index 1fc0c7e60..c6ec07682 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ValidationError.java @@ -29,6 +29,10 @@ class ValidationError { private final Element element; private final String msg; + ValidationError(final Definition definition, final String msg, final Object... args) { + this(definition.getElement(), msg, args); + } + ValidationError(final Element element, final String msg, final Object... args) { this.element = element; this.msg = String.format(msg, args); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index 624f80957..a75b9b1cd 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -98,6 +98,7 @@ protected final void requireNonMemberMethods(final Class.. definition.getElement().getSimpleName()))); } + // TODO: Allow definitions to extend other definitions. protected void limitBaseInterfaces(final Class allowed) { if (!definition.getElement().getKind().isInterface()) { return; @@ -109,7 +110,7 @@ protected void limitBaseInterfaces(final Class allowed) { } errors.add(new ValidationError( - definition.getElement(), + definition, "Interface %s can only extend %s or nothing", definition.getElement().getSimpleName(), allowed.getName())); @@ -122,7 +123,7 @@ protected void requireInterface() { } errors.add(new ValidationError( - definition.getElement(), + definition, "Element %s must be an interface but was a %s", definition.getElement().getSimpleName(), definition.getElement().getKind())); From d865d42dff2d1d8dd2347986225f01709a7bebd5 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Tue, 19 Mar 2024 21:48:17 +0000 Subject: [PATCH 126/141] Tidy --- .../com/inrupt/rdf/wrapping/processor/ResourceValidator.java | 2 +- .../resources/validationExamples/good/resource mutator.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 5e02a96c2..3980cd881 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -307,7 +307,7 @@ private void requireMutatorNoPluralComplex() { return; } - // Ignore value params with primitive generic type arguments + // Require generic type arguments to be primitive if (valueArgType.getTypeArguments().stream() .map(definition::typeOf) .map(a -> a.getAnnotation(Resource.class)) diff --git a/processor/src/test/resources/validationExamples/good/resource mutator.java b/processor/src/test/resources/validationExamples/good/resource mutator.java index 1665672b0..98be05f75 100644 --- a/processor/src/test/resources/validationExamples/good/resource mutator.java +++ b/processor/src/test/resources/validationExamples/good/resource mutator.java @@ -27,7 +27,6 @@ interface X { @ResourceProperty(value = "x", cardinality = OVERWRITE_NULLABLE, nodeMapping = AS_TYPED_LITERAL) void overwriteNullable(final Iterable value); - @ResourceProperty(value = "x", cardinality = ADD) void add(final X value); From 599fa3cc16b9e25401ec2ae796f10282ad09964b Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Tue, 19 Mar 2024 23:30:55 +0000 Subject: [PATCH 127/141] Support instantiating resource definitions --- .../rdf/wrapping/processor/Manager.java | 23 +++++++++++++++++++ .../rdf/wrapping/processor/E2ETest.java | 19 ++++++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java index bcce0e5b7..c8ff841f9 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java @@ -23,11 +23,15 @@ import static com.inrupt.rdf.wrapping.processor.Implementor.WRAP; import static com.inrupt.rdf.wrapping.processor.Implementor.asImplementation; +import com.inrupt.rdf.wrapping.annotation.Resource; + import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Objects; import org.apache.jena.query.Dataset; import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.RDFNode; /** * A utility class that aids wrapper interfaces to find generated implementations. @@ -44,6 +48,25 @@ public static T wrap(final Dataset original, final Class definition) { return wrap(original, definition, Dataset.class); } + // TODO: Tidy + // TODO: Cover + public static T create(final String name, final Class resource, final U graph) { + Objects.requireNonNull(resource); + Objects.requireNonNull(graph); + + if (resource.getAnnotation(Resource.class) == null) { + throw new RuntimeException("resource must be a definition"); + } + + if (!(graph instanceof Model)) { + throw new RuntimeException("graph must be a Model"); + } + + final Class rawImplementation = findImplementation(resource).asSubclass(RDFNode.class); + final Model graph1 = (Model) graph; + return (T) graph1.createResource(name).as(rawImplementation); + } + private static T wrap(final Object original, final Class definition, final Class parameterType) { final Class rawImplementation = findImplementation(definition); final Class implementation = subclass(rawImplementation, definition); diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java index 6fd82691b..9ab36a583 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/E2ETest.java @@ -135,6 +135,11 @@ void test() { assertThat(myDataset.anonymous().instance().getLabel(), is(nullValue())); myDataset.anonymous().instance().add(singletonList(666)); assertThat(myDataset.anonymous().instance().getLabel(), is(666)); + + final MyResource five = myDataset.named().createMyResource(randomUUID().toString()); + five.overwrite(555); + myDataset.named().instance().add(five); + assertThat(myDataset.named().instance().child().getLabel(), is(555)); } } @@ -163,6 +168,10 @@ default Integer label() { @Graph interface MyGraph { + default MyResource createMyResource(final String uri) { + return MyResource.create(uri, this); + } + @GraphProperty(CHILD) MyResource subject(); @@ -185,6 +194,10 @@ default Integer label() { @Resource interface MyResource { + static MyResource create(final String uri, final MyGraph graph) { + return Manager.create(uri, MyResource.class, graph); + } + @ResourceProperty(value = LABEL, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Integer getLabel(); @@ -251,7 +264,7 @@ interface MyResource { @ResourceProperty(value = MANY, cardinality = OBJECTS_READ_ONLY, valueMapping = LITERAL_AS_INTEGER_OR_NULL) Collection many16(); - @ResourceProperty(value = LABEL, cardinality = OVERWRITE) + @ResourceProperty(value = CHILD, cardinality = OVERWRITE) void overwrite(MyResource value); @ResourceProperty(value = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) @@ -260,7 +273,7 @@ interface MyResource { @ResourceProperty(value = LABEL, cardinality = OVERWRITE, nodeMapping = AS_TYPED_LITERAL) void overwrite(Iterable value); - @ResourceProperty(value = LABEL, cardinality = OVERWRITE_NULLABLE) + @ResourceProperty(value = CHILD, cardinality = OVERWRITE_NULLABLE) void overwriteNullable(MyResource value); @ResourceProperty(value = LABEL, cardinality = OVERWRITE_NULLABLE, nodeMapping = AS_TYPED_LITERAL) @@ -269,7 +282,7 @@ interface MyResource { @ResourceProperty(value = LABEL, cardinality = OVERWRITE_NULLABLE, nodeMapping = AS_TYPED_LITERAL) void overwriteNullable(Iterable value); - @ResourceProperty(value = LABEL, cardinality = ADD) + @ResourceProperty(value = CHILD, cardinality = ADD) void add(MyResource value); @ResourceProperty(value = LABEL, cardinality = ADD, nodeMapping = AS_TYPED_LITERAL) From ffe506de342958ab75f1e1ac6858a90ebf208078 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 24 Mar 2024 12:11:04 +0000 Subject: [PATCH 128/141] Expose resource factory Graphs from other packages can access it --- .../com/inrupt/rdf/wrapping/processor/ResourceImplementor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 4295b9b82..8ebeef6c5 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -77,7 +77,7 @@ private void addClass() { private void addFactoryField() { target.field( - STATIC | FINAL, + PUBLIC | STATIC | FINAL, org.apache.jena.enhanced.Implementation.class, FACTORY, typeOf(UriOrBlankFactory.class)._new().arg(typeOf(target).methodRef("new"))); From 8cf9f830df517c694115f05353be1d3e2803adac Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 24 Mar 2024 12:25:22 +0000 Subject: [PATCH 129/141] Call super where adequate --- .../inrupt/rdf/wrapping/processor/DatasetImplementor.java | 5 +++-- .../com/inrupt/rdf/wrapping/processor/GraphImplementor.java | 6 +++--- .../inrupt/rdf/wrapping/processor/ResourceImplementor.java | 5 +++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 31504577c..e19e18a1f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -22,6 +22,7 @@ import static org.jboss.jdeparser.JExprs.*; import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JType.THIS; import static org.jboss.jdeparser.JTypes.$t; import javax.annotation.Generated; @@ -74,9 +75,9 @@ private void addWrap() { private void addGraphs() { definition.properties().forEach(p -> { if (p.graphName().isEmpty()) { - addGraph(p, call("getDefaultModel")); + addGraph(p, THIS._super().call("getDefaultModel")); } else { - addGraph(p, call("getNamedModel").arg(str(p.graphName()))); + addGraph(p, THIS._super().call("getNamedModel").arg(str(p.graphName()))); } }); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 436041cf0..4064b2c2e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -22,8 +22,8 @@ import static com.inrupt.rdf.wrapping.processor.ResourceImplementor.FACTORY; import static org.jboss.jdeparser.JExprs.$v; -import static org.jboss.jdeparser.JExprs.call; import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JType.THIS; import static org.jboss.jdeparser.JTypes.$t; import com.inrupt.rdf.wrapping.jena.WrapperModel; @@ -87,7 +87,7 @@ private void addToPersonality(final JMethodDef constructor) { constructor .body() - .call(call("getPersonality"), "add") + .call(THIS._super().call("getPersonality"), "add") .arg(implementation._class()) .arg(implementation.field(FACTORY)); }); @@ -98,7 +98,7 @@ private void addResourceMethods() { final JType implementation = asImplementation(p.getReturnType()); // Call model wrapper convenience method passing projection class argument - final JCall convenienceCall = call(p.method()).arg(implementation._class()); + final JCall convenienceCall = THIS._super().call(p.method()).arg(implementation._class()); // Pass each filter value from the annotation as additional argument for (final String value : p.resources()) { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 8ebeef6c5..c7eabd661 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -22,6 +22,7 @@ import static org.jboss.jdeparser.JExprs.*; import static org.jboss.jdeparser.JMod.*; +import static org.jboss.jdeparser.JType.THIS; import static org.jboss.jdeparser.JTypes.typeOf; import com.inrupt.rdf.wrapping.annotation.Resource; @@ -140,7 +141,7 @@ private void addMutators() { valueExpr = name(value); } - final JCall call = m.body().call(typeOf(target)._super(), p.cardinalityMethod()); + final JCall call = m.body().call(THIS._super(), p.cardinalityMethod()); valueArgType.getTypeArguments().stream() .findFirst() @@ -159,7 +160,7 @@ private void addComplex(final ResourcePropertyDefinition definition, final TypeM } private void addPropertyMethod(final ResourcePropertyDefinition p, final JExpr mapping) { - final JCall predicate = call("getModel").call("createProperty").arg(str(p.predicate())); + final JCall predicate = THIS._super().call("getModel").call("createProperty").arg(str(p.predicate())); addMethod(p).body()._return(call(p.cardinalityMethod()).arg(predicate).arg(mapping)); } From f073cc83ceb191601e697596a14491c8e6a39bd8 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 24 Mar 2024 13:10:56 +0000 Subject: [PATCH 130/141] Remove imports To minimize clashes --- .../rdf/wrapping/processor/DatasetImplementor.java | 11 ----------- .../rdf/wrapping/processor/GraphImplementor.java | 12 ------------ .../wrapping/processor/ResourceImplementor.java | 14 -------------- 3 files changed, 37 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index e19e18a1f..9d724e6f2 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -25,8 +25,6 @@ import static org.jboss.jdeparser.JType.THIS; import static org.jboss.jdeparser.JTypes.$t; -import javax.annotation.Generated; - import org.apache.jena.query.Dataset; import org.apache.jena.sparql.core.DatasetGraph; import org.apache.jena.sparql.core.DatasetImpl; @@ -41,21 +39,12 @@ class DatasetImplementor extends Implementor { @Override protected void implementInternal() { - addImports(); addClass(); addConstructor(); addWrap(); addGraphs(); } - private void addImports() { - sourceFile - ._import(Generated.class) - ._import(Dataset.class) - ._import(DatasetGraph.class) - ._import(DatasetImpl.class); - } - private void addClass() { addClass(DatasetImpl.class); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 4064b2c2e..3abf0910d 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -28,8 +28,6 @@ import com.inrupt.rdf.wrapping.jena.WrapperModel; -import javax.annotation.Generated; - import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.impl.ModelCom; @@ -45,7 +43,6 @@ class GraphImplementor extends Implementor { @Override protected void implementInternal() { - addImports(); addClass(); final JMethodDef constructor = addConstructor(); addToPersonality(constructor); @@ -54,15 +51,6 @@ protected void implementInternal() { addResourceMethods(); } - private void addImports() { - sourceFile - ._import(WrapperModel.class) - ._import(Generated.class) - ._import(Graph.class) - ._import(Model.class) - ._import(ModelCom.class); - } - private void addClass() { addClass(WrapperModel.class); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index c7eabd661..7807d592c 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -31,7 +31,6 @@ import com.inrupt.rdf.wrapping.jena.ValueMappings; import com.inrupt.rdf.wrapping.jena.WrapperResource; -import javax.annotation.Generated; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.lang.model.type.WildcardType; @@ -50,7 +49,6 @@ class ResourceImplementor extends Implementor { @Override protected void implementInternal() { - addImports(); addClass(); addFactoryField(); addConstructor(); @@ -60,18 +58,6 @@ protected void implementInternal() { addComplexPlural(); } - private void addImports() { - sourceFile - ._import(UriOrBlankFactory.class) - ._import(WrapperResource.class) - ._import(Generated.class) - ._import(EnhGraph.class) - ._import(org.apache.jena.enhanced.Implementation.class) - ._import(Node.class) - ._import(ValueMappings.class) - ._import(NodeMappings.class); - } - private void addClass() { addClass(WrapperResource.class); } From e76802ac34f962f09b138a5567c02738b69d52a3 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 6 Apr 2024 18:05:03 +0100 Subject: [PATCH 131/141] Reminder --- .../com/inrupt/rdf/wrapping/annotation/ResourceProperty.java | 1 + .../rdf/wrapping/processor/ResourcePropertyDefinition.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java index 1ec89bcc1..c26575ead 100644 --- a/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java +++ b/annotation/src/main/java/com/inrupt/rdf/wrapping/annotation/ResourceProperty.java @@ -36,6 +36,7 @@ public @interface ResourceProperty { String value(); + // TODO: Rename Cardinality cardinality() default ANY_OR_NULL; ValueMapping valueMapping() default AS; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java index 1c0552bfe..787ec3a3e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java @@ -38,10 +38,12 @@ String predicate() { return annotation().value(); } + // TODO: Rename Cardinality cardinality() { return annotation().cardinality(); } + // TODO: Rename String cardinalityMethod() { return cardinality().getMethodName(); } From 1c524a0fe034a7c34c7d530755a4911f1c21b2b7 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 6 Apr 2024 18:09:56 +0100 Subject: [PATCH 132/141] Move things around --- .../com/inrupt/rdf/wrapping/processor/Definition.java | 2 +- .../com/inrupt/rdf/wrapping/processor/Environment.java | 8 ++++---- .../inrupt/rdf/wrapping/processor/GraphDefinition.java | 2 +- .../com/inrupt/rdf/wrapping/processor/Implementor.java | 2 +- .../inrupt/rdf/wrapping/processor/ResourceDefinition.java | 2 +- .../inrupt/rdf/wrapping/processor/ResourceValidator.java | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java index 994739eac..191ac2267 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java @@ -68,7 +68,7 @@ TypeElement typeOf(final TypeMirror mirror) { } TypeElement returnTypeOf(final ExecutableElement method) { - return typeOf(method.getReturnType()); + return getEnv().findDeclaration(method.getReturnType()); } protected T getElement() { diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java index 3f0563b92..cc313183f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Environment.java @@ -34,11 +34,11 @@ class Environment extends WrapperProcessingEnvironment { super(env); } - TypeElement type(final Class clazz) { + TypeElement findDeclaration(final Class clazz) { return getElementUtils().getTypeElement(clazz.getCanonicalName()); } - TypeElement type(final TypeMirror mirror) { + TypeElement findDeclaration(final TypeMirror mirror) { return (TypeElement) getTypeUtils().asElement(mirror); } @@ -55,10 +55,10 @@ Stream methodsOf(final Element element) { } Stream methodsOf(final Class clazz) { - return methodsOf(type(clazz)); + return methodsOf(findDeclaration(clazz)); } private TypeMirror mirror(final Class clazz) { - return type(clazz).asType(); + return findDeclaration(clazz).asType(); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java index bf59a2887..178af28af 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphDefinition.java @@ -42,7 +42,7 @@ Stream properties() { Stream transitiveResourceTypes() { final Stream children = returnTypes(); final Stream descendants = returnTypes() - .map(getEnv()::type) + .map(getEnv()::findDeclaration) .map(type -> new ResourceDefinition(type, getEnv())) .flatMap(ResourceDefinition::transitiveResourceTypes); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 1874b4258..a4497c0f3 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -106,7 +106,7 @@ protected JMethodDef addMethod(final Definition } protected JType asImplementation(final TypeMirror original) { - final TypeElement returnType = definition.typeOf(original); + final TypeElement returnType = definition.getEnv().findDeclaration(original); final String originalBinaryName = binaryName(returnType); return $t(asImplementation(originalBinaryName)); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java index 0d6231724..fa3eb40ae 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceDefinition.java @@ -119,7 +119,7 @@ Stream transitiveResourceTypes() { private ResourceDefinition dequeue(final Queue outstanding) { final TypeMirror next = outstanding.remove(); - final TypeElement nextType = getEnv().type(next); + final TypeElement nextType = getEnv().findDeclaration(next); return new ResourceDefinition(nextType, getEnv()); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 3980cd881..37f39f97a 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -285,7 +285,7 @@ private void requirePluralCompatible() { if (thisReturn.getTypeArguments().stream() .map(WildcardType.class::cast) .map(WildcardType::getExtendsBound) - .map(definition::typeOf) + .map(definition.getEnv()::findDeclaration) .map(a -> a.getAnnotation(Resource.class)) .allMatch(Objects::nonNull)) { return; @@ -309,7 +309,7 @@ private void requireMutatorNoPluralComplex() { // Require generic type arguments to be primitive if (valueArgType.getTypeArguments().stream() - .map(definition::typeOf) + .map(definition.getEnv()::findDeclaration) .map(a -> a.getAnnotation(Resource.class)) .allMatch(Objects::isNull)) { return; From 973c0d239ba38942d5aa0036cc7d5f771d214490 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 6 Apr 2024 18:11:30 +0100 Subject: [PATCH 133/141] Move things around --- .../inrupt/rdf/wrapping/processor/DatasetImplementor.java | 2 +- .../java/com/inrupt/rdf/wrapping/processor/Definition.java | 4 ---- .../com/inrupt/rdf/wrapping/processor/GraphImplementor.java | 2 +- .../java/com/inrupt/rdf/wrapping/processor/Implementor.java | 6 +++++- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 9d724e6f2..3701616af 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -56,7 +56,7 @@ private void addConstructor() { } private void addWrap() { - final JMethodDef myWrap = target.method(PUBLIC | STATIC, definition.getOriginalInterface(), WRAP); + final JMethodDef myWrap = target.method(PUBLIC | STATIC, getOriginalInterface(), WRAP); myWrap.param(FINAL, Dataset.class, ORIGINAL); myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("asDatasetGraph"))); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java index 191ac2267..6fc42d85f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java @@ -79,10 +79,6 @@ protected Environment getEnv() { return env; } - protected JType getOriginalInterface() { - return JTypes.typeOf(element.asType()); - } - protected Stream membersAnnotatedWith(final Class annotation) { return env.methodsOf(element) .filter(method -> method.getAnnotation(annotation) != null); diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index 3abf0910d..fee11fcb0 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -64,7 +64,7 @@ private JMethodDef addConstructor() { } private void addWrap() { - final JMethodDef myWrap = target.method(PUBLIC | STATIC, definition.getOriginalInterface(), WRAP); + final JMethodDef myWrap = target.method(PUBLIC | STATIC, getOriginalInterface(), WRAP); myWrap.param(FINAL, Model.class, ORIGINAL); myWrap.body()._return($t(target)._new().arg($v(ORIGINAL).call("getGraph"))); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index a4497c0f3..1e967d6bd 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -89,12 +89,16 @@ static String asImplementation(final String original) { protected void addClass(final Class clazz) { target = sourceFile._class(PUBLIC, getImplementationClass()); target._extends(clazz); - target._implements(definition.getOriginalInterface()); + target._implements(getOriginalInterface()); target.docComment().text("Warning, this class consists of generated code."); target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); } + protected JType getOriginalInterface() { + return JTypes.typeOf(definition.getElement().asType()); + } + protected JMethodDef addMethod(final Definition d) { final String myName = d.getElement().getSimpleName().toString(); final JType myType = typeOf(d.getElement().getReturnType()); From ef63bcd5ce5bdba3526c5ac92e73f74351dd244d Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 6 Apr 2024 18:12:31 +0100 Subject: [PATCH 134/141] Tidy --- .../rdf/wrapping/processor/DatasetImplementor.java | 3 ++- .../com/inrupt/rdf/wrapping/processor/Definition.java | 10 +--------- .../rdf/wrapping/processor/GraphImplementor.java | 1 - .../wrapping/processor/ResourcePropertyDefinition.java | 6 +++--- .../rdf/wrapping/processor/ResourceValidator.java | 6 ++---- 5 files changed, 8 insertions(+), 18 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java index 3701616af..6b8447930 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/DatasetImplementor.java @@ -20,7 +20,8 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.jboss.jdeparser.JExprs.*; +import static org.jboss.jdeparser.JExprs.$v; +import static org.jboss.jdeparser.JExprs.str; import static org.jboss.jdeparser.JMod.*; import static org.jboss.jdeparser.JType.THIS; import static org.jboss.jdeparser.JTypes.$t; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java index 6fc42d85f..3ee84eec2 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java @@ -32,10 +32,6 @@ import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; - -import org.jboss.jdeparser.JType; -import org.jboss.jdeparser.JTypes; class Definition { static final Predicate isVoid = method -> method.getReturnType().getKind() == VOID; @@ -63,10 +59,6 @@ class Definition { } } - TypeElement typeOf(final TypeMirror mirror) { - return getEnv().type(mirror); - } - TypeElement returnTypeOf(final ExecutableElement method) { return getEnv().findDeclaration(method.getReturnType()); } @@ -80,7 +72,7 @@ protected Environment getEnv() { } protected Stream membersAnnotatedWith(final Class annotation) { - return env.methodsOf(element) + return getEnv().methodsOf(getElement()) .filter(method -> method.getAnnotation(annotation) != null); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java index fee11fcb0..ac01df709 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/GraphImplementor.java @@ -30,7 +30,6 @@ import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.impl.ModelCom; import org.jboss.jdeparser.JCall; import org.jboss.jdeparser.JExprs; import org.jboss.jdeparser.JMethodDef; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java index 787ec3a3e..5d6ac387f 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourcePropertyDefinition.java @@ -27,7 +27,7 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Name; -import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.DeclaredType; class ResourcePropertyDefinition extends PropertyDefinition { ResourcePropertyDefinition(final ExecutableElement element, final Environment env) { @@ -68,7 +68,7 @@ Name getName() { return getElement().getSimpleName(); } - TypeMirror getValueParamType() { - return getElement().getParameters().get(0).asType(); + DeclaredType getValueParamType() { + return (DeclaredType) getElement().getParameters().get(0).asType(); } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java index 37f39f97a..cbbb9dfac 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceValidator.java @@ -300,15 +300,13 @@ private void requirePluralCompatible() { private void requireMutatorNoPluralComplex() { definition.setterProperties().forEach(p -> { - final DeclaredType valueArgType = (DeclaredType) p.getValueParamType(); - // Ignore value params lacking generic type arguments - if (valueArgType.getTypeArguments().isEmpty()) { + if (p.getValueParamType().getTypeArguments().isEmpty()) { return; } // Require generic type arguments to be primitive - if (valueArgType.getTypeArguments().stream() + if (p.getValueParamType().getTypeArguments().stream() .map(definition.getEnv()::findDeclaration) .map(a -> a.getAnnotation(Resource.class)) .allMatch(Objects::isNull)) { From 778262a36d46f5ec8376949d7bc8d5dcc815429c Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 6 Apr 2024 18:13:37 +0100 Subject: [PATCH 135/141] Link to original from generated in javadoc --- .../java/com/inrupt/rdf/wrapping/processor/Implementor.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 1e967d6bd..d59fa0ced 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -91,7 +91,11 @@ protected void addClass(final Class clazz) { target._extends(clazz); target._implements(getOriginalInterface()); - target.docComment().text("Warning, this class consists of generated code."); + final JDocComment javadoc = target.docComment(); + javadoc.text("Warning, this class consists of generated code and is not intended to be used directly. Use "); + javadoc.linkType(false, getOriginalInterface()).text("the original interface"); + javadoc.text(" instead."); + target.annotate(Generated.class).value(this.getClass().getName()).value("date", Instant.now().toString()); } From 0f32600e5818fcb93cd00be32209015fc980b2af Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 6 Apr 2024 18:28:32 +0100 Subject: [PATCH 136/141] Extract --- .../rdf/wrapping/processor/ResourceImplementor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index 7807d592c..c776a8f83 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -112,8 +112,6 @@ private void addComplexPlural() { // TODO: Cover private void addMutators() { definition.setterProperties().forEach(p -> { - final JCall predicate = call("getModel").call("createProperty").arg(str(p.predicate())); - final JExpr mapping = typeOf(NodeMappings.class).methodRef(p.nodeMappingMethod()); final JMethodDef m = addMethod(p); @@ -146,8 +144,10 @@ private void addComplex(final ResourcePropertyDefinition definition, final TypeM } private void addPropertyMethod(final ResourcePropertyDefinition p, final JExpr mapping) { - final JCall predicate = THIS._super().call("getModel").call("createProperty").arg(str(p.predicate())); + addMethod(p).body()._return(THIS._super().call(p.cardinalityMethod()).arg(getProperty(p)).arg(mapping)); + } - addMethod(p).body()._return(call(p.cardinalityMethod()).arg(predicate).arg(mapping)); + private static JCall getProperty(final ResourcePropertyDefinition d) { + return THIS._super().call("getModel").call("getProperty").arg(str(d.predicate())); } } From 8f591241fb2526bf07f7abbf07b9335c0dc25369 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sat, 6 Apr 2024 18:29:06 +0100 Subject: [PATCH 137/141] Tidy mutator implementor --- .../processor/ResourceImplementor.java | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java index c776a8f83..97d01bda4 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ResourceImplementor.java @@ -31,6 +31,7 @@ import com.inrupt.rdf.wrapping.jena.ValueMappings; import com.inrupt.rdf.wrapping.jena.WrapperResource; +import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.lang.model.type.WildcardType; @@ -114,25 +115,27 @@ private void addMutators() { definition.setterProperties().forEach(p -> { final JExpr mapping = typeOf(NodeMappings.class).methodRef(p.nodeMappingMethod()); - final JMethodDef m = addMethod(p); - final DeclaredType valueArgType = (DeclaredType) p.getValueParamType(); - final JParamDeclaration value = m.param(FINAL, typeOf(valueArgType), "value"); + final JMethodDef method = addMethod(p); + final JParamDeclaration valueParam = method.param(FINAL, typeOf(p.getValueParamType()), "value"); - final JExpr valueExpr; - if (definition.typeOf(valueArgType).getAnnotation(Resource.class) != null) { - valueExpr = name(value).cast(RDFNode.class); - } else { - valueExpr = name(value); - } + // Mutator method implementations for complex properties must cast value parameter to node so it works + // with identity node mapping. + // TODO: What happens with other node mapping methods? + final TypeElement declaration = definition.getEnv().findDeclaration(p.getValueParamType()); + final JExpr value = declaration.getAnnotation(Resource.class) != null ? + name(valueParam).cast(RDFNode.class) : + name(valueParam); - final JCall call = m.body().call(THIS._super(), p.cardinalityMethod()); + final JCall call = method.body().call(THIS._super(), p.cardinalityMethod()); - valueArgType.getTypeArguments().stream() + // Plural mutator method implementations must specify type argument of cardinality method to assist type + // inference. + p.getValueParamType().getTypeArguments().stream() .findFirst() - .ifPresent(typeMirror -> - call.typeArg(typeOf(typeMirror))); + .map(JTypes::typeOf) + .ifPresent(call::typeArg); - call.arg(predicate).arg(valueExpr).arg(mapping); + call.arg(getProperty(p)).arg(value).arg(mapping); }); } From 06ec477062e2de9985bc814e82efde336e49b629 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 7 Apr 2024 17:44:55 +0100 Subject: [PATCH 138/141] Tidy and cover manager resource creation --- .../rdf/wrapping/processor/Manager.java | 52 +++++++---- .../rdf/wrapping/processor/ManagerTest.java | 89 +++++++++++++++++++ 2 files changed, 124 insertions(+), 17 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java index c8ff841f9..8d8c3146e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java @@ -23,12 +23,11 @@ import static com.inrupt.rdf.wrapping.processor.Implementor.WRAP; import static com.inrupt.rdf.wrapping.processor.Implementor.asImplementation; -import com.inrupt.rdf.wrapping.annotation.Resource; - import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Objects; +import org.apache.jena.enhanced.UnsupportedPolymorphismException; import org.apache.jena.query.Dataset; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.RDFNode; @@ -48,23 +47,15 @@ public static T wrap(final Dataset original, final Class definition) { return wrap(original, definition, Dataset.class); } - // TODO: Tidy - // TODO: Cover - public static T create(final String name, final Class resource, final U graph) { - Objects.requireNonNull(resource); + public static T create(final String name, final Class targetClass, final Object graph) { + Objects.requireNonNull(targetClass); Objects.requireNonNull(graph); - if (resource.getAnnotation(Resource.class) == null) { - throw new RuntimeException("resource must be a definition"); - } - - if (!(graph instanceof Model)) { - throw new RuntimeException("graph must be a Model"); - } - - final Class rawImplementation = findImplementation(resource).asSubclass(RDFNode.class); - final Model graph1 = (Model) graph; - return (T) graph1.createResource(name).as(rawImplementation); + final Class rawImplementation = findImplementation(targetClass); + final Class implementation = subclass(rawImplementation, RDFNode.class); + final Model model = asModel(graph); + final RDFNode result = createAndProject(name, model, implementation); + return ensureImplements(result, targetClass); } private static T wrap(final Object original, final Class definition, final Class parameterType) { @@ -131,4 +122,31 @@ private static T cast(final Object result, final Class definition) { throw new RuntimeException("wrap method return type mismatch", e); } } + + private static T ensureImplements(final Object result, final Class definition) { + try { + return definition.cast(result); + + } catch (ClassCastException e) { + throw new RuntimeException("implementation does not implement definition", e); + } + } + + private static RDFNode createAndProject(final String name, final Model m, + final Class implementation) { + try { + return m.createResource(name).as(implementation); + + } catch (UnsupportedPolymorphismException e) { + throw new RuntimeException("could not project to implementation", e); + } + } + + private static Model asModel(final Object graph) { + if (!(graph instanceof Model)) { + throw new RuntimeException("graph must be a Model"); + } + + return (Model) graph; + } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java index a6fa14f52..ee933636a 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ManagerTest.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; +import static com.inrupt.rdf.wrapping.processor.Manager.create; import static com.inrupt.rdf.wrapping.processor.Manager.wrap; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasProperty; @@ -28,12 +29,19 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.params.provider.Arguments.arguments; +import com.inrupt.rdf.wrapping.jena.UriOrBlankFactory; +import com.inrupt.rdf.wrapping.jena.WrapperModel; + import java.util.stream.Stream; +import org.apache.jena.enhanced.EnhGraph; +import org.apache.jena.enhanced.Implementation; +import org.apache.jena.graph.Node; import org.apache.jena.query.Dataset; import org.apache.jena.query.DatasetFactory; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.impl.ResourceImpl; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -64,6 +72,28 @@ static Stream wrapFails() { ); } + @DisplayName("fails to create resource with error") + @ParameterizedTest(name = "[{2}] when definition is [{0}] and graph is [{1}]") + @MethodSource + void createFails(final Class definition, final Object model, final String error) { + final Throwable t = assertThrows(RuntimeException.class, () -> create(null, definition, model)); + assertThat(t, hasProperty("message", is(error))); + } + + static Stream createFails() { + final Object model = ModelFactory.createDefaultModel(); + final Object notModel = "not model"; + final Personalized personalized = new Personalized(); + + return Stream.of( + arguments(ResourceOk.class, notModel, "graph must be a Model"), + arguments(ResourceNoImplementation.class, model, "implementation not found"), + arguments(ResourceImplementationMismatch.class, model, "implementation type mismatch"), + arguments(ResourceNoConstructor.class, personalized, "could not project to implementation"), + arguments(ResourceNotDefinition.class, personalized, "implementation does not implement definition") + ); + } + @Test @DisplayName("wraps graph") void wrapModel() { @@ -80,6 +110,14 @@ void wrapDataset() { assertDoesNotThrow(() -> wrap(dataset, OkDataset.class)); } + @Test + @DisplayName("creates resource") + void createResource() { + final Model model = new Personalized(); + + assertDoesNotThrow(() -> create(null, ResourceOk.class, model)); + } + interface NoImplementation { } @@ -149,4 +187,55 @@ static OkDataset wrap(final Dataset ignored) { }; } } + + //region Resource + + static class Personalized extends WrapperModel { + protected Personalized() { + super(ModelFactory.createDefaultModel().getGraph()); + + getPersonality() + .add(ResourceOk_$impl.class, ResourceOk_$impl.factory) + .add(ResourceNotDefinition_$impl.class, ResourceNotDefinition_$impl.factory); + } + } + + interface ResourceNoImplementation { + } + + interface ResourceNotDefinition { + } + + static class ResourceNotDefinition_$impl extends ResourceImpl { + static final Implementation factory = new UriOrBlankFactory(ResourceNotDefinition_$impl::new); + + protected ResourceNotDefinition_$impl(final Node n, final EnhGraph m) { + super(n, m); + } + } + + interface ResourceNoConstructor { + } + + static class ResourceNoConstructor_$impl extends ResourceImpl { + } + + interface ResourceImplementationMismatch { + } + + static class ResourceImplementationMismatch_$impl { + } + + interface ResourceOk { + } + + static class ResourceOk_$impl extends ResourceImpl implements ResourceOk { + static final Implementation factory = new UriOrBlankFactory(ResourceOk_$impl::new); + + protected ResourceOk_$impl(final Node n, final EnhGraph m) { + super(n, m); + } + } + + //endregion } From 5c3943334847a3b5942c0868d595c4a492edb50a Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 7 Apr 2024 18:15:52 +0100 Subject: [PATCH 139/141] Move factories inside processor to hide wildcards --- .../rdf/wrapping/processor/Definition.java | 16 ------- .../rdf/wrapping/processor/Implementor.java | 13 ------ .../rdf/wrapping/processor/Processor.java | 42 +++++++++++++++++-- .../rdf/wrapping/processor/Validator.java | 13 ------ 4 files changed, 39 insertions(+), 45 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java index 3ee84eec2..682a89108 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Definition.java @@ -22,9 +22,6 @@ import static javax.lang.model.type.TypeKind.VOID; -import com.inrupt.rdf.wrapping.annotation.Dataset; -import com.inrupt.rdf.wrapping.annotation.Graph; - import java.lang.annotation.Annotation; import java.util.function.Predicate; import java.util.stream.Stream; @@ -46,19 +43,6 @@ class Definition { this.clazz = clazz; } - static Definition definition(final TypeElement type, final Environment env) { - if (type.getAnnotation(Dataset.class) != null) { - return new DatasetDefinition(type, env); - - } else if (type.getAnnotation(Graph.class) != null) { - return new GraphDefinition(type, env); - - } else { // Resource - // Processor's supported annotations are finite - return new ResourceDefinition(type, env); - } - } - TypeElement returnTypeOf(final ExecutableElement method) { return getEnv().findDeclaration(method.getReturnType()); } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index d59fa0ced..2e35ca55c 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -67,19 +67,6 @@ void implement() { } } - static Implementor implementor(final Definition definition) { - if (definition instanceof DatasetDefinition) { - return new DatasetImplementor((DatasetDefinition) definition); - - } else if (definition instanceof GraphDefinition) { - return new GraphImplementor((GraphDefinition) definition); - - } else { // Resource - // Processor's supported annotations are finite - return new ResourceImplementor((ResourceDefinition) definition); - } - } - static String asImplementation(final String original) { return original + "_$impl"; } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java index e620751c0..ef8f133b0 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Processor.java @@ -20,9 +20,6 @@ */ package com.inrupt.rdf.wrapping.processor; -import static com.inrupt.rdf.wrapping.processor.Definition.definition; -import static com.inrupt.rdf.wrapping.processor.Implementor.implementor; -import static com.inrupt.rdf.wrapping.processor.Validator.validator; import static java.util.stream.Collectors.toSet; import static javax.lang.model.SourceVersion.RELEASE_8; import static javax.tools.Diagnostic.Kind.NOTE; @@ -79,4 +76,43 @@ public boolean process(final Set annotations, final Round return true; } + + private static Definition definition(final TypeElement type, final Environment env) { + if (type.getAnnotation(Dataset.class) != null) { + return new DatasetDefinition(type, env); + + } else if (type.getAnnotation(Graph.class) != null) { + return new GraphDefinition(type, env); + + } else { // Resource + // Supported annotations are finite + return new ResourceDefinition(type, env); + } + } + + private static Implementor implementor(final Definition definition) { + if (definition instanceof DatasetDefinition) { + return new DatasetImplementor((DatasetDefinition) definition); + + } else if (definition instanceof GraphDefinition) { + return new GraphImplementor((GraphDefinition) definition); + + } else { // Resource + // Supported annotations are finite + return new ResourceImplementor((ResourceDefinition) definition); + } + } + + private static Validator validator(final Definition definition) { + if (definition instanceof DatasetDefinition) { + return new DatasetValidator((DatasetDefinition) definition); + + } else if (definition instanceof GraphDefinition) { + return new GraphValidator((GraphDefinition) definition); + + } else { // Resource + // Supported annotations are finite + return new ResourceValidator((ResourceDefinition) definition); + } + } } diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java index a75b9b1cd..4c9f6227e 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Validator.java @@ -42,19 +42,6 @@ protected Validator(final T definition) { this.definition = definition; } - static Validator validator(final Definition definition) { - if (definition instanceof DatasetDefinition) { - return new DatasetValidator((DatasetDefinition) definition); - - } else if (definition instanceof GraphDefinition) { - return new GraphValidator((GraphDefinition) definition); - - } else { // Resource - // Processor's supported annotations are finite - return new ResourceValidator((ResourceDefinition) definition); - } - } - Collection validate() { validateInternal(); From cfde5a4c11c055bdcccda80d087192ce9bb45aaa Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 7 Apr 2024 18:42:32 +0100 Subject: [PATCH 140/141] Print error instead of throwing on implementor write failure --- .../rdf/wrapping/processor/Implementor.java | 4 +++- .../rdf/wrapping/processor/ImplementorTest.java | 17 ++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java index 2e35ca55c..6c72d8945 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Implementor.java @@ -20,6 +20,7 @@ */ package com.inrupt.rdf.wrapping.processor; +import static javax.tools.Diagnostic.Kind.ERROR; import static org.jboss.jdeparser.JMod.PUBLIC; import static org.jboss.jdeparser.JTypes.$t; import static org.jboss.jdeparser.JTypes.typeOf; @@ -63,7 +64,8 @@ void implement() { try { sources.writeSources(); } catch (IOException e) { - throw new RuntimeException("could not open writer", e); + final String msg = String.format("could not write sources, caused by [%s]", e); + definition.getEnv().getMessager().printMessage(ERROR, msg, definition.getElement()); } } diff --git a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java index 5e9bea7e1..28f56abef 100644 --- a/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java +++ b/processor/src/test/java/com/inrupt/rdf/wrapping/processor/ImplementorTest.java @@ -20,17 +20,14 @@ */ package com.inrupt.rdf.wrapping.processor; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasProperty; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static javax.tools.Diagnostic.Kind.ERROR; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; import java.io.IOException; import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; import javax.lang.model.element.Name; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; @@ -51,6 +48,7 @@ void failsToWrite() throws IOException { final Name name = mock(Name.class); final PackageElement packageElement = mock(PackageElement.class); final Filer filer = mock(Filer.class); + final Messager messager = mock(Messager.class); when(definition.getElement()).thenReturn(type); when(definition.getEnv()).thenReturn(env); @@ -60,6 +58,7 @@ void failsToWrite() throws IOException { when(filer.createSourceFile(any())).thenThrow(IOException.class); // Substance when(env.getElementUtils()).thenReturn(elementUtils); when(env.getFiler()).thenReturn(filer); + when(env.getMessager()).thenReturn(messager); @SuppressWarnings({"rawtypes", "unchecked"}) // For test brevity final Implementor mock = new Implementor(definition) { @@ -68,7 +67,7 @@ protected void implementInternal() { } }; - final Throwable t = assertThrows(RuntimeException.class, mock::implement); - assertThat(t, hasProperty("message", is("could not open writer"))); + mock.implement(); + verify(messager).printMessage(eq(ERROR), startsWith("could not write source"), eq(type)); } } From 4466714b6169ab084a1e9b72d96126132c2aafc8 Mon Sep 17 00:00:00 2001 From: Samu Lang Date: Sun, 7 Apr 2024 18:44:07 +0100 Subject: [PATCH 141/141] Dedicated exception --- .../rdf/wrapping/processor/Manager.java | 20 +++++------ .../processor/ProcessorException.java | 33 +++++++++++++++++++ 2 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 processor/src/main/java/com/inrupt/rdf/wrapping/processor/ProcessorException.java diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java index 8d8c3146e..3867d1b02 100644 --- a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/Manager.java @@ -74,7 +74,7 @@ private static Class findImplementation(final Class definition) { return Class.forName(implementation); } catch (ClassNotFoundException e) { - throw new RuntimeException("implementation not found", e); + throw new ProcessorException("implementation not found", e); } } @@ -83,7 +83,7 @@ private static Class subclass(final Class implementation, fi return implementation.asSubclass(definition); } catch (ClassCastException e) { - throw new RuntimeException("implementation type mismatch", e); + throw new ProcessorException("implementation type mismatch", e); } } @@ -92,13 +92,13 @@ private static Method findWrapMethod(final Class implementation return implementation.getDeclaredMethod(WRAP, parameterType); } catch (NoSuchMethodException e) { - throw new RuntimeException("wrap method not found", e); + throw new ProcessorException("wrap method not found", e); } } private static void ensureNotVoid(final Method wrap) { if (wrap.getReturnType() == void.class) { - throw new RuntimeException("wrap method is void"); + throw new ProcessorException("wrap method is void"); } } @@ -107,10 +107,10 @@ private static Object invoke(final Method wrap, final Object... original) { return wrap.invoke(null, original); } catch (IllegalAccessException e) { - throw new RuntimeException("wrap method inaccessible", e); + throw new ProcessorException("wrap method inaccessible", e); } catch (InvocationTargetException e) { - throw new RuntimeException("wrap method threw exception", e); + throw new ProcessorException("wrap method threw exception", e); } } @@ -119,7 +119,7 @@ private static T cast(final Object result, final Class definition) { return definition.cast(result); } catch (ClassCastException e) { - throw new RuntimeException("wrap method return type mismatch", e); + throw new ProcessorException("wrap method return type mismatch", e); } } @@ -128,7 +128,7 @@ private static T ensureImplements(final Object result, final Class defini return definition.cast(result); } catch (ClassCastException e) { - throw new RuntimeException("implementation does not implement definition", e); + throw new ProcessorException("implementation does not implement definition", e); } } @@ -138,13 +138,13 @@ private static RDFNode createAndProject(final String name, final Model m, return m.createResource(name).as(implementation); } catch (UnsupportedPolymorphismException e) { - throw new RuntimeException("could not project to implementation", e); + throw new ProcessorException("could not project to implementation", e); } } private static Model asModel(final Object graph) { if (!(graph instanceof Model)) { - throw new RuntimeException("graph must be a Model"); + throw new ProcessorException("graph must be a Model"); } return (Model) graph; diff --git a/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ProcessorException.java b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ProcessorException.java new file mode 100644 index 000000000..79c3e26b5 --- /dev/null +++ b/processor/src/main/java/com/inrupt/rdf/wrapping/processor/ProcessorException.java @@ -0,0 +1,33 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.rdf.wrapping.processor; + +public class ProcessorException extends RuntimeException { + private static final long serialVersionUID = -2368504596860538512L; + + public ProcessorException(final String message, final Throwable cause) { + super(message, cause); + } + + public ProcessorException(final String message) { + super(message); + } +}