From 2d7c7fea9c51fe3ad48100d3b6c5292ae7ecf67a Mon Sep 17 00:00:00 2001 From: "kirill.labutin" Date: Fri, 2 Jan 2026 23:56:25 +0300 Subject: [PATCH] =?UTF-8?q?WIP:=20=D0=BF=D1=80=D0=BE=D0=BC=D0=B5=D0=B6?= =?UTF-8?q?=D1=83=D1=82=D0=BE=D1=87=D0=BD=D1=8B=D0=B9=20=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=D0=BC=D0=B8=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kirillius/XCP/Persistence/NodeEntity.java | 7 +--- .../XCP/Persistence/NodeRepository.java | 2 - .../Repositories/TagRepository.java | 3 ++ .../XCP/Persistence/TagCollection.java | 9 +++++ .../EntityReferenceSerializer.java | 8 ++-- .../PersistenceSerializationModule.java | 11 +++++- .../Repositories/GroupRepositoryImpl.java | 15 +++++-- .../Repositories/TagRepositoryImpl.java | 21 +++++++++- .../XCP/Persistence/TagCollectionImpl.java | 8 ++++ .../XCP/Persistence/TagSetDeserializer.java | 39 +++++++++++++++++++ .../XCP/Persistence/TagSetSerializer.java | 30 ++++++++++++++ .../Repositories/GenericRepositoryTest.java | 14 ++++++- .../Repositories/GroupRepositoryImplTest.java | 28 ++++++++++++- .../Repositories/TagRepositoryImplTest.java | 3 +- .../Repositories/UserRepositoryImplTest.java | 3 +- 15 files changed, 176 insertions(+), 25 deletions(-) create mode 100644 api/src/main/java/ru/kirillius/XCP/Persistence/TagCollection.java create mode 100644 database/src/main/java/ru/kirillius/XCP/Persistence/TagCollectionImpl.java create mode 100644 database/src/main/java/ru/kirillius/XCP/Persistence/TagSetDeserializer.java create mode 100644 database/src/main/java/ru/kirillius/XCP/Persistence/TagSetSerializer.java diff --git a/api/src/main/java/ru/kirillius/XCP/Persistence/NodeEntity.java b/api/src/main/java/ru/kirillius/XCP/Persistence/NodeEntity.java index 29e9ef6..f5e52ef 100644 --- a/api/src/main/java/ru/kirillius/XCP/Persistence/NodeEntity.java +++ b/api/src/main/java/ru/kirillius/XCP/Persistence/NodeEntity.java @@ -1,11 +1,8 @@ package ru.kirillius.XCP.Persistence; import ru.kirillius.XCP.Persistence.Entities.Group; -import ru.kirillius.XCP.Persistence.Entities.Tag; import tools.jackson.databind.node.ObjectNode; -import java.util.Set; - public interface NodeEntity extends PersistenceEntity { String getName(); @@ -27,7 +24,7 @@ public interface NodeEntity extends PersistenceEntity { void setProperties(ObjectNode properties); - Set getTags(); + TagCollection getTags(); - void setTags(Set tags); + void setTags(TagCollection tags); } diff --git a/api/src/main/java/ru/kirillius/XCP/Persistence/NodeRepository.java b/api/src/main/java/ru/kirillius/XCP/Persistence/NodeRepository.java index 96bb22e..b7479b3 100644 --- a/api/src/main/java/ru/kirillius/XCP/Persistence/NodeRepository.java +++ b/api/src/main/java/ru/kirillius/XCP/Persistence/NodeRepository.java @@ -10,6 +10,4 @@ public interface NodeRepository extends Repository { StreamHandler getByGroup(Group group); StreamHandler getByTags(Collection tags); - - } diff --git a/api/src/main/java/ru/kirillius/XCP/Persistence/Repositories/TagRepository.java b/api/src/main/java/ru/kirillius/XCP/Persistence/Repositories/TagRepository.java index 76aa8e0..b8be6b7 100644 --- a/api/src/main/java/ru/kirillius/XCP/Persistence/Repositories/TagRepository.java +++ b/api/src/main/java/ru/kirillius/XCP/Persistence/Repositories/TagRepository.java @@ -3,6 +3,7 @@ package ru.kirillius.XCP.Persistence.Repositories; import ru.kirillius.XCP.Commons.ResourceHandler; import ru.kirillius.XCP.Persistence.Entities.Tag; import ru.kirillius.XCP.Persistence.Repository; +import ru.kirillius.XCP.Persistence.TagCollection; import java.util.Collection; import java.util.stream.Stream; @@ -11,4 +12,6 @@ public interface TagRepository extends Repository { Tag getByName(String name); ResourceHandler> getByNames(Collection names); + + TagCollection createCollection(); } diff --git a/api/src/main/java/ru/kirillius/XCP/Persistence/TagCollection.java b/api/src/main/java/ru/kirillius/XCP/Persistence/TagCollection.java new file mode 100644 index 0000000..c813763 --- /dev/null +++ b/api/src/main/java/ru/kirillius/XCP/Persistence/TagCollection.java @@ -0,0 +1,9 @@ +package ru.kirillius.XCP.Persistence; + +import ru.kirillius.XCP.Persistence.Entities.Tag; + +import java.util.Collection; + +public interface TagCollection extends Collection { + +} diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/EntityReferenceSerializer.java b/database/src/main/java/ru/kirillius/XCP/Persistence/EntityReferenceSerializer.java index 8087b74..796ddff 100644 --- a/database/src/main/java/ru/kirillius/XCP/Persistence/EntityReferenceSerializer.java +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/EntityReferenceSerializer.java @@ -6,16 +6,16 @@ import tools.jackson.databind.SerializationContext; import tools.jackson.databind.ser.std.StdSerializer; public class EntityReferenceSerializer extends StdSerializer { - private RepositoryServiceImpl repositoryService; + private final RepositoryServiceImpl repositoryService; public EntityReferenceSerializer(RepositoryServiceImpl repositoryService) { super(EntityReference.class); this.repositoryService = repositoryService; } - protected EntityReferenceSerializer(Class t) { - super(t); - } +// protected EntityReferenceSerializer(Class t) { +// super(t); +// } @Override public void serialize(EntityReference reference, JsonGenerator gen, SerializationContext provider) throws JacksonException { diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/PersistenceSerializationModule.java b/database/src/main/java/ru/kirillius/XCP/Persistence/PersistenceSerializationModule.java index 1e990d9..6513cca 100644 --- a/database/src/main/java/ru/kirillius/XCP/Persistence/PersistenceSerializationModule.java +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/PersistenceSerializationModule.java @@ -8,6 +8,7 @@ import tools.jackson.databind.module.SimpleSerializers; import java.util.List; import java.util.Map; +import java.util.Set; class PersistenceSerializationModule extends JacksonModule { public PersistenceSerializationModule(RepositoryServiceImpl repositoryService) { @@ -29,7 +30,13 @@ class PersistenceSerializationModule extends JacksonModule { @Override public void setupModule(SetupContext context) { - context.addSerializers(new SimpleSerializers(List.of(new EntityReferenceSerializer(repositoryService)))); - context.addDeserializers(new SimpleDeserializers(Map.of(EntityReference.class, new EntityReferenceDeserializer(repositoryService)))); + context.addSerializers(new SimpleSerializers(List.of( + new EntityReferenceSerializer(repositoryService) + // new TagSetSerializer(repositoryService) + ))); + context.addDeserializers(new SimpleDeserializers(Map.of( + EntityReference.class, new EntityReferenceDeserializer(repositoryService) + // Set.class, new TagSetDeserializer(repositoryService) + ))); } } diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/GroupRepositoryImpl.java b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/GroupRepositoryImpl.java index a7a889d..3552958 100644 --- a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/GroupRepositoryImpl.java +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/GroupRepositoryImpl.java @@ -68,6 +68,8 @@ public class GroupRepositoryImpl extends AbstractNodeRepository implement super.store(entity); } + + @Entity @Table(name = "Groups") @Builder @@ -76,6 +78,8 @@ public class GroupRepositoryImpl extends AbstractNodeRepository implement @Getter @Setter public static class GroupEntity implements Group { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @JsonProperty @@ -120,13 +124,13 @@ public class GroupRepositoryImpl extends AbstractNodeRepository implement private GroupEntity parent; @JsonProperty("parent") - public EntityReference getParentReference() { + EntityReference getParentReference() { return new EntityReference(getParent()); } @JsonProperty("parent") - public void setParentReference(EntityReference entityReference) { - parent = (GroupEntity) entityReference.get(); + void setParentReference(EntityReference entityReference) { + parent = entityReference == null ? null : (GroupEntity) entityReference.get(); } public Group getParent() { @@ -137,6 +141,9 @@ public class GroupRepositoryImpl extends AbstractNodeRepository implement this.parent = (GroupEntity) parent; } + + + @Override public void setTags(Set tags) { this.tags = tags.stream().map(t -> (TagRepositoryImpl.TagEntity) t).collect(Collectors.toSet()); @@ -153,7 +160,7 @@ public class GroupRepositoryImpl extends AbstractNodeRepository implement @Setter private ObjectNode properties = SerializationUtils.EmptyObject(); - @JsonProperty + @JsonIgnore @ManyToMany(fetch = FetchType.EAGER) private Set tags = new HashSet<>(); diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/TagRepositoryImpl.java b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/TagRepositoryImpl.java index 62b1d71..4f06e8d 100644 --- a/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/TagRepositoryImpl.java +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/Repositories/TagRepositoryImpl.java @@ -24,12 +24,19 @@ public class TagRepositoryImpl extends AbstractRepository implements TagRep } - @Override public Tag getByName(String name) { try (var handler = buildQueryParametrized("WHERE name = ?1", name)) { var result = handler.get().findFirst(); - return result.orElse(null); + if (result.isPresent()) { + return result.get(); + } else { + var tag = create(); + tag.setName(name); + store(tag); + return tag; + } + } catch (IOException e) { throw new RuntimeException(e); } @@ -40,6 +47,11 @@ public class TagRepositoryImpl extends AbstractRepository implements TagRep return search("where name IN (?1)", List.of(names)); } + @Override + public TagCollection createCollection() { + return new TagCollectionImpl(); + } + @Entity @Table(name = "Tags") @Builder @@ -58,6 +70,11 @@ public class TagRepositoryImpl extends AbstractRepository implements TagRep @UuidGenerator private UUID uuid; + @Override + public String toString() { + return name; + } + @Column(nullable = false, unique = true) @JsonProperty private String name = ""; diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/TagCollectionImpl.java b/database/src/main/java/ru/kirillius/XCP/Persistence/TagCollectionImpl.java new file mode 100644 index 0000000..67917b5 --- /dev/null +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/TagCollectionImpl.java @@ -0,0 +1,8 @@ +package ru.kirillius.XCP.Persistence; + +import ru.kirillius.XCP.Persistence.Entities.Tag; + +import java.util.HashSet; + +public class TagCollectionImpl extends HashSet implements TagCollection { +} diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/TagSetDeserializer.java b/database/src/main/java/ru/kirillius/XCP/Persistence/TagSetDeserializer.java new file mode 100644 index 0000000..9559b26 --- /dev/null +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/TagSetDeserializer.java @@ -0,0 +1,39 @@ +package ru.kirillius.XCP.Persistence; + +import ru.kirillius.XCP.Persistence.Entities.Tag; +import ru.kirillius.XCP.Persistence.Repositories.TagRepository; +import tools.jackson.core.JacksonException; +import tools.jackson.core.JsonGenerator; +import tools.jackson.core.JsonParser; +import tools.jackson.core.JsonToken; +import tools.jackson.databind.DeserializationContext; +import tools.jackson.databind.SerializationContext; +import tools.jackson.databind.deser.std.StdDeserializer; +import tools.jackson.databind.ser.std.StdSerializer; + +import java.util.HashSet; +import java.util.Set; + +public class TagSetDeserializer extends StdDeserializer> { + private final RepositoryServiceImpl repositoryService; + + public TagSetDeserializer(RepositoryServiceImpl repositoryService) { + super(Set.class); + this.repositoryService = repositoryService; + } + + + @Override + public Set deserialize(JsonParser p, DeserializationContext ctxt) throws JacksonException { + var result = new HashSet(); + + var tagNames = p.readValueAs(String[].class); + var repository = repositoryService.getRepository(TagRepository.class); + + for (var name : tagNames) { + var tag = repository.getByName(name); + result.add(tag); + } + return result; + } +} diff --git a/database/src/main/java/ru/kirillius/XCP/Persistence/TagSetSerializer.java b/database/src/main/java/ru/kirillius/XCP/Persistence/TagSetSerializer.java new file mode 100644 index 0000000..52c2952 --- /dev/null +++ b/database/src/main/java/ru/kirillius/XCP/Persistence/TagSetSerializer.java @@ -0,0 +1,30 @@ +package ru.kirillius.XCP.Persistence; + +import ru.kirillius.XCP.Persistence.Entities.Tag; +import tools.jackson.core.JacksonException; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.JavaType; +import tools.jackson.databind.SerializationContext; +import tools.jackson.databind.ser.std.StdSerializer; + +import java.util.Set; + +public class TagSetSerializer extends StdSerializer> { + private final RepositoryServiceImpl repositoryService; + + public TagSetSerializer(RepositoryServiceImpl repositoryService) { + super(Set.class); + this.repositoryService = repositoryService; + } + + @Override + public void serialize(Set set, JsonGenerator gen, SerializationContext provider) throws JacksonException { + if(set == null) { + gen.writeNull(); + return; + } + gen.writeStartArray(); + set.forEach(tag -> gen.writeString(tag.getName())); + gen.writeEndArray(); + } +} diff --git a/database/src/test/java/ru/kirillius/XCP/Persistence/Repositories/GenericRepositoryTest.java b/database/src/test/java/ru/kirillius/XCP/Persistence/Repositories/GenericRepositoryTest.java index ae4951e..cbbb048 100644 --- a/database/src/test/java/ru/kirillius/XCP/Persistence/Repositories/GenericRepositoryTest.java +++ b/database/src/test/java/ru/kirillius/XCP/Persistence/Repositories/GenericRepositoryTest.java @@ -77,7 +77,7 @@ abstract class GenericRepositoryTest { @Override protected RepositoryService spawnRepositoryService() { - return instantiateTestService(List.of(repositoryClass, TagRepositoryImpl.class)); + var service = instantiateTestService(List.of(repositoryClass, TagRepositoryImpl.class)); + for (var i = 0; i < 5; i++) { + var tagRepository = service.getRepositoryForEntity(Tag.class); + var tag = tagRepository.create(); + tag.setName("tag" + i); + tagRepository.store(tag); + } + return service; } @Test @@ -117,7 +128,20 @@ class GroupRepositoryImplTest extends GenericRepositoryTest(handler.get().toList())); + } catch (IOException e) { + throw new RuntimeException(e); + } } } \ No newline at end of file diff --git a/database/src/test/java/ru/kirillius/XCP/Persistence/Repositories/TagRepositoryImplTest.java b/database/src/test/java/ru/kirillius/XCP/Persistence/Repositories/TagRepositoryImplTest.java index c041ce7..1d25a52 100644 --- a/database/src/test/java/ru/kirillius/XCP/Persistence/Repositories/TagRepositoryImplTest.java +++ b/database/src/test/java/ru/kirillius/XCP/Persistence/Repositories/TagRepositoryImplTest.java @@ -2,6 +2,7 @@ package ru.kirillius.XCP.Persistence.Repositories; import org.junit.jupiter.api.Test; import ru.kirillius.XCP.Persistence.Entities.Tag; +import ru.kirillius.XCP.Persistence.RepositoryService; import java.io.IOException; @@ -21,7 +22,7 @@ class TagRepositoryImplTest extends GenericRepositoryTest