improved data architecture

This commit is contained in:
2024-02-09 22:43:31 +08:00
parent f77a5c3e0d
commit e3d99fa178
34 changed files with 1188 additions and 267 deletions

View File

@@ -5,6 +5,8 @@ module net.woggioni.jpacrepo.api {
requires jakarta.persistence;
requires jakarta.annotation;
requires jakarta.json.bind;
requires jakarta.cdi;
requires jakarta.json;
exports net.woggioni.jpacrepo.api.model;
exports net.woggioni.jpacrepo.api.service;

View File

@@ -0,0 +1,16 @@
package net.woggioni.jpacrepo.api.jsonb;
import jakarta.json.bind.serializer.JsonbSerializer;
import jakarta.json.bind.serializer.SerializationContext;
import jakarta.json.stream.JsonGenerator;
import net.woggioni.jpacrepo.api.model.NamedEntity;
public class NamedEntitySerializer implements JsonbSerializer<NamedEntity> {
@Override
public void serialize(
NamedEntity namedEntity,
JsonGenerator jsonGenerator,
SerializationContext serializationContext) {
serializationContext.serialize(namedEntity.getName(), jsonGenerator);
}
}

View File

@@ -0,0 +1,22 @@
package net.woggioni.jpacrepo.api.jsonb;
import jakarta.json.bind.serializer.JsonbSerializer;
import jakarta.json.bind.serializer.SerializationContext;
import jakarta.json.stream.JsonGenerator;
import net.woggioni.jpacrepo.api.model.NamedEntity;
import java.util.Set;
public class SetSerializer implements JsonbSerializer<Set<NamedEntity>> {
@Override
public void serialize(
Set<NamedEntity> namedEntities,
JsonGenerator jsonGenerator,
SerializationContext serializationContext) {
jsonGenerator.writeStartArray();
for(NamedEntity namedEntity : namedEntities) {
serializationContext.serialize(namedEntity.getName(), jsonGenerator);
}
jsonGenerator.writeEnd();
}
}

View File

@@ -0,0 +1,40 @@
package net.woggioni.jpacrepo.api.model;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.woggioni.jpacrepo.api.jsonb.NamedEntitySerializer;
import java.util.Comparator;
import java.util.Objects;
import java.util.jar.Attributes;
@Entity
@Access(AccessType.PROPERTY)
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
@JsonbTypeSerializer(NamedEntitySerializer.class)
public class Dependency extends NamedEntity implements Comparable<Dependency> {
public static Dependency of(String name) {
var result = new Dependency();
result.setName(name);
return result;
}
@Override
public int compareTo(Dependency o) {
return super.compareTo(o);
}
}

View File

@@ -0,0 +1,30 @@
package net.woggioni.jpacrepo.api.model;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.Entity;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import net.woggioni.jpacrepo.api.jsonb.NamedEntitySerializer;
@Entity
@Access(AccessType.PROPERTY)
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
@JsonbTypeSerializer(NamedEntitySerializer.class)
public class License extends NamedEntity implements Comparable<License> {
public static License of(String name) {
var result = new License();
result.setName(name);
return result;
}
@Override
public int compareTo(License o) {
return super.compareTo(o);
}
}

View File

@@ -0,0 +1,56 @@
package net.woggioni.jpacrepo.api.model;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.Column;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import jakarta.xml.bind.annotation.XmlTransient;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.woggioni.jpacrepo.api.jsonb.NamedEntitySerializer;
import java.util.Comparator;
import java.util.Objects;
@Getter
@Setter
@Access(AccessType.PROPERTY)
@NoArgsConstructor
@MappedSuperclass
@JsonbTypeSerializer(NamedEntitySerializer.class)
public abstract class NamedEntity {
@Getter(onMethod_ = {
@Column(unique = true, length = 1024),
})
private String name;
@Getter(onMethod_ = {
@Id,
@GeneratedValue,
@XmlTransient
})
private long id;
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(Object obj) {
if(obj.getClass() == getClass()) {
NamedEntity other = (NamedEntity) obj;
return Objects.equals(getName(), other.getName());
} else {
return false;
}
}
public int compareTo(NamedEntity o) {
return Comparator.<String>naturalOrder().compare(getName(), o.getName());
}
}

View File

@@ -0,0 +1,28 @@
package net.woggioni.jpacrepo.api.model;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.Entity;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import net.woggioni.jpacrepo.api.jsonb.NamedEntitySerializer;
@Entity
@Access(AccessType.PROPERTY)
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
@JsonbTypeSerializer(NamedEntitySerializer.class)
public class Packager extends NamedEntity implements Comparable<Packager> {
public static Packager of(String name) {
var result = new Packager();
result.setName(name);
return result;
}
@Override
public int compareTo(Packager o) {
return super.compareTo(o);
}
}

View File

@@ -0,0 +1,31 @@
package net.woggioni.jpacrepo.api.model;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.Entity;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import net.woggioni.jpacrepo.api.jsonb.NamedEntitySerializer;
@Entity
@Access(AccessType.PROPERTY)
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
@JsonbTypeSerializer(NamedEntitySerializer.class)
public class PkgBase extends NamedEntity implements Comparable<PkgBase> {
public static PkgBase of(String name) {
var result = new PkgBase();
result.setName(name);
return result;
}
@Override
public int compareTo(PkgBase o) {
return super.compareTo(o);
}
}

View File

@@ -1,17 +1,18 @@
package net.woggioni.jpacrepo.api.model;
import jakarta.json.bind.annotation.JsonbTransient;
import jakarta.json.bind.annotation.JsonbVisibility;
import jakarta.json.bind.config.PropertyVisibilityStrategy;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;
@@ -19,73 +20,144 @@ import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlTransient;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.woggioni.jpacrepo.api.jsonb.SetSerializer;
import java.io.Serializable;
import java.time.Instant;
import java.util.Objects;
import java.util.Set;
@Data
@Setter
@Getter
@NoArgsConstructor
@Entity
@Access(AccessType.FIELD)
@NamedQueries(value = {
@NamedQuery(name = "searchByFileName", query = "SELECT p FROM PkgData p WHERE p.fileName = :fileName"),
@NamedQuery(name = "searchByName", query = "SELECT p FROM PkgData p WHERE p.id.name = :name"),
@NamedQuery(name = "searchById", query = "SELECT p FROM PkgData p WHERE p.id = :id"),
@NamedQuery(name = "searchByHash", query = "SELECT p FROM PkgData p WHERE p.md5sum = :md5sum")
})
@Access(AccessType.PROPERTY)
@Table(indexes = {
@Index(columnList = "md5sum", unique = true),
@Index(columnList = "fileName", unique = true)
@Index(columnList = "fileName", unique = true),
@Index(columnList = "name, version, arch, compressionformat", unique = true)
})
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
public class PkgData implements Serializable {
@EmbeddedId
private PkgId id;
@Getter(onMethod_ = {
@Embedded,
@Column(unique = true)
})
private PkgId pkgId;
private String base;
@Getter(onMethod_ = {
@Id,
@GeneratedValue,
@XmlTransient,
@JsonbTransient
})
private long id;
@Getter(onMethod_ = {
@ManyToOne
})
private PkgBase base;
@Getter(
onMethod_ = {
@Column(length = 1024)
})
private String description;
@Getter(
onMethod_ = {
@Column(length = 1024)
})
private String url;
private Instant buildDate;
private String packager;
@Getter(onMethod_ = {
@ManyToOne
})
private Packager packager;
private long size;
private String license;
@Getter(onMethod_ = {
@ManyToMany,
@JoinTable(name = "PkgData_license")
})
@JsonbTypeSerializer(SetSerializer.class)
private Set<License> license;
private String md5sum;
@Getter(
onMethod_ = {
@Column(length = 16)
})
private byte[] md5sum;
@Getter(
onMethod_ = {
@Column(length = 1024)
})
private String fileName;
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> replaces;
@Getter(onMethod_ = {
@ManyToMany,
@JoinTable(name = "PkgData_replaces")
})
@JsonbTypeSerializer(SetSerializer.class)
private Set<Dependency> replaces;
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> conflict;
@Getter(onMethod_ = {
@ManyToMany,
@JoinTable(name = "PkgData_conflict")
})
@JsonbTypeSerializer(SetSerializer.class)
private Set<Dependency> conflict;
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> provides;
@Getter(onMethod_ = {
@ManyToMany,
@JoinTable(name = "PkgData_provides")
})
@JsonbTypeSerializer(SetSerializer.class)
private Set<Dependency> provides;
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> depend;
@Getter(onMethod_ = {
@ManyToMany,
@JoinTable(name = "PkgData_depend")
})
@JsonbTypeSerializer(SetSerializer.class)
private Set<Dependency> depend;
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> optdepend;
@Getter(onMethod_ = {
@ManyToMany,
@JoinTable(name = "PkgData_optdepend")
})
@JsonbTypeSerializer(SetSerializer.class)
private Set<Dependency> optdepend;
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> makedepend;
@Getter(onMethod_ = {
@ManyToMany,
@JoinTable(name = "PkgData_makedepend")
})
@JsonbTypeSerializer(SetSerializer.class)
private Set<Dependency> makedepend;
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> makeopkgopt;
@Getter(onMethod_ = {
@ManyToMany,
@JoinTable(name = "PkgData_makepkgopt"),
})
@JsonbTypeSerializer(SetSerializer.class)
private Set<Dependency> makepkgopt;
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> backup;
@Getter(onMethod_ = {
@ManyToMany,
@JoinTable(name = "PkgData_backup"),
})
@JsonbTypeSerializer(SetSerializer.class)
private Set<Dependency> backup;
@XmlTransient
@JsonbTransient
@@ -96,5 +168,19 @@ public class PkgData implements Serializable {
private void writeTimestamp() {
updTimestamp = Instant.now();
}
@Override
public int hashCode() {
return pkgId.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof PkgData other) {
return Objects.equals(id, other.id);
} else {
return false;
}
}
}

View File

@@ -2,6 +2,7 @@ package net.woggioni.jpacrepo.api.model;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
@@ -9,21 +10,41 @@ import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
import java.util.Objects;
@Data
@Embeddable
@Access(AccessType.FIELD)
@Access(AccessType.PROPERTY)
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
public class PkgId implements Serializable {
@Getter(
onMethod_ = {
@Column(length = 64)
})
private String name;
@Getter(
onMethod_ = {
@Column(length = 64)
})
private String version;
@Getter(
onMethod_ = {
@Column(length = 16)
})
private String arch;
@Enumerated(EnumType.ORDINAL)
@Getter(
onMethod_ = {
@Enumerated(EnumType.ORDINAL)
})
private CompressionFormat compressionFormat;
}

View File

@@ -15,6 +15,7 @@ import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.Set;
@Remote
@@ -41,7 +42,7 @@ public interface PacmanServiceRemote {
CompressionFormat compressionFormat);
@Nullable
PkgData getPackage(PkgId pkgId);
Optional<PkgData> getPackage(PkgId pkgId);
@Nullable
Long getFileSize(String fileName);

View File

@@ -0,0 +1,35 @@
package net.woggioni.jpacrepo.api.wire;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import net.woggioni.jpacrepo.api.model.PkgId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@XmlRootElement(name = "pkgIds")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class PkgIdList extends ArrayList<PkgId> {
public PkgIdList() {}
public PkgIdList(Collection<PkgId> c) {
super(c);
}
public PkgIdList(PkgId... elements) {
for (PkgId el : elements) add(el);
}
@XmlElement(name = "pkgId")
public List<PkgId> getItems() {
return this;
}
public void setItems(List<PkgId> pkgs) {
this.clear();
this.addAll(pkgs);
}
}