1use petgraph::Graph;
2use std::collections::HashMap;
3
4use crate::{ClassNode, EdgeType, MethodConnectivity};
5
6pub type OwnedGraph = Graph<OwnedClassNode, EdgeType>;
8
9#[derive(Debug, Clone)]
15pub struct OwnedClassNode {
16 pub id: String,
18 pub name: String,
19 pub namespace: String,
20 pub line_count: u32,
21 pub method_count: u32,
22 pub halstead_eta1: u32,
23 pub halstead_eta2: u32,
24 pub halstead_n1: u32,
25 pub halstead_n2: u32,
26 pub method_connectivity: Option<MethodConnectivity>,
27 pub method_fingerprints: Option<serde_json::Value>,
29 pub method_tokens: Option<serde_json::Value>,
30 pub call_sequences: Option<serde_json::Value>,
31 pub cyclomatic_complexity: Option<serde_json::Value>,
32 pub path_conditions: Option<serde_json::Value>,
33 pub invariants: Option<serde_json::Value>,
34 pub error_messages: Option<serde_json::Value>,
35 pub magic_numbers: Option<serde_json::Value>,
36 pub dead_code: Option<serde_json::Value>,
37 pub tenant_branches: Option<serde_json::Value>,
38 pub state_transitions: Option<serde_json::Value>,
39}
40
41impl OwnedClassNode {
42 pub(crate) fn from_data(
43 id: &str,
44 data: &HashMap<String, String>,
45 ) -> Result<Self, crate::graphml::Error> {
46 use crate::graphml::Error;
47
48 let require = |key: &str| -> Result<&str, Error> {
49 data.get(key)
50 .map(String::as_str)
51 .ok_or_else(|| Error::MissingAttr(key.to_owned()))
52 };
53 let require_u32 = |key: &str| -> Result<u32, Error> {
54 require(key)?
55 .parse::<u32>()
56 .map_err(|e| Error::ParseInt { key: key.to_owned(), source: e })
57 };
58 let opt_u32 = |key: &str| -> u32 {
59 data.get(key).and_then(|s| s.parse().ok()).unwrap_or(0)
60 };
61 let opt_json = |key: &str| -> Result<Option<serde_json::Value>, Error> {
62 data.get(key)
63 .map(|s| {
64 serde_json::from_str(s)
65 .map_err(|e| Error::Json { key: key.to_owned(), source: e })
66 })
67 .transpose()
68 };
69
70 Ok(OwnedClassNode {
71 id: id.to_owned(),
72 name: require("name")?.to_owned(),
73 namespace: require("namespace")?.to_owned(),
74 line_count: require_u32("lineCount")?,
75 method_count: require_u32("methodCount")?,
76 halstead_eta1: opt_u32("halstead_eta1"),
77 halstead_eta2: opt_u32("halstead_eta2"),
78 halstead_n1: opt_u32("halstead_N1"),
79 halstead_n2: opt_u32("halstead_N2"),
80 method_connectivity: data
81 .get("methodConnectivity")
82 .map(|s| {
83 serde_json::from_str(s).map_err(|e| Error::Json {
84 key: "methodConnectivity".to_owned(),
85 source: e,
86 })
87 })
88 .transpose()?,
89 method_fingerprints: opt_json("methodFingerprints")?,
90 method_tokens: opt_json("methodTokens")?,
91 call_sequences: opt_json("callSequences")?,
92 cyclomatic_complexity: opt_json("cyclomaticComplexity")?,
93 path_conditions: opt_json("pathConditions")?,
94 invariants: opt_json("invariants")?,
95 error_messages: opt_json("errorMessages")?,
96 magic_numbers: opt_json("magicNumbers")?,
97 dead_code: opt_json("deadCode")?,
98 tenant_branches: opt_json("tenantBranches")?,
99 state_transitions: opt_json("stateTransitions")?,
100 })
101 }
102}
103
104impl ClassNode for OwnedClassNode {
105 fn id(&self) -> &str {
106 &self.id
107 }
108 fn namespace(&self) -> &str {
109 &self.namespace
110 }
111 fn line_count(&self) -> u32 {
112 self.line_count
113 }
114 fn method_count(&self) -> u32 {
115 self.method_count
116 }
117 fn method_connectivity(&self) -> Option<&MethodConnectivity> {
118 self.method_connectivity.as_ref()
119 }
120 fn cyclomatic_complexity(&self) -> Option<&serde_json::Value> {
121 self.cyclomatic_complexity.as_ref()
122 }
123 fn halstead_eta1(&self) -> u32 {
124 self.halstead_eta1
125 }
126 fn halstead_eta2(&self) -> u32 {
127 self.halstead_eta2
128 }
129 fn halstead_n1(&self) -> u32 {
130 self.halstead_n1
131 }
132 fn halstead_n2(&self) -> u32 {
133 self.halstead_n2
134 }
135 fn method_tokens(&self) -> Option<&serde_json::Value> {
136 self.method_tokens.as_ref()
137 }
138 fn method_fingerprints(&self) -> Option<&serde_json::Value> {
139 self.method_fingerprints.as_ref()
140 }
141 fn call_sequences(&self) -> Option<&serde_json::Value> {
142 self.call_sequences.as_ref()
143 }
144}
145