diff --git a/core/src/main/java/org/incenp/linkml/core/ClassInfo.java b/core/src/main/java/org/incenp/linkml/core/ClassInfo.java index 6f9346b..642e6e7 100644 --- a/core/src/main/java/org/incenp/linkml/core/ClassInfo.java +++ b/core/src/main/java/org/incenp/linkml/core/ClassInfo.java @@ -117,7 +117,9 @@ private ClassInfo(Class klass) { identifierIsLocal = identifierSlot.isLocalIdentifier(); } else if ( slot.isExtensionStore() ) { extensionSlot = slot; - } else if ( slot.isTypeDesignator() ) { + } + + if ( slot.isTypeDesignator() ) { designatorSlot = slot; } diff --git a/core/src/main/java/org/incenp/linkml/core/ObjectConverter.java b/core/src/main/java/org/incenp/linkml/core/ObjectConverter.java index f65c506..a449b07 100644 --- a/core/src/main/java/org/incenp/linkml/core/ObjectConverter.java +++ b/core/src/main/java/org/incenp/linkml/core/ObjectConverter.java @@ -309,14 +309,6 @@ protected List getGlobalIdentifierList(Object raw, ConverterContext ctx) @Override public Object serialise(Object object, ConverterContext ctx) throws LinkMLRuntimeException { - // Search for a more specialised converter. - // FIXME: Looks a bit too much like a hack... - IConverter conv = ctx.getConverter(object.getClass()); - if ( conv instanceof ObjectConverter ) { - if ( ((ObjectConverter) conv).klass.getParents().contains(klass) ) { - return ((ObjectConverter) conv).serialise(object, true, ctx); - } - } return serialise(object, true, ctx); } @@ -346,6 +338,15 @@ public Map serialise(Object object, boolean withIdentifier, Conv throw new LinkMLValueError(String.format(OBJECT_EXPECTED, getType().getName())); } + // Search for a more specialised converter. + // FIXME: Looks a bit too much like a hack... + IConverter conv = ctx.getConverter(object.getClass()); + if ( conv instanceof ObjectConverter && conv != this ) { + if ( ((ObjectConverter) conv).klass.getParents().contains(klass) ) { + return ((ObjectConverter) conv).serialise(object, withIdentifier, ctx); + } + } + Map raw = new HashMap<>(); for ( Slot slot : klass.getSlots() ) { if ( (slot.isIdentifier()) && !withIdentifier ) { @@ -390,9 +391,10 @@ public Object serialiseForSlot(Object object, Slot slot, ConverterContext ctx) t } return list; } else if ( inlining == InliningMode.DICT ) { - boolean simpleDict = klass.isEligibleForSimpleDict(true); + // boolean simpleDict = klass.isEligibleForSimpleDict(true); Map map = new HashMap<>(); for ( Object item : items ) { + boolean simpleDict = ClassInfo.get(item.getClass()).isEligibleForSimpleDict(true); Object rawItem = simpleDict ? klass.getPrimarySlot().getValue(item) : serialise(item, false, ctx); map.put(toIdentifier(item, ctx), rawItem); } @@ -434,7 +436,11 @@ protected Object toIdentifier(Object object, ConverterContext ctx) throws LinkML Slot identifierSlot = klass.getIdentifierSlot(); Object identifier = identifierSlot.getValue(object); if ( identifier == null ) { - throw new LinkMLValueError(String.format(NO_IDENTIFIER, getType().getName())); + if ( identifierSlot.isTypeDesignator() ) { + identifier = new TypeDesignatorResolver().getDesignator(ClassInfo.get(object.getClass())); + } else { + throw new LinkMLValueError(String.format(NO_IDENTIFIER, getType().getName())); + } } return ctx.getConverter(identifierSlot).serialise(identifier, ctx); } diff --git a/core/src/test/java/org/incenp/linkml/core/ObjectConverterTest.java b/core/src/test/java/org/incenp/linkml/core/ObjectConverterTest.java index 12dc534..f3cf32e 100644 --- a/core/src/test/java/org/incenp/linkml/core/ObjectConverterTest.java +++ b/core/src/test/java/org/incenp/linkml/core/ObjectConverterTest.java @@ -43,6 +43,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -54,19 +55,25 @@ import org.incenp.linkml.core.samples.base.ContainerOfAny; import org.incenp.linkml.core.samples.base.ContainerOfBooleanValues; import org.incenp.linkml.core.samples.base.ContainerOfIRIIdentifiableObjects; +import org.incenp.linkml.core.samples.base.ContainerOfIdentifiedSelfDesignatedObjects; import org.incenp.linkml.core.samples.base.ContainerOfInlinedObjects; import org.incenp.linkml.core.samples.base.ContainerOfIntegerValues; +import org.incenp.linkml.core.samples.base.ContainerOfKeyedSelfDesignatedObjects; import org.incenp.linkml.core.samples.base.ContainerOfReferences; import org.incenp.linkml.core.samples.base.ContainerOfSelfDesignatedObjects; import org.incenp.linkml.core.samples.base.ContainerOfSimpleDicts; import org.incenp.linkml.core.samples.base.ContainerOfSimpleObjects; import org.incenp.linkml.core.samples.base.DerivedCurieSelfDesignatedClass; +import org.incenp.linkml.core.samples.base.DerivedIdentifiedSelfDesignatedClass; +import org.incenp.linkml.core.samples.base.DerivedKeyedSelfDesignatedClass; import org.incenp.linkml.core.samples.base.DerivedMultiSelfDesignatedClass; import org.incenp.linkml.core.samples.base.DerivedSelfDesignatedClass; import org.incenp.linkml.core.samples.base.DerivedURISelfDesignatedClass; import org.incenp.linkml.core.samples.base.ExtensibleSimpleClass; import org.incenp.linkml.core.samples.base.ExtraSimpleDict; import org.incenp.linkml.core.samples.base.IRISimpleIdentifiableClass; +import org.incenp.linkml.core.samples.base.IdentifiedSelfDesignatedClass; +import org.incenp.linkml.core.samples.base.KeyedSelfDesignatedClass; import org.incenp.linkml.core.samples.base.MultivaluedSimpleDict; import org.incenp.linkml.core.samples.base.SampleEnum; import org.incenp.linkml.core.samples.base.SecondDerivedSelfDesignatedClass; @@ -515,6 +522,128 @@ void testMultiLevelTypeDesignators() throws IOException { roundtrip(cosdo); } + @Test + void testKeyTypeDesignator() throws IOException, LinkMLRuntimeException { + ContainerOfKeyedSelfDesignatedObjects cksdo = parse("container-of-keyed-self-designated-objects.yaml", + ContainerOfKeyedSelfDesignatedObjects.class); + + HashMap d = new HashMap<>(); + for ( KeyedSelfDesignatedClass o : cksdo.getObjects() ) { + d.put(o.getType(), o); + } + KeyedSelfDesignatedClass ksdc = d.get("KeyedSelfDesignatedClass"); + Assertions.assertNotNull(ksdc); + Assertions.assertEquals("Alice", ksdc.getFrobnicator()); + + KeyedSelfDesignatedClass ksdc2 = d.get("DerivedKeyedSelfDesignatedClass"); + Assertions.assertNotNull(ksdc2); + Assertions.assertEquals("Bob", ksdc2.getFrobnicator()); + Assertions.assertInstanceOf(DerivedKeyedSelfDesignatedClass.class, ksdc2); + Assertions.assertEquals(123, ((DerivedKeyedSelfDesignatedClass) ksdc2).getLength()); + + // Remove the base object, because the roundtrip test is + // sensible to the order of the objects in the list, which is + // not guaranteed to be preserved since the list is serialised + // as a dictionary. Still, if we can read back the one-item + // list, this is enough to know that serialisation works as + // expected. + cksdo.getObjects().remove(ksdc); + roundtrip(cksdo); + + // Try serialising again, but this time with the type designator unset; the + // correct type designator should still appear in the serialised object + ksdc2.setType(null); + ObjectConverter conv = (ObjectConverter) ctx.getConverter(cksdo.getClass()); + Map raw = conv.serialise(cksdo, true, ctx); + @SuppressWarnings("unchecked") + Map objects = (Map) raw.get("objects"); + Assertions.assertTrue(objects.containsKey("DerivedKeyedSelfDesignatedClass")); + } + + @Test + void testKeyTypeDesignatorWithUnknownType() throws IOException, LinkMLRuntimeException { + String test = "objects:\n" + + " UnknownSelfDesignatedClass:\n" + + " frobnicator: \"Charlie\"\n" + + " width: 456\n"; + ContainerOfKeyedSelfDesignatedObjects cksdo = parseString(test, ContainerOfKeyedSelfDesignatedObjects.class); + KeyedSelfDesignatedClass ksdc = cksdo.getObjects().get(0); + Assertions.assertNotNull(ksdc); + Assertions.assertEquals("UnknownSelfDesignatedClass", ksdc.getType()); + Assertions.assertEquals("Charlie", ksdc.getFrobnicator()); + Assertions.assertEquals(456, ksdc.getExtraSlots().get("width")); + + roundtrip(cksdo); + + // Try serialising again, but this time with the type designator slot unset; the + // base type designator should still appear in the serialised object + ksdc.setType(null); + ObjectConverter conv = (ObjectConverter) ctx.getConverter(cksdo.getClass()); + Map raw = conv.serialise(cksdo, true, ctx); + @SuppressWarnings("unchecked") + Map objects = (Map) raw.get("objects"); + Assertions.assertTrue(objects.containsKey("KeyedSelfDesignatedClass")); + } + + @Test + void testKeyTypeDesignatorWithSimpleDictMix() throws IOException, LinkMLRuntimeException { + // Same test case as "testKeyTypeDesignator" above, except that the base class + // instance is serialised as a "simple dict" entry, while the derived instance + // is serialised as a "compact dict". + String test = "objects:\n" + + " KeyedSelfDesignatedClass: Alice\n" + + " DerivedKeyedSelfDesignatedClass:\n" + + " frobnicator: Bob\n" + + " length: 123\n"; + ContainerOfKeyedSelfDesignatedObjects cksdo = parseString(test, ContainerOfKeyedSelfDesignatedObjects.class); + + HashMap d = new HashMap<>(); + for ( KeyedSelfDesignatedClass o : cksdo.getObjects() ) { + d.put(o.getType(), o); + } + KeyedSelfDesignatedClass ksdc = d.get("KeyedSelfDesignatedClass"); + Assertions.assertNotNull(ksdc); + Assertions.assertEquals("Alice", ksdc.getFrobnicator()); + + KeyedSelfDesignatedClass ksdc2 = d.get("DerivedKeyedSelfDesignatedClass"); + Assertions.assertNotNull(ksdc2); + Assertions.assertEquals("Bob", ksdc2.getFrobnicator()); + Assertions.assertInstanceOf(DerivedKeyedSelfDesignatedClass.class, ksdc2); + Assertions.assertEquals(123, ((DerivedKeyedSelfDesignatedClass) ksdc2).getLength()); + } + + @Test + void testIdentifierTypeDesignator() throws IOException { + String test = "objects:\n" + + " 'EX:IdentifiedSelfDesignatedClass': Alice\n" + + " 'EX:DerivedIdentifiedSelfDesignatedClass':\n" + + " frobnicator: Bob\n" + + " length: 123\n"; + // Make sure the derived class and its IRI are known + ClassInfo.get(DerivedIdentifiedSelfDesignatedClass.class); + // Make sure the context knows about the EX prefix + ctx.addPrefix("EX", TEST_NS); + ContainerOfIdentifiedSelfDesignatedObjects cisdo = parseString(test, + ContainerOfIdentifiedSelfDesignatedObjects.class); + + HashMap d = new HashMap<>(); + for ( IdentifiedSelfDesignatedClass o : cisdo.getObjects() ) { + d.put(o.getType(), o); + } + IdentifiedSelfDesignatedClass isdc = d.get(TEST_NS + "IdentifiedSelfDesignatedClass"); + Assertions.assertNotNull(isdc); + Assertions.assertEquals("Alice", isdc.getFrobnicator()); + + IdentifiedSelfDesignatedClass isdc2 = d.get(TEST_NS + "DerivedIdentifiedSelfDesignatedClass"); + Assertions.assertNotNull(isdc2); + Assertions.assertEquals("Bob", isdc2.getFrobnicator()); + Assertions.assertInstanceOf(DerivedIdentifiedSelfDesignatedClass.class, isdc2); + Assertions.assertEquals(123, ((DerivedIdentifiedSelfDesignatedClass) isdc2).getLength()); + + cisdo.getObjects().remove(isdc); + roundtrip(cisdo); + } + @Test void testReferenceToIRIIdentifiers() throws IOException, LinkMLRuntimeException { ctx.addPrefix("PFX", "https://example.org/"); diff --git a/core/src/test/java/org/incenp/linkml/core/samples/base/ContainerOfIdentifiedSelfDesignatedObjects.java b/core/src/test/java/org/incenp/linkml/core/samples/base/ContainerOfIdentifiedSelfDesignatedObjects.java new file mode 100644 index 0000000..fd02a31 --- /dev/null +++ b/core/src/test/java/org/incenp/linkml/core/samples/base/ContainerOfIdentifiedSelfDesignatedObjects.java @@ -0,0 +1,82 @@ +package org.incenp.linkml.core.samples.base; + +import java.net.URI; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.incenp.linkml.core.annotations.Converter; +import org.incenp.linkml.core.annotations.ExtensionHolder; +import org.incenp.linkml.core.annotations.Identifier; +import org.incenp.linkml.core.annotations.Inlined; +import org.incenp.linkml.core.annotations.LinkURI; +import org.incenp.linkml.core.annotations.Required; +import org.incenp.linkml.core.annotations.SlotName; +import org.incenp.linkml.core.annotations.TypeDesignator; +import org.incenp.linkml.core.CurieConverter; + +@LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#ContainerOfIdentifiedSelfDesignatedObjects") +public class ContainerOfIdentifiedSelfDesignatedObjects { + + @Inlined + @LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#objects") + private List objects; + + public void setObjects(List objects) { + this.objects = objects; + } + + public List getObjects() { + return this.objects; + } + + public List getObjects(boolean set) { + if ( this.objects == null && set ) { + this.objects = new ArrayList<>(); + } + return this.objects; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Object o; + sb.append("ContainerOfIdentifiedSelfDesignatedObjects("); + if ( (o = this.getObjects()) != null ) { + sb.append("objects="); + sb.append(o); + sb.append(","); + } + sb.append(")"); + return sb.toString(); + } + + @Override + public boolean equals(final Object o) { + if ( o == this ) return true; + if ( !(o instanceof ContainerOfIdentifiedSelfDesignatedObjects) ) return false; + final ContainerOfIdentifiedSelfDesignatedObjects other = (ContainerOfIdentifiedSelfDesignatedObjects) o; + if ( !other.canEqual((Object) this)) return false; + final Object this$objects = this.getObjects(); + final Object other$objects = other.getObjects(); + if ( this$objects == null ? other$objects != null : !this$objects.equals(other$objects)) return false; + return true; + } + + protected boolean canEqual(final Object other) { + return other instanceof ContainerOfIdentifiedSelfDesignatedObjects; + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + final Object $objects = this.getObjects(); + result = result * PRIME + ($objects == null ? 43 : $objects.hashCode()); + return result; + } +} \ No newline at end of file diff --git a/core/src/test/java/org/incenp/linkml/core/samples/base/ContainerOfKeyedSelfDesignatedObjects.java b/core/src/test/java/org/incenp/linkml/core/samples/base/ContainerOfKeyedSelfDesignatedObjects.java new file mode 100644 index 0000000..ed92db3 --- /dev/null +++ b/core/src/test/java/org/incenp/linkml/core/samples/base/ContainerOfKeyedSelfDesignatedObjects.java @@ -0,0 +1,82 @@ +package org.incenp.linkml.core.samples.base; + +import java.net.URI; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.incenp.linkml.core.annotations.Converter; +import org.incenp.linkml.core.annotations.ExtensionHolder; +import org.incenp.linkml.core.annotations.Identifier; +import org.incenp.linkml.core.annotations.Inlined; +import org.incenp.linkml.core.annotations.LinkURI; +import org.incenp.linkml.core.annotations.Required; +import org.incenp.linkml.core.annotations.SlotName; +import org.incenp.linkml.core.annotations.TypeDesignator; +import org.incenp.linkml.core.CurieConverter; + +@LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#ContainerOfKeyedSelfDesignatedObjects") +public class ContainerOfKeyedSelfDesignatedObjects { + + @Inlined + @LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#objects") + private List objects; + + public void setObjects(List objects) { + this.objects = objects; + } + + public List getObjects() { + return this.objects; + } + + public List getObjects(boolean set) { + if ( this.objects == null && set ) { + this.objects = new ArrayList<>(); + } + return this.objects; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Object o; + sb.append("ContainerOfKeyedSelfDesignatedObjects("); + if ( (o = this.getObjects()) != null ) { + sb.append("objects="); + sb.append(o); + sb.append(","); + } + sb.append(")"); + return sb.toString(); + } + + @Override + public boolean equals(final Object o) { + if ( o == this ) return true; + if ( !(o instanceof ContainerOfKeyedSelfDesignatedObjects) ) return false; + final ContainerOfKeyedSelfDesignatedObjects other = (ContainerOfKeyedSelfDesignatedObjects) o; + if ( !other.canEqual((Object) this)) return false; + final Object this$objects = this.getObjects(); + final Object other$objects = other.getObjects(); + if ( this$objects == null ? other$objects != null : !this$objects.equals(other$objects)) return false; + return true; + } + + protected boolean canEqual(final Object other) { + return other instanceof ContainerOfKeyedSelfDesignatedObjects; + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + final Object $objects = this.getObjects(); + result = result * PRIME + ($objects == null ? 43 : $objects.hashCode()); + return result; + } +} \ No newline at end of file diff --git a/core/src/test/java/org/incenp/linkml/core/samples/base/DerivedIdentifiedSelfDesignatedClass.java b/core/src/test/java/org/incenp/linkml/core/samples/base/DerivedIdentifiedSelfDesignatedClass.java new file mode 100644 index 0000000..4ab81df --- /dev/null +++ b/core/src/test/java/org/incenp/linkml/core/samples/base/DerivedIdentifiedSelfDesignatedClass.java @@ -0,0 +1,67 @@ +package org.incenp.linkml.core.samples.base; + +import java.net.URI; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.incenp.linkml.core.annotations.Converter; +import org.incenp.linkml.core.annotations.ExtensionHolder; +import org.incenp.linkml.core.annotations.Identifier; +import org.incenp.linkml.core.annotations.Inlined; +import org.incenp.linkml.core.annotations.LinkURI; +import org.incenp.linkml.core.annotations.Required; +import org.incenp.linkml.core.annotations.SlotName; +import org.incenp.linkml.core.annotations.TypeDesignator; +import org.incenp.linkml.core.CurieConverter; + +@LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#DerivedIdentifiedSelfDesignatedClass") +public class DerivedIdentifiedSelfDesignatedClass extends IdentifiedSelfDesignatedClass { + + @LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#length") + private Integer length; + + public void setLength(Integer length) { + this.length = length; + } + + public Integer getLength() { + return this.length; + } + + @Override + public String toString() { + return "DerivedIdentifiedSelfDesignatedClass(type=" + this.getType() + ")"; + } + + @Override + public boolean equals(final Object o) { + if ( o == this ) return true; + if ( !(o instanceof DerivedIdentifiedSelfDesignatedClass) ) return false; + final DerivedIdentifiedSelfDesignatedClass other = (DerivedIdentifiedSelfDesignatedClass) o; + if ( !other.canEqual((Object) this)) return false; + if ( !super.equals(o) ) return false; + + final Object this$length = this.getLength(); + final Object other$length = other.getLength(); + if ( this$length == null ? other$length != null : !this$length.equals(other$length)) return false; + return true; + } + + protected boolean canEqual(final Object other) { + return other instanceof DerivedIdentifiedSelfDesignatedClass; + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = super.hashCode(); + final Object $length = this.getLength(); + result = result * PRIME + ($length == null ? 43 : $length.hashCode()); + return result; + } +} \ No newline at end of file diff --git a/core/src/test/java/org/incenp/linkml/core/samples/base/DerivedKeyedSelfDesignatedClass.java b/core/src/test/java/org/incenp/linkml/core/samples/base/DerivedKeyedSelfDesignatedClass.java new file mode 100644 index 0000000..99ac744 --- /dev/null +++ b/core/src/test/java/org/incenp/linkml/core/samples/base/DerivedKeyedSelfDesignatedClass.java @@ -0,0 +1,67 @@ +package org.incenp.linkml.core.samples.base; + +import java.net.URI; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.incenp.linkml.core.annotations.Converter; +import org.incenp.linkml.core.annotations.ExtensionHolder; +import org.incenp.linkml.core.annotations.Identifier; +import org.incenp.linkml.core.annotations.Inlined; +import org.incenp.linkml.core.annotations.LinkURI; +import org.incenp.linkml.core.annotations.Required; +import org.incenp.linkml.core.annotations.SlotName; +import org.incenp.linkml.core.annotations.TypeDesignator; +import org.incenp.linkml.core.CurieConverter; + +@LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#DerivedKeyedSelfDesignatedClass") +public class DerivedKeyedSelfDesignatedClass extends KeyedSelfDesignatedClass { + + @LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#length") + private Integer length; + + public void setLength(Integer length) { + this.length = length; + } + + public Integer getLength() { + return this.length; + } + + @Override + public String toString() { + return "DerivedKeyedSelfDesignatedClass(type=" + this.getType() + ")"; + } + + @Override + public boolean equals(final Object o) { + if ( o == this ) return true; + if ( !(o instanceof DerivedKeyedSelfDesignatedClass) ) return false; + final DerivedKeyedSelfDesignatedClass other = (DerivedKeyedSelfDesignatedClass) o; + if ( !other.canEqual((Object) this)) return false; + if ( !super.equals(o) ) return false; + + final Object this$length = this.getLength(); + final Object other$length = other.getLength(); + if ( this$length == null ? other$length != null : !this$length.equals(other$length)) return false; + return true; + } + + protected boolean canEqual(final Object other) { + return other instanceof DerivedKeyedSelfDesignatedClass; + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = super.hashCode(); + final Object $length = this.getLength(); + result = result * PRIME + ($length == null ? 43 : $length.hashCode()); + return result; + } +} \ No newline at end of file diff --git a/core/src/test/java/org/incenp/linkml/core/samples/base/IdentifiedSelfDesignatedClass.java b/core/src/test/java/org/incenp/linkml/core/samples/base/IdentifiedSelfDesignatedClass.java new file mode 100644 index 0000000..943f95f --- /dev/null +++ b/core/src/test/java/org/incenp/linkml/core/samples/base/IdentifiedSelfDesignatedClass.java @@ -0,0 +1,85 @@ +package org.incenp.linkml.core.samples.base; + +import java.net.URI; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.incenp.linkml.core.annotations.Converter; +import org.incenp.linkml.core.annotations.ExtensionHolder; +import org.incenp.linkml.core.annotations.Identifier; +import org.incenp.linkml.core.annotations.Inlined; +import org.incenp.linkml.core.annotations.LinkURI; +import org.incenp.linkml.core.annotations.Required; +import org.incenp.linkml.core.annotations.SlotName; +import org.incenp.linkml.core.annotations.TypeDesignator; +import org.incenp.linkml.core.CurieConverter; + +@LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#IdentifiedSelfDesignatedClass") +public class IdentifiedSelfDesignatedClass { + + @Identifier + @TypeDesignator + @Required + @Converter(CurieConverter.class) + @LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#type") + private String type; + + @LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#frobnicator") + private String frobnicator; + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return this.type; + } + + public void setFrobnicator(String frobnicator) { + this.frobnicator = frobnicator; + } + + public String getFrobnicator() { + return this.frobnicator; + } + + @Override + public String toString() { + return "IdentifiedSelfDesignatedClass(type=" + this.getType() + ")"; + } + + @Override + public boolean equals(final Object o) { + if ( o == this ) return true; + if ( !(o instanceof IdentifiedSelfDesignatedClass) ) return false; + final IdentifiedSelfDesignatedClass other = (IdentifiedSelfDesignatedClass) o; + if ( !other.canEqual((Object) this)) return false; + final Object this$type = this.getType(); + final Object other$type = other.getType(); + if ( this$type == null ? other$type != null : !this$type.equals(other$type)) return false; + final Object this$frobnicator = this.getFrobnicator(); + final Object other$frobnicator = other.getFrobnicator(); + if ( this$frobnicator == null ? other$frobnicator != null : !this$frobnicator.equals(other$frobnicator)) return false; + return true; + } + + protected boolean canEqual(final Object other) { + return other instanceof IdentifiedSelfDesignatedClass; + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + final Object $type = this.getType(); + result = result * PRIME + ($type == null ? 43 : $type.hashCode()); + final Object $frobnicator = this.getFrobnicator(); + result = result * PRIME + ($frobnicator == null ? 43 : $frobnicator.hashCode()); + return result; + } +} \ No newline at end of file diff --git a/core/src/test/java/org/incenp/linkml/core/samples/base/KeyedSelfDesignatedClass.java b/core/src/test/java/org/incenp/linkml/core/samples/base/KeyedSelfDesignatedClass.java new file mode 100644 index 0000000..fb8d93d --- /dev/null +++ b/core/src/test/java/org/incenp/linkml/core/samples/base/KeyedSelfDesignatedClass.java @@ -0,0 +1,102 @@ +package org.incenp.linkml.core.samples.base; + +import java.net.URI; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.incenp.linkml.core.annotations.Converter; +import org.incenp.linkml.core.annotations.ExtensionHolder; +import org.incenp.linkml.core.annotations.Identifier; +import org.incenp.linkml.core.annotations.Inlined; +import org.incenp.linkml.core.annotations.LinkURI; +import org.incenp.linkml.core.annotations.Required; +import org.incenp.linkml.core.annotations.SlotName; +import org.incenp.linkml.core.annotations.TypeDesignator; +import org.incenp.linkml.core.CurieConverter; + +@LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#KeyedSelfDesignatedClass") +public class KeyedSelfDesignatedClass { + + @Identifier(isGlobal = false) + @TypeDesignator + @Required + @LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#type") + private String type; + + @LinkURI("https://incenp.org/dvlpt/linkml-java/tests/samples#frobnicator") + private String frobnicator; + + @ExtensionHolder + private Map extraSlots; + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return this.type; + } + + public void setFrobnicator(String frobnicator) { + this.frobnicator = frobnicator; + } + + public String getFrobnicator() { + return this.frobnicator; + } + + public void setExtraSlots(Map extraSlots) { + this.extraSlots = extraSlots; + } + + public Map getExtraSlots() { + return this.extraSlots; + } + + public Map getExtraSlots(boolean set) { + if ( this.extraSlots == null && set ) { + this.extraSlots = new HashMap<>(); + } + return this.extraSlots; + } + + @Override + public String toString() { + return "KeyedSelfDesignatedClass(type=" + this.getType() + ")"; + } + + @Override + public boolean equals(final Object o) { + if ( o == this ) return true; + if ( !(o instanceof KeyedSelfDesignatedClass) ) return false; + final KeyedSelfDesignatedClass other = (KeyedSelfDesignatedClass) o; + if ( !other.canEqual((Object) this)) return false; + final Object this$type = this.getType(); + final Object other$type = other.getType(); + if ( this$type == null ? other$type != null : !this$type.equals(other$type)) return false; + final Object this$frobnicator = this.getFrobnicator(); + final Object other$frobnicator = other.getFrobnicator(); + if ( this$frobnicator == null ? other$frobnicator != null : !this$frobnicator.equals(other$frobnicator)) return false; + return true; + } + + protected boolean canEqual(final Object other) { + return other instanceof KeyedSelfDesignatedClass; + } + + @Override + public int hashCode() { + final int PRIME = 59; + int result = 1; + final Object $type = this.getType(); + result = result * PRIME + ($type == null ? 43 : $type.hashCode()); + final Object $frobnicator = this.getFrobnicator(); + result = result * PRIME + ($frobnicator == null ? 43 : $frobnicator.hashCode()); + return result; + } +} \ No newline at end of file diff --git a/core/src/test/linkml/samples.yaml b/core/src/test/linkml/samples.yaml index 36c80e9..6ec28fc 100644 --- a/core/src/test/linkml/samples.yaml +++ b/core/src/test/linkml/samples.yaml @@ -387,6 +387,68 @@ classes: range: Anything multivalued: true + KeyedSelfDesignatedClass: + description: >- + A class with a slot that is both a type designator and a key slot. + attributes: + type: + designates_type: true + key: true + frobnicator: + extra_slots: + allowed: true + + DerivedKeyedSelfDesignatedClass: + description: >- + A class that derives from a class with a slot that is both a type + designator and a key slot. + is_a: KeyedSelfDesignatedClass + attributes: + length: + range: integer + + ContainerOfKeyedSelfDesignatedObjects: + description: >- + A class with a slot whose range is set to a class with a slot that is + both a key slot and and a type designator slot. + attributes: + objects: + range: KeyedSelfDesignatedClass + multivalued: true + inlined: true + inlined_as_list: false + + IdentifiedSelfDesignatedClass: + description: >- + A class with a slot that is both a type designator and an + identifier slot. + attributes: + type: + designates_type: true + identifier: true + range: uriorcurie + frobnicator: + + DerivedIdentifiedSelfDesignatedClass: + description: >- + A class that derives from a class with a slot that is both a type + designator and an identifier slot. + is_a: IdentifiedSelfDesignatedClass + attributes: + length: + range: integer + + ContainerOfIdentifiedSelfDesignatedObjects: + description: >- + A class with a slot whose range is set to a class with a slot that is + both an identifier slot and and a type designator slot. + attributes: + objects: + range: IdentifiedSelfDesignatedClass + multivalued: true + inlined: true + inlined_as_list: false + enums: diff --git a/core/src/test/resources/core/samples/container-of-keyed-self-designated-objects.yaml b/core/src/test/resources/core/samples/container-of-keyed-self-designated-objects.yaml new file mode 100644 index 0000000..5e964fb --- /dev/null +++ b/core/src/test/resources/core/samples/container-of-keyed-self-designated-objects.yaml @@ -0,0 +1,6 @@ +objects: + DerivedKeyedSelfDesignatedClass: + frobnicator: Bob + length: 123 + KeyedSelfDesignatedClass: + frobnicator: Alice \ No newline at end of file