1use crate::types::{FieldValue, FormData};
7use indexmap::IndexMap;
8use xfa_layout_engine::form::{DrawContent, FormNodeId, FormNodeType, FormTree};
9
10pub fn json_to_form_tree(data: &FormData, tree: &mut FormTree, root: FormNodeId) {
15 let node = tree.get(root);
16 let children: Vec<FormNodeId> = node.children.clone();
17
18 match &node.node_type {
19 FormNodeType::Root | FormNodeType::PageSet | FormNodeType::PageArea { .. } => {
20 for child_id in children {
21 merge_node(data, tree, child_id, "");
22 }
23 }
24 _ => {
25 merge_node(data, tree, root, "");
26 }
27 }
28}
29
30fn merge_node(data: &FormData, tree: &mut FormTree, node_id: FormNodeId, parent_path: &str) {
32 let node = tree.get(node_id);
33 let name = node.name.clone();
34 let path = if parent_path.is_empty() {
35 name.clone()
36 } else {
37 format!("{parent_path}.{name}")
38 };
39
40 let node_type = node.node_type.clone();
41 let children: Vec<FormNodeId> = node.children.clone();
42 let is_repeating = node.occur.is_repeating();
43
44 match node_type {
45 FormNodeType::Field { .. } => {
46 if let Some(value) = data.fields.get(&path) {
47 let string_value = field_value_to_string(value);
48 tree.get_mut(node_id).node_type = FormNodeType::Field {
49 value: string_value,
50 };
51 }
52 }
53 FormNodeType::Draw(..) => {
54 if let Some(value) = data.fields.get(&path) {
55 let string_value = field_value_to_string(value);
56 tree.get_mut(node_id).node_type =
57 FormNodeType::Draw(DrawContent::Text(string_value));
58 }
59 }
60 FormNodeType::Image { .. } => {
61 }
63 FormNodeType::Subform | FormNodeType::Area | FormNodeType::ExclGroup => {
66 if is_repeating {
67 } else {
70 merge_children_with_repeating_groups(data, tree, &children, &path);
71 }
72 }
73 FormNodeType::SubformSet
74 | FormNodeType::Root
75 | FormNodeType::PageSet
76 | FormNodeType::PageArea { .. } => {
77 merge_children_with_repeating_groups(data, tree, &children, &path);
78 }
79 }
80}
81
82fn merge_children_with_repeating_groups(
85 data: &FormData,
86 tree: &mut FormTree,
87 children: &[FormNodeId],
88 parent_path: &str,
89) {
90 let mut repeating_counts: IndexMap<String, usize> = IndexMap::new();
92
93 for &child_id in children {
94 let child = tree.get(child_id);
95 let is_repeating = child.occur.is_repeating();
96
97 if is_repeating {
98 let name = child.name.clone();
99 let index = repeating_counts.get(&name).copied().unwrap_or(0);
100 repeating_counts.insert(name.clone(), index + 1);
101
102 let path = if parent_path.is_empty() {
103 name
104 } else {
105 format!("{parent_path}.{name}")
106 };
107
108 if let Some(FieldValue::Array(instances)) = data.fields.get(&path) {
110 if let Some(instance_data) = instances.get(index) {
111 merge_instance(tree, child_id, instance_data);
112 }
113 }
114 } else {
115 merge_node(data, tree, child_id, parent_path);
116 }
117 }
118}
119
120fn merge_instance(
123 tree: &mut FormTree,
124 node_id: FormNodeId,
125 instance_data: &IndexMap<String, FieldValue>,
126) {
127 let children: Vec<FormNodeId> = tree.get(node_id).children.clone();
128
129 for &child_id in &children {
130 let child = tree.get(child_id);
131 let child_name = child.name.clone();
132 let child_type = child.node_type.clone();
133
134 match child_type {
135 FormNodeType::Field { .. } => {
136 if let Some(value) = instance_data.get(&child_name) {
137 let string_value = field_value_to_string(value);
138 tree.get_mut(child_id).node_type = FormNodeType::Field {
139 value: string_value,
140 };
141 }
142 }
143 FormNodeType::Draw(..) => {
144 if let Some(value) = instance_data.get(&child_name) {
145 let string_value = field_value_to_string(value);
146 tree.get_mut(child_id).node_type =
147 FormNodeType::Draw(DrawContent::Text(string_value));
148 }
149 }
150 FormNodeType::Subform => {
151 let nested_prefix = format!("{child_name}.");
153 let nested_data: IndexMap<String, FieldValue> = instance_data
154 .iter()
155 .filter_map(|(k, v)| {
156 k.strip_prefix(&nested_prefix)
157 .map(|rest| (rest.to_string(), v.clone()))
158 })
159 .collect();
160 if !nested_data.is_empty() {
161 merge_instance(tree, child_id, &nested_data);
162 }
163 }
164 _ => {}
165 }
166 }
167}
168
169fn field_value_to_string(value: &FieldValue) -> String {
171 match value {
172 FieldValue::Text(s) => s.clone(),
173 FieldValue::Number(n) => {
174 if *n == n.trunc() && n.abs() < 1e15 {
175 format!("{}", *n as i64)
176 } else {
177 n.to_string()
178 }
179 }
180 FieldValue::Boolean(b) => if *b { "1" } else { "0" }.to_string(),
181 FieldValue::Null => String::new(),
182 FieldValue::Array(_) => String::new(),
183 }
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189 use crate::export::form_tree_to_json;
190 use indexmap::IndexMap;
191 use xfa_layout_engine::form::{FormNode, Occur};
192 use xfa_layout_engine::text::FontMetrics;
193 use xfa_layout_engine::types::{BoxModel, LayoutStrategy};
194
195 fn make_field(tree: &mut FormTree, name: &str, value: &str) -> FormNodeId {
196 tree.add_node(FormNode {
197 name: name.to_string(),
198 node_type: FormNodeType::Field {
199 value: value.to_string(),
200 },
201 box_model: BoxModel::default(),
202 layout: LayoutStrategy::Positioned,
203 children: vec![],
204 occur: Occur::once(),
205 font: FontMetrics::default(),
206 calculate: None,
207 validate: None,
208 column_widths: vec![],
209 col_span: 1,
210 })
211 }
212
213 fn make_subform(tree: &mut FormTree, name: &str, children: Vec<FormNodeId>) -> FormNodeId {
214 make_subform_with_occur(tree, name, children, Occur::once())
215 }
216
217 fn make_subform_with_occur(
218 tree: &mut FormTree,
219 name: &str,
220 children: Vec<FormNodeId>,
221 occur: Occur,
222 ) -> FormNodeId {
223 tree.add_node(FormNode {
224 name: name.to_string(),
225 node_type: FormNodeType::Subform,
226 box_model: BoxModel::default(),
227 layout: LayoutStrategy::TopToBottom,
228 children,
229 occur,
230 font: FontMetrics::default(),
231 calculate: None,
232 validate: None,
233 column_widths: vec![],
234 col_span: 1,
235 })
236 }
237
238 fn make_root(tree: &mut FormTree, children: Vec<FormNodeId>) -> FormNodeId {
239 tree.add_node(FormNode {
240 name: "Root".to_string(),
241 node_type: FormNodeType::Root,
242 box_model: BoxModel::default(),
243 layout: LayoutStrategy::TopToBottom,
244 children,
245 occur: Occur::once(),
246 font: FontMetrics::default(),
247 calculate: None,
248 validate: None,
249 column_widths: vec![],
250 col_span: 1,
251 })
252 }
253
254 #[test]
255 fn roundtrip_simple_form() {
256 let mut tree = FormTree::new();
257 let name = make_field(&mut tree, "Name", "Original");
258 let amount = make_field(&mut tree, "Amount", "100");
259 let form = make_subform(&mut tree, "form1", vec![name, amount]);
260 let root = make_root(&mut tree, vec![form]);
261
262 let mut data = form_tree_to_json(&tree, root);
264 data.fields.insert(
265 "form1.Name".to_string(),
266 FieldValue::Text("Updated".to_string()),
267 );
268 data.fields
269 .insert("form1.Amount".to_string(), FieldValue::Number(200.0));
270
271 json_to_form_tree(&data, &mut tree, root);
272
273 let exported = form_tree_to_json(&tree, root);
275 assert_eq!(
276 exported.fields.get("form1.Name"),
277 Some(&FieldValue::Text("Updated".to_string()))
278 );
279 assert_eq!(
280 exported.fields.get("form1.Amount"),
281 Some(&FieldValue::Number(200.0))
282 );
283 }
284
285 #[test]
286 fn import_boolean_as_zero_one() {
287 let mut tree = FormTree::new();
288 let check = make_field(&mut tree, "Active", "0");
289 let form = make_subform(&mut tree, "form1", vec![check]);
290 let root = make_root(&mut tree, vec![form]);
291
292 let mut fields = IndexMap::new();
293 fields.insert("form1.Active".to_string(), FieldValue::Boolean(true));
294 let data = FormData { fields };
295
296 json_to_form_tree(&data, &mut tree, root);
297
298 match &tree.get(check).node_type {
300 FormNodeType::Field { value } => assert_eq!(value, "1"),
301 _ => panic!("Expected Field"),
302 }
303 }
304
305 #[test]
306 fn import_null_clears_field() {
307 let mut tree = FormTree::new();
308 let field = make_field(&mut tree, "Note", "something");
309 let form = make_subform(&mut tree, "form1", vec![field]);
310 let root = make_root(&mut tree, vec![form]);
311
312 let mut fields = IndexMap::new();
313 fields.insert("form1.Note".to_string(), FieldValue::Null);
314 let data = FormData { fields };
315
316 json_to_form_tree(&data, &mut tree, root);
317
318 match &tree.get(field).node_type {
319 FormNodeType::Field { value } => assert_eq!(value, ""),
320 _ => panic!("Expected Field"),
321 }
322 }
323
324 #[test]
325 fn field_value_to_string_formats() {
326 assert_eq!(field_value_to_string(&FieldValue::Number(42.0)), "42");
327 assert_eq!(field_value_to_string(&FieldValue::Number(3.14)), "3.14");
328 assert_eq!(field_value_to_string(&FieldValue::Boolean(true)), "1");
329 assert_eq!(field_value_to_string(&FieldValue::Boolean(false)), "0");
330 assert_eq!(field_value_to_string(&FieldValue::Null), "");
331 assert_eq!(
332 field_value_to_string(&FieldValue::Text("hi".to_string())),
333 "hi"
334 );
335 }
336
337 #[test]
338 fn import_repeating_by_index_not_always_first() {
339 let mut tree = FormTree::new();
341 let desc1 = make_field(&mut tree, "Desc", "old1");
342 let qty1 = make_field(&mut tree, "Qty", "0");
343 let item1 = make_subform_with_occur(
344 &mut tree,
345 "Item",
346 vec![desc1, qty1],
347 Occur::repeating(0, None, 2),
348 );
349
350 let desc2 = make_field(&mut tree, "Desc", "old2");
351 let qty2 = make_field(&mut tree, "Qty", "0");
352 let item2 = make_subform_with_occur(
353 &mut tree,
354 "Item",
355 vec![desc2, qty2],
356 Occur::repeating(0, None, 2),
357 );
358
359 let form = make_subform(&mut tree, "form1", vec![item1, item2]);
360 let root = make_root(&mut tree, vec![form]);
361
362 let mut instance0 = IndexMap::new();
364 instance0.insert("Desc".to_string(), FieldValue::Text("Widget A".to_string()));
365 instance0.insert("Qty".to_string(), FieldValue::Number(10.0));
366 let mut instance1 = IndexMap::new();
367 instance1.insert("Desc".to_string(), FieldValue::Text("Widget B".to_string()));
368 instance1.insert("Qty".to_string(), FieldValue::Number(5.0));
369
370 let mut fields = IndexMap::new();
371 fields.insert(
372 "form1.Item".to_string(),
373 FieldValue::Array(vec![instance0, instance1]),
374 );
375 let data = FormData { fields };
376
377 json_to_form_tree(&data, &mut tree, root);
378
379 match &tree.get(desc1).node_type {
381 FormNodeType::Field { value } => assert_eq!(value, "Widget A"),
382 _ => panic!("Expected Field"),
383 }
384 match &tree.get(desc2).node_type {
385 FormNodeType::Field { value } => assert_eq!(value, "Widget B"),
386 _ => panic!("Expected Field"),
387 }
388 match &tree.get(qty1).node_type {
389 FormNodeType::Field { value } => assert_eq!(value, "10"),
390 _ => panic!("Expected Field"),
391 }
392 match &tree.get(qty2).node_type {
393 FormNodeType::Field { value } => assert_eq!(value, "5"),
394 _ => panic!("Expected Field"),
395 }
396 }
397
398 #[test]
399 fn import_nested_subform_inside_repeating() {
400 let mut tree = FormTree::new();
402
403 let street1 = make_field(&mut tree, "Street", "old");
405 let addr1 = make_subform(&mut tree, "Address", vec![street1]);
406 let name1 = make_field(&mut tree, "Name", "old");
407 let item1 = make_subform_with_occur(
408 &mut tree,
409 "Item",
410 vec![name1, addr1],
411 Occur::repeating(0, None, 2),
412 );
413
414 let street2 = make_field(&mut tree, "Street", "old");
415 let addr2 = make_subform(&mut tree, "Address", vec![street2]);
416 let name2 = make_field(&mut tree, "Name", "old");
417 let item2 = make_subform_with_occur(
418 &mut tree,
419 "Item",
420 vec![name2, addr2],
421 Occur::repeating(0, None, 2),
422 );
423
424 let form = make_subform(&mut tree, "form1", vec![item1, item2]);
425 let root = make_root(&mut tree, vec![form]);
426
427 let mut inst0 = IndexMap::new();
429 inst0.insert("Name".to_string(), FieldValue::Text("Alice".to_string()));
430 inst0.insert(
431 "Address.Street".to_string(),
432 FieldValue::Text("123 Main St".to_string()),
433 );
434 let mut inst1 = IndexMap::new();
435 inst1.insert("Name".to_string(), FieldValue::Text("Bob".to_string()));
436 inst1.insert(
437 "Address.Street".to_string(),
438 FieldValue::Text("456 Oak Ave".to_string()),
439 );
440
441 let mut fields = IndexMap::new();
442 fields.insert(
443 "form1.Item".to_string(),
444 FieldValue::Array(vec![inst0, inst1]),
445 );
446 let data = FormData { fields };
447
448 json_to_form_tree(&data, &mut tree, root);
449
450 match &tree.get(name1).node_type {
452 FormNodeType::Field { value } => assert_eq!(value, "Alice"),
453 _ => panic!("Expected Field"),
454 }
455 match &tree.get(street1).node_type {
456 FormNodeType::Field { value } => assert_eq!(value, "123 Main St"),
457 _ => panic!("Expected Field"),
458 }
459 match &tree.get(name2).node_type {
460 FormNodeType::Field { value } => assert_eq!(value, "Bob"),
461 _ => panic!("Expected Field"),
462 }
463 match &tree.get(street2).node_type {
464 FormNodeType::Field { value } => assert_eq!(value, "456 Oak Ave"),
465 _ => panic!("Expected Field"),
466 }
467 }
468}