1use serde::{Deserialize, Serialize};
2
3use super::super::{DomainError, GraphVersion, RepositoryCodeRange, error::required_text};
4use super::validation::{normalize_optional, stable_software_id, validate_confidence};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct SoftwareFile {
9 pub software_file_id: String,
10 pub repository_id: String,
11 pub source_scope: String,
12 pub path: String,
13 pub language_id: String,
14 pub file_role: String,
15 pub parse_status: String,
16 pub created_graph_version: GraphVersion,
17}
18
19impl SoftwareFile {
20 pub fn new(input: SoftwareFileInput) -> Result<Self, DomainError> {
22 let source_scope = required_text("source_scope", input.source_scope)?;
23 let path = required_text("software_file_path", input.path)?;
24
25 Ok(Self {
26 software_file_id: stable_software_id("file", [source_scope.as_str(), path.as_str()]),
27 repository_id: required_text("repository_id", input.repository_id)?,
28 source_scope,
29 path,
30 language_id: required_text("language_id", input.language_id)?,
31 file_role: required_text("file_role", input.file_role)?,
32 parse_status: required_text("parse_status", input.parse_status)?,
33 created_graph_version: input.created_graph_version,
34 })
35 }
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct SoftwareFileInput {
41 pub repository_id: String,
42 pub source_scope: String,
43 pub path: String,
44 pub language_id: String,
45 pub file_role: String,
46 pub parse_status: String,
47 pub created_graph_version: GraphVersion,
48}
49
50#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
52pub struct SoftwareTopic {
53 pub topic_id: String,
54 pub repository_id: String,
55 pub source_scope: String,
56 pub name: String,
57 pub topic_kind: String,
58 pub source_path: String,
59 pub line_range: RepositoryCodeRange,
60 pub created_graph_version: GraphVersion,
61}
62
63impl SoftwareTopic {
64 pub fn new(input: SoftwareTopicInput) -> Result<Self, DomainError> {
66 let source_scope = required_text("source_scope", input.source_scope)?;
67 let name = required_text("topic_name", input.name)?;
68 let topic_kind = required_text("topic_kind", input.topic_kind)?;
69 let source_path = required_text("topic_source_path", input.source_path)?;
70 let line_start = input.line_range.start.to_string();
71
72 Ok(Self {
73 topic_id: stable_software_id(
74 "topic",
75 [
76 source_scope.as_str(),
77 topic_kind.as_str(),
78 source_path.as_str(),
79 name.as_str(),
80 line_start.as_str(),
81 ],
82 ),
83 repository_id: required_text("repository_id", input.repository_id)?,
84 source_scope,
85 name,
86 topic_kind,
87 source_path,
88 line_range: input.line_range,
89 created_graph_version: input.created_graph_version,
90 })
91 }
92}
93
94#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct SoftwareTopicInput {
97 pub repository_id: String,
98 pub source_scope: String,
99 pub name: String,
100 pub topic_kind: String,
101 pub source_path: String,
102 pub line_range: RepositoryCodeRange,
103 pub created_graph_version: GraphVersion,
104}
105
106#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
108pub struct SoftwareRelationship {
109 pub relationship_id: String,
110 pub repository_id: String,
111 pub source_scope: String,
112 pub relationship_kind: String,
113 pub source_id: String,
114 pub source_kind: String,
115 pub target_id: String,
116 pub target_kind: String,
117 #[serde(skip_serializing_if = "Option::is_none")]
118 pub target_hint: Option<String>,
119 pub resolution_state: String,
120 pub confidence_basis_points: u16,
121 pub confidence_tier: String,
122 pub evidence_path: String,
123 pub evidence_line_range: RepositoryCodeRange,
124 pub created_graph_version: GraphVersion,
125}
126
127impl SoftwareRelationship {
128 pub fn new(input: SoftwareRelationshipInput) -> Result<Self, DomainError> {
130 let source_scope = required_text("source_scope", input.source_scope)?;
131 let relationship_kind = required_text("relationship_kind", input.relationship_kind)?;
132 let source_id = required_text("relationship_source_id", input.source_id)?;
133 let target_id = required_text("relationship_target_id", input.target_id)?;
134 let evidence_path = required_text("evidence_path", input.evidence_path)?;
135 let line_start = input.evidence_line_range.start.to_string();
136
137 Ok(Self {
138 relationship_id: stable_software_id(
139 "relationship",
140 [
141 source_scope.as_str(),
142 relationship_kind.as_str(),
143 source_id.as_str(),
144 target_id.as_str(),
145 evidence_path.as_str(),
146 line_start.as_str(),
147 ],
148 ),
149 repository_id: required_text("repository_id", input.repository_id)?,
150 source_scope,
151 relationship_kind,
152 source_id,
153 source_kind: required_text("relationship_source_kind", input.source_kind)?,
154 target_id,
155 target_kind: required_text("relationship_target_kind", input.target_kind)?,
156 target_hint: normalize_optional("target_hint", input.target_hint)?,
157 resolution_state: required_text("resolution_state", input.resolution_state)?,
158 confidence_basis_points: validate_confidence(input.confidence_basis_points)?,
159 confidence_tier: required_text("confidence_tier", input.confidence_tier)?,
160 evidence_path,
161 evidence_line_range: input.evidence_line_range,
162 created_graph_version: input.created_graph_version,
163 })
164 }
165}
166
167#[derive(Debug, Clone, PartialEq, Eq)]
169pub struct SoftwareRelationshipInput {
170 pub repository_id: String,
171 pub source_scope: String,
172 pub relationship_kind: String,
173 pub source_id: String,
174 pub source_kind: String,
175 pub target_id: String,
176 pub target_kind: String,
177 pub target_hint: Option<String>,
178 pub resolution_state: String,
179 pub confidence_basis_points: u16,
180 pub confidence_tier: String,
181 pub evidence_path: String,
182 pub evidence_line_range: RepositoryCodeRange,
183 pub created_graph_version: GraphVersion,
184}
185
186#[cfg(test)]
187#[path = "graph_tests.rs"]
188mod tests;