Skip to content

Commit

Permalink
feat (modl): Initial outline of future Java model
Browse files Browse the repository at this point in the history
  • Loading branch information
vorburger committed Jun 24, 2024
1 parent ac0ee52 commit 36cc8dd
Show file tree
Hide file tree
Showing 17 changed files with 326 additions and 18 deletions.
9 changes: 9 additions & 0 deletions java/dev/enola/model/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# limitations under the License.

load("@rules_java//java:defs.bzl", "java_library")
load("//tools/bazel:junit.bzl", "junit_tests")

java_library(
name = "model",
Expand All @@ -34,3 +35,11 @@ java_library(
"@maven//:org_slf4j_slf4j_api",
],
)

junit_tests(
name = "tests",
srcs = glob(["**/*Test.java"]),
deps = [
":model",
],
)
26 changes: 26 additions & 0 deletions java/dev/enola/model/enola/java/ModelTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2024 The Enola <https://enola.dev> Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.enola.model.enola.java;

import org.junit.Test;

public class ModelTest {

@Test
public void model() {}
}
28 changes: 28 additions & 0 deletions java/dev/enola/model/enola/java/Package.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2024 The Enola <https://enola.dev> Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.enola.model.enola.java;

import dev.enola.model.w3.rdfs.HasLabel;
import dev.enola.model.w3.rdfs.Typed;
import dev.enola.thing.java.IRI;

/** 📦 <a href="https://docs.enola.dev/models/enola.dev/java/package/">Java Package</a>. */
@IRI("https://enola.dev/java/Package/{FQN}")
public interface Package
extends Typed, HasLabel { // NOT dev.enola.model.w3.rdfs.Class; these are the instances
}
71 changes: 71 additions & 0 deletions java/dev/enola/model/enola/java/Type.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2024 The Enola <https://enola.dev> Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.enola.model.enola.java;

import dev.enola.model.w3.rdfs.HasLabel;
import dev.enola.thing.Thing;
import dev.enola.thing.java.IRI;
import dev.enola.thing.java.JThing;

/**
* ☕ <a href="https://docs.enola.dev/models/enola.dev/java/type/">Java Type</a>.
*
* <p>Type (Class, Interface, Enum, Record, Primitives, Array, Void) in the Java Virtual Machine
* (JVM).
*/
@JThing("https://enola.dev/java/type")
// ? @IRI("https://enola.dev/java/type/{FQN}")
public interface Type
extends /*Typed,*/ HasLabel { // NOT dev.enola.model.w3.rdfs.Class; these are the instances

@IRI("https://enola.dev/java/package")
Package pkg();

@IRI("https://enola.dev/java/type-kind")
Kind kind();

@IRI("https://enola.dev/code/uses")
Iterable<Type> uses();

@IRI("https://enola.dev/code/oop/parents") // parents extends #uses
Iterable<Type> parents();

// TODO How to best do enums with (RDF) Things?
enum Kind {
Class,
Interface,
Enum,
Record,
Primitives,
Array,
Void
}

interface Builder<B extends Type> extends Thing.Builder<B> { // skipcq: JAVA-E0169

Builder<B> label(String label);

Builder<B> pkg(Package pkg);

Builder<B> kind(Kind kind);

Builder<B> addUses(Type uses);

Builder<B> addParents(Type parents);
}
}
99 changes: 99 additions & 0 deletions java/dev/enola/model/enola/java/gen/ImmutableType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2024 The Enola <https://enola.dev> Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.enola.model.enola.java.gen;

import com.google.common.collect.ImmutableMap;

import dev.enola.model.enola.java.Package;
import dev.enola.model.enola.java.Type;
import dev.enola.thing.KIRI;
import dev.enola.thing.impl.ImmutableThing;

public class ImmutableType extends ImmutableThing implements Type {

// TODO This, and similar, classes should (eventually) be automagically code generated...

@Override
public Package pkg() {
return get("https://enola.dev/java/package", Package.class);
}

@Override
public Kind kind() {
return get("https://enola.dev/java/type-kind", Kind.class);
}

@Override
public Iterable<Type> uses() {
return get("https://enola.dev/code/uses", Iterable.class);
// TODO new TypeToken<Iterable<Type>>() {};
}

@Override
public Iterable<Type> parents() {
return get("https://enola.dev/code/oop/parents", Iterable.class);
// TODO new TypeToken<Iterable<Type>>() {};
}

protected ImmutableType(
String iri,
ImmutableMap<String, Object> properties,
ImmutableMap<String, String> datatypes) {
super(iri, properties, datatypes);
}

// skipcq: JAVA-E0169
public static class Builder<B extends ImmutableType> extends ImmutableThing.Builder<B>
implements Type.Builder<B> {

Builder() {
super();
set(KIRI.RDF.TYPE, "https://enola.dev/java/type");
}

@Override
public Type.Builder<B> pkg(Package pkg) {
set("https://enola.dev/java/package", pkg);
return this;
}

@Override
public Type.Builder<B> label(String name) {
set(KIRI.RDFS.LABEL, name);
return this;
}

@Override
public Type.Builder<B> kind(Kind kind) {
set("https://enola.dev/java/type-kind", kind);
return this;
}

@Override
public Type.Builder<B> addUses(Type uses) {
// TODO add() to ImmutableList.Builder ... created in constructor?
return this;
}

@Override
public Type.Builder<B> addParents(Type parents) {
// TODO add() to ImmutableList.Builder ... created in constructor?
return this;
}
}
}
4 changes: 1 addition & 3 deletions java/dev/enola/model/w3/rdfs/Class.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,4 @@
*/
package dev.enola.model.w3.rdfs;

import dev.enola.thing.Thing;

public interface Class extends Thing {}
public interface Class extends Typed {}
7 changes: 5 additions & 2 deletions java/dev/enola/model/w3/rdfs/HasLabel.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
package dev.enola.model.w3.rdfs;

import dev.enola.thing.KIRI;
import dev.enola.thing.Thing;
import dev.enola.thing.java.IRI;

public interface HasLabel {
public interface HasLabel extends Thing {

@IRI(KIRI.RDFS.LABEL)
String getLabel();
default String label() {
return get(KIRI.RDFS.LABEL, String.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@

import dev.enola.thing.KIRI;
import dev.enola.thing.Thing;
import dev.enola.thing.java.IRI;
import dev.enola.thing.repo.ThingProvider;

public interface Resource extends Thing {
public interface Typed extends Thing {

@IRI(KIRI.RDF.TYPE)
Class type();

default Class type(ThingProvider tp) {
return (Class) tp.get(getString(KIRI.RDFS.CLASS));
return (Class) tp.get(getString(KIRI.RDF.TYPE));
}

// TODO Use ThingProviderThreadLocal ... here, or in a Converter?
}
3 changes: 3 additions & 0 deletions java/dev/enola/thing/PredicatesObjects.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,10 @@ public interface PredicatesObjects {
* be a {@link Link} (or {@link URI}) with an IRI or another PredicatesObjects (for an "inline
* embedded/expanded blank node") or a {@link java.util.List} of such items. The object is
* immutable. May be null if Thing has no such predicate.
*
* @deprecated Use {@link #get(String, Class)} instead.
*/
@Deprecated // TODO Remove after replacing all usages with #get(String, Class)
<T> @Nullable T get(String predicateIRI);

/**
Expand Down
2 changes: 1 addition & 1 deletion java/dev/enola/thing/impl/ImmutableThing.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public static class Builder<B extends IImmutableThing> // skipcq: JAVA-E0169
protected final ImmutableMap.Builder<String, String> datatypes;
protected @Nullable String iri;

private Builder() {
protected Builder() {
properties = ImmutableMap.builder();
datatypes = ImmutableMap.builder();
}
Expand Down
2 changes: 1 addition & 1 deletion java/dev/enola/thing/java/IRI.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
public @interface IRI {
String value();

String datatype() default "";
// TODO Derive from Java type? String datatype() default "";
}
22 changes: 22 additions & 0 deletions java/dev/enola/thing/java/JThing.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright 2024 The Enola <https://enola.dev> Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.enola.thing.java;

public @interface JThing {
String value();
}
7 changes: 4 additions & 3 deletions java/dev/enola/thing/java/test/TestThing.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
import dev.enola.thing.KIRI;
import dev.enola.thing.Thing;
import dev.enola.thing.java.IRI;
import dev.enola.thing.java.JThing;

import org.jspecify.annotations.Nullable;

@JThing("https://enola.dev/TestThing")
public interface TestThing extends Thing {

// NB: This is only here like this for TestThingTest; otherwise this would be inlined in @IRI!
Expand All @@ -35,9 +37,8 @@ public interface TestThing extends Thing {
@Nullable String label();

interface Builder<B extends TestThing> extends Thing.Builder<B> { // skipcq: JAVA-E0169
Builder<B> label(String label);

Builder label(String label);

Builder number(Integer number);
Builder<B> number(Integer number);
}
}
8 changes: 4 additions & 4 deletions java/dev/enola/thing/java/test/TestThingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ public class TestThingTest {
ImmutableTestThing.create("https://enola.dev/test1", "hello, world", 43);
final ImmutableTestThing thing2 =
ImmutableTestThing.create("https://enola.dev/test1", "hello, world", 43);
final ImmutableTestThing bthing = // Thing from Builder with static setter methods
final ImmutableTestThing bthing = // JThing from Builder with static setter methods
ImmutableTestThing.builder()
.iri("https://enola.dev/test1")
.label("hello, world")
.number(43)
.build();
final ImmutableTestThing dthing = // Thing from Builder with "dynamic" set()
final ImmutableTestThing dthing = // JThing from Builder with "dynamic" set()
ImmutableTestThing.builder()
.iri("https://enola.dev/test1")
.set(KIRI.RDFS.LABEL, "hello, world")
Expand All @@ -52,7 +52,7 @@ public class TestThingTest {
final String EXTRA = "https://enola.dev/another-predicate";
final Instant INSTANT = Instant.parse("2023-10-26T15:29:31.123456-05:00");
final ImmutableTestThing
ething = // Thing from Builder with an EXTRA predicate, which is not a static field
ething = // JThing from Builder with an EXTRA predicate, which is not a static field
ImmutableTestThing.builder()
.iri("https://enola.dev/test1")
.label("hello, world")
Expand All @@ -61,7 +61,7 @@ public class TestThingTest {
.build();

final ImmutableTestThing
mthing = // Thing without one of the static (ImmutableTestThing.NUMBER_URI predicate)
mthing = // JThing without one of the static (ImmutableTestThing.NUMBER_URI predicate)
// fields set!
ImmutableTestThing.builder()
.iri("https://enola.dev/test1")
Expand Down
Loading

0 comments on commit 36cc8dd

Please sign in to comment.