RelationProposal.java
package com.taxonomy.relations.model;
import jakarta.persistence.*;
import org.hibernate.annotations.Nationalized;
import java.time.Instant;
import com.taxonomy.catalog.model.TaxonomyNode;
import com.taxonomy.model.ProposalStatus;
import com.taxonomy.model.RelationType;
/**
* A proposed relation between two taxonomy nodes, awaiting human review.
* Created by the Relation Proposal Pipeline.
*/
@Entity
@Table(name = "relation_proposal",
uniqueConstraints = @UniqueConstraint(
columnNames = {"source_node_id", "target_node_id", "relation_type"}))
public class RelationProposal {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "source_node_id", nullable = false)
private TaxonomyNode sourceNode;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "target_node_id", nullable = false)
private TaxonomyNode targetNode;
@Enumerated(EnumType.STRING)
@Column(name = "relation_type", nullable = false)
private RelationType relationType;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private ProposalStatus status = ProposalStatus.PENDING;
/** Confidence score between 0.0 and 1.0. */
@Column(nullable = false)
private double confidence;
/** Human-readable explanation of why this relation was proposed. */
@Nationalized
@Column(length = 2000)
private String rationale;
/** How this proposal was generated (e.g. "hybrid-search", "embedding-similarity"). */
@Nationalized
private String provenance;
@Column(name = "created_at", nullable = false, updatable = false)
private Instant createdAt;
@Column(name = "reviewed_at")
private Instant reviewedAt;
@Column(name = "workspace_id")
private String workspaceId;
@Column(name = "owner_username")
private String ownerUsername;
@PrePersist
void onCreate() {
if (createdAt == null) {
createdAt = Instant.now();
}
}
// ── Getters / Setters ─────────────────────────────────────────────────────
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public TaxonomyNode getSourceNode() { return sourceNode; }
public void setSourceNode(TaxonomyNode sourceNode) { this.sourceNode = sourceNode; }
public TaxonomyNode getTargetNode() { return targetNode; }
public void setTargetNode(TaxonomyNode targetNode) { this.targetNode = targetNode; }
public RelationType getRelationType() { return relationType; }
public void setRelationType(RelationType relationType) { this.relationType = relationType; }
public ProposalStatus getStatus() { return status; }
public void setStatus(ProposalStatus status) { this.status = status; }
public double getConfidence() { return confidence; }
public void setConfidence(double confidence) { this.confidence = confidence; }
public String getRationale() { return rationale; }
public void setRationale(String rationale) { this.rationale = rationale; }
public String getProvenance() { return provenance; }
public void setProvenance(String provenance) { this.provenance = provenance; }
public Instant getCreatedAt() { return createdAt; }
public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; }
public Instant getReviewedAt() { return reviewedAt; }
public void setReviewedAt(Instant reviewedAt) { this.reviewedAt = reviewedAt; }
public String getWorkspaceId() { return workspaceId; }
public void setWorkspaceId(String workspaceId) { this.workspaceId = workspaceId; }
public String getOwnerUsername() { return ownerUsername; }
public void setOwnerUsername(String ownerUsername) { this.ownerUsername = ownerUsername; }
}