1use serde::{Deserialize, Serialize};
7
8use crate::wasm::Expression;
9
10fn is_false(b: &bool) -> bool {
12 !*b
13}
14
15fn is_empty_vec(v: &[String]) -> bool {
17 v.is_empty()
18}
19
20fn is_none<T>(opt: &Option<T>) -> bool {
22 opt.is_none()
23}
24
25#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38#[serde(tag = "annotation")]
39pub enum PlanningAnnotation {
40 PlanningId,
42
43 PlanningEntity,
46
47 PlanningSolution,
50
51 PlanningVariable {
54 #[serde(
57 default,
58 rename = "valueRangeProviderRefs",
59 skip_serializing_if = "is_empty_vec"
60 )]
61 value_range_provider_refs: Vec<String>,
62
63 #[serde(default, rename = "allowsUnassigned", skip_serializing_if = "is_false")]
65 allows_unassigned: bool,
66 },
67
68 PlanningListVariable {
71 #[serde(
74 default,
75 rename = "valueRangeProviderRefs",
76 skip_serializing_if = "is_empty_vec"
77 )]
78 value_range_provider_refs: Vec<String>,
79
80 #[serde(
82 default,
83 rename = "allowsUnassignedValues",
84 skip_serializing_if = "is_false"
85 )]
86 allows_unassigned_values: bool,
87 },
88
89 PlanningScore {
92 #[serde(
94 default,
95 rename = "bendable_hard_levels",
96 skip_serializing_if = "is_none"
97 )]
98 bendable_hard_levels: Option<i32>,
99
100 #[serde(
102 default,
103 rename = "bendable_soft_levels",
104 skip_serializing_if = "is_none"
105 )]
106 bendable_soft_levels: Option<i32>,
107 },
108
109 ValueRangeProvider {
112 #[serde(default, skip_serializing_if = "is_none")]
115 id: Option<String>,
116 },
117
118 ProblemFactProperty,
120
121 ProblemFactCollectionProperty,
123
124 PlanningEntityProperty,
126
127 PlanningEntityCollectionProperty,
129
130 PlanningPin,
132
133 InverseRelationShadowVariable {
136 #[serde(rename = "source_variable_name")]
138 source_variable_name: String,
139 },
140
141 IndexShadowVariable {
144 #[serde(rename = "source_variable_name")]
146 source_variable_name: String,
147 },
148
149 NextElementShadowVariable {
152 #[serde(rename = "source_variable_name")]
154 source_variable_name: String,
155 },
156
157 PreviousElementShadowVariable {
160 #[serde(rename = "source_variable_name")]
162 source_variable_name: String,
163 },
164
165 AnchorShadowVariable {
168 #[serde(rename = "source_variable_name")]
170 source_variable_name: String,
171 },
172
173 CascadingUpdateShadowVariable {
176 #[serde(rename = "target_method_name")]
178 target_method_name: String,
179 #[serde(skip_serializing_if = "Option::is_none")]
183 compute_expression: Option<Expression>,
184 },
185
186 PiggybackShadowVariable {
189 #[serde(rename = "shadow_variable_name")]
191 shadow_variable_name: String,
192 },
193
194 DifficultyComparator {
197 #[serde(rename = "comparator_function")]
199 comparator_function: String,
200 },
201
202 StrengthComparator {
205 #[serde(rename = "comparator_function")]
207 comparator_function: String,
208 },
209}
210
211impl PlanningAnnotation {
212 pub fn planning_id() -> Self {
216 PlanningAnnotation::PlanningId
217 }
218
219 pub fn planning_variable(value_range_provider_refs: Vec<String>) -> Self {
223 PlanningAnnotation::PlanningVariable {
224 value_range_provider_refs,
225 allows_unassigned: false,
226 }
227 }
228
229 pub fn planning_variable_unassigned(value_range_provider_refs: Vec<String>) -> Self {
231 PlanningAnnotation::PlanningVariable {
232 value_range_provider_refs,
233 allows_unassigned: true,
234 }
235 }
236
237 pub fn planning_variable_full(
239 value_range_provider_refs: Vec<String>,
240 allows_unassigned: bool,
241 ) -> Self {
242 PlanningAnnotation::PlanningVariable {
243 value_range_provider_refs,
244 allows_unassigned,
245 }
246 }
247
248 pub fn planning_list_variable(value_range_provider_refs: Vec<String>) -> Self {
252 PlanningAnnotation::PlanningListVariable {
253 value_range_provider_refs,
254 allows_unassigned_values: false,
255 }
256 }
257
258 pub fn planning_list_variable_unassigned(value_range_provider_refs: Vec<String>) -> Self {
260 PlanningAnnotation::PlanningListVariable {
261 value_range_provider_refs,
262 allows_unassigned_values: true,
263 }
264 }
265
266 pub fn planning_list_variable_full(
268 value_range_provider_refs: Vec<String>,
269 allows_unassigned_values: bool,
270 ) -> Self {
271 PlanningAnnotation::PlanningListVariable {
272 value_range_provider_refs,
273 allows_unassigned_values,
274 }
275 }
276
277 pub fn planning_score() -> Self {
281 PlanningAnnotation::PlanningScore {
282 bendable_hard_levels: None,
283 bendable_soft_levels: None,
284 }
285 }
286
287 pub fn planning_score_bendable(hard_levels: i32, soft_levels: i32) -> Self {
289 PlanningAnnotation::PlanningScore {
290 bendable_hard_levels: Some(hard_levels),
291 bendable_soft_levels: Some(soft_levels),
292 }
293 }
294
295 pub fn value_range_provider() -> Self {
299 PlanningAnnotation::ValueRangeProvider { id: None }
300 }
301
302 pub fn value_range_provider_with_id(id: impl Into<String>) -> Self {
304 PlanningAnnotation::ValueRangeProvider {
305 id: Some(id.into()),
306 }
307 }
308
309 pub fn inverse_relation_shadow(source_variable_name: impl Into<String>) -> Self {
313 PlanningAnnotation::InverseRelationShadowVariable {
314 source_variable_name: source_variable_name.into(),
315 }
316 }
317
318 pub fn index_shadow(source_variable_name: impl Into<String>) -> Self {
320 PlanningAnnotation::IndexShadowVariable {
321 source_variable_name: source_variable_name.into(),
322 }
323 }
324
325 pub fn next_element_shadow(source_variable_name: impl Into<String>) -> Self {
327 PlanningAnnotation::NextElementShadowVariable {
328 source_variable_name: source_variable_name.into(),
329 }
330 }
331
332 pub fn previous_element_shadow(source_variable_name: impl Into<String>) -> Self {
334 PlanningAnnotation::PreviousElementShadowVariable {
335 source_variable_name: source_variable_name.into(),
336 }
337 }
338
339 pub fn anchor_shadow(source_variable_name: impl Into<String>) -> Self {
341 PlanningAnnotation::AnchorShadowVariable {
342 source_variable_name: source_variable_name.into(),
343 }
344 }
345
346 pub fn cascading_update_shadow(
349 target_method_name: impl Into<String>,
350 compute_expression: Expression,
351 ) -> Self {
352 PlanningAnnotation::CascadingUpdateShadowVariable {
353 target_method_name: target_method_name.into(),
354 compute_expression: Some(compute_expression),
355 }
356 }
357
358 pub fn cascading_update_shadow_pending(target_method_name: impl Into<String>) -> Self {
363 PlanningAnnotation::CascadingUpdateShadowVariable {
364 target_method_name: target_method_name.into(),
365 compute_expression: None,
366 }
367 }
368
369 pub fn piggyback_shadow(shadow_variable_name: impl Into<String>) -> Self {
371 PlanningAnnotation::PiggybackShadowVariable {
372 shadow_variable_name: shadow_variable_name.into(),
373 }
374 }
375
376 pub fn difficulty_comparator(comparator_function: impl Into<String>) -> Self {
380 PlanningAnnotation::DifficultyComparator {
381 comparator_function: comparator_function.into(),
382 }
383 }
384
385 pub fn strength_comparator(comparator_function: impl Into<String>) -> Self {
387 PlanningAnnotation::StrengthComparator {
388 comparator_function: comparator_function.into(),
389 }
390 }
391
392 pub fn problem_fact_property() -> Self {
396 PlanningAnnotation::ProblemFactProperty
397 }
398
399 pub fn problem_fact_collection_property() -> Self {
401 PlanningAnnotation::ProblemFactCollectionProperty
402 }
403
404 pub fn planning_entity_property() -> Self {
406 PlanningAnnotation::PlanningEntityProperty
407 }
408
409 pub fn planning_entity_collection_property() -> Self {
411 PlanningAnnotation::PlanningEntityCollectionProperty
412 }
413
414 pub fn is_planning_variable(&self) -> bool {
418 matches!(self, PlanningAnnotation::PlanningVariable { .. })
419 }
420
421 pub fn is_planning_list_variable(&self) -> bool {
423 matches!(self, PlanningAnnotation::PlanningListVariable { .. })
424 }
425
426 pub fn is_any_variable(&self) -> bool {
428 self.is_planning_variable() || self.is_planning_list_variable()
429 }
430
431 pub fn is_shadow_variable(&self) -> bool {
433 matches!(
434 self,
435 PlanningAnnotation::InverseRelationShadowVariable { .. }
436 | PlanningAnnotation::IndexShadowVariable { .. }
437 | PlanningAnnotation::NextElementShadowVariable { .. }
438 | PlanningAnnotation::PreviousElementShadowVariable { .. }
439 | PlanningAnnotation::AnchorShadowVariable { .. }
440 | PlanningAnnotation::CascadingUpdateShadowVariable { .. }
441 | PlanningAnnotation::PiggybackShadowVariable { .. }
442 )
443 }
444
445 pub fn value_range_provider_refs(&self) -> Option<&Vec<String>> {
447 match self {
448 PlanningAnnotation::PlanningVariable {
449 value_range_provider_refs,
450 ..
451 } => Some(value_range_provider_refs),
452 PlanningAnnotation::PlanningListVariable {
453 value_range_provider_refs,
454 ..
455 } => Some(value_range_provider_refs),
456 _ => None,
457 }
458 }
459}
460
461#[cfg(test)]
462mod tests {
463 use super::*;
464
465 #[test]
466 fn test_planning_id() {
467 let ann = PlanningAnnotation::PlanningId;
468 assert_eq!(ann, PlanningAnnotation::PlanningId);
469 }
470
471 #[test]
472 fn test_planning_variable() {
473 let ann = PlanningAnnotation::planning_variable(vec!["rooms".to_string()]);
474 match ann {
475 PlanningAnnotation::PlanningVariable {
476 value_range_provider_refs,
477 allows_unassigned,
478 } => {
479 assert_eq!(value_range_provider_refs, vec!["rooms"]);
480 assert!(!allows_unassigned);
481 }
482 _ => panic!("Expected PlanningVariable"),
483 }
484 }
485
486 #[test]
487 fn test_planning_variable_unassigned() {
488 let ann = PlanningAnnotation::planning_variable_unassigned(vec!["rooms".to_string()]);
489 match ann {
490 PlanningAnnotation::PlanningVariable {
491 value_range_provider_refs,
492 allows_unassigned,
493 } => {
494 assert_eq!(value_range_provider_refs, vec!["rooms"]);
495 assert!(allows_unassigned);
496 }
497 _ => panic!("Expected PlanningVariable"),
498 }
499 }
500
501 #[test]
502 fn test_planning_list_variable() {
503 let ann = PlanningAnnotation::planning_list_variable(vec!["visits".to_string()]);
504 match ann {
505 PlanningAnnotation::PlanningListVariable {
506 value_range_provider_refs,
507 allows_unassigned_values,
508 } => {
509 assert_eq!(value_range_provider_refs, vec!["visits"]);
510 assert!(!allows_unassigned_values);
511 }
512 _ => panic!("Expected PlanningListVariable"),
513 }
514 }
515
516 #[test]
517 fn test_planning_list_variable_unassigned() {
518 let ann = PlanningAnnotation::planning_list_variable_unassigned(vec!["visits".to_string()]);
519 match ann {
520 PlanningAnnotation::PlanningListVariable {
521 value_range_provider_refs,
522 allows_unassigned_values,
523 } => {
524 assert_eq!(value_range_provider_refs, vec!["visits"]);
525 assert!(allows_unassigned_values);
526 }
527 _ => panic!("Expected PlanningListVariable"),
528 }
529 }
530
531 #[test]
532 fn test_planning_score() {
533 let ann = PlanningAnnotation::planning_score();
534 match ann {
535 PlanningAnnotation::PlanningScore {
536 bendable_hard_levels,
537 bendable_soft_levels,
538 } => {
539 assert!(bendable_hard_levels.is_none());
540 assert!(bendable_soft_levels.is_none());
541 }
542 _ => panic!("Expected PlanningScore"),
543 }
544 }
545
546 #[test]
547 fn test_planning_score_bendable() {
548 let ann = PlanningAnnotation::planning_score_bendable(2, 3);
549 match ann {
550 PlanningAnnotation::PlanningScore {
551 bendable_hard_levels,
552 bendable_soft_levels,
553 } => {
554 assert_eq!(bendable_hard_levels, Some(2));
555 assert_eq!(bendable_soft_levels, Some(3));
556 }
557 _ => panic!("Expected PlanningScore"),
558 }
559 }
560
561 #[test]
562 fn test_value_range_provider() {
563 let ann = PlanningAnnotation::value_range_provider();
564 match ann {
565 PlanningAnnotation::ValueRangeProvider { id } => {
566 assert!(id.is_none());
567 }
568 _ => panic!("Expected ValueRangeProvider"),
569 }
570 }
571
572 #[test]
573 fn test_value_range_provider_with_id() {
574 let ann = PlanningAnnotation::value_range_provider_with_id("rooms");
575 match ann {
576 PlanningAnnotation::ValueRangeProvider { id } => {
577 assert_eq!(id, Some("rooms".to_string()));
578 }
579 _ => panic!("Expected ValueRangeProvider"),
580 }
581 }
582
583 #[test]
584 fn test_inverse_relation_shadow() {
585 let ann = PlanningAnnotation::inverse_relation_shadow("visits");
586 match ann {
587 PlanningAnnotation::InverseRelationShadowVariable {
588 source_variable_name,
589 } => {
590 assert_eq!(source_variable_name, "visits");
591 }
592 _ => panic!("Expected InverseRelationShadowVariable"),
593 }
594 }
595
596 #[test]
597 fn test_is_planning_variable() {
598 let var = PlanningAnnotation::planning_variable(vec![]);
599 assert!(var.is_planning_variable());
600 assert!(var.is_any_variable());
601 assert!(!var.is_planning_list_variable());
602 assert!(!var.is_shadow_variable());
603 }
604
605 #[test]
606 fn test_is_planning_list_variable() {
607 let var = PlanningAnnotation::planning_list_variable(vec![]);
608 assert!(!var.is_planning_variable());
609 assert!(var.is_any_variable());
610 assert!(var.is_planning_list_variable());
611 assert!(!var.is_shadow_variable());
612 }
613
614 #[test]
615 fn test_is_shadow_variable() {
616 let shadow = PlanningAnnotation::inverse_relation_shadow("test");
617 assert!(shadow.is_shadow_variable());
618 assert!(!shadow.is_any_variable());
619 }
620
621 #[test]
622 fn test_value_range_provider_refs_getter() {
623 let var = PlanningAnnotation::planning_variable(vec!["rooms".to_string()]);
624 assert_eq!(
625 var.value_range_provider_refs(),
626 Some(&vec!["rooms".to_string()])
627 );
628
629 let list_var = PlanningAnnotation::planning_list_variable(vec!["visits".to_string()]);
630 assert_eq!(
631 list_var.value_range_provider_refs(),
632 Some(&vec!["visits".to_string()])
633 );
634
635 let score = PlanningAnnotation::planning_score();
636 assert!(score.value_range_provider_refs().is_none());
637 }
638
639 #[test]
642 fn test_json_planning_id() {
643 let ann = PlanningAnnotation::PlanningId;
644 let json = serde_json::to_string(&ann).unwrap();
645 assert_eq!(json, r#"{"annotation":"PlanningId"}"#);
646
647 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
648 assert_eq!(parsed, ann);
649 }
650
651 #[test]
652 fn test_json_planning_variable_default() {
653 let ann = PlanningAnnotation::planning_variable(vec![]);
654 let json = serde_json::to_string(&ann).unwrap();
655 assert_eq!(json, r#"{"annotation":"PlanningVariable"}"#);
657
658 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
659 assert_eq!(parsed, ann);
660 }
661
662 #[test]
663 fn test_json_planning_variable_with_refs() {
664 let ann = PlanningAnnotation::planning_variable(vec!["rooms".to_string()]);
665 let json = serde_json::to_string(&ann).unwrap();
666 assert_eq!(
667 json,
668 r#"{"annotation":"PlanningVariable","valueRangeProviderRefs":["rooms"]}"#
669 );
670
671 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
672 assert_eq!(parsed, ann);
673 }
674
675 #[test]
676 fn test_json_planning_variable_allows_unassigned() {
677 let ann = PlanningAnnotation::planning_variable_unassigned(vec![]);
678 let json = serde_json::to_string(&ann).unwrap();
679 assert_eq!(
680 json,
681 r#"{"annotation":"PlanningVariable","allowsUnassigned":true}"#
682 );
683
684 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
685 assert_eq!(parsed, ann);
686 }
687
688 #[test]
689 fn test_json_planning_variable_full() {
690 let ann = PlanningAnnotation::planning_variable_full(
691 vec!["rooms".to_string(), "timeslots".to_string()],
692 true,
693 );
694 let json = serde_json::to_string(&ann).unwrap();
695 assert!(json.contains(r#""valueRangeProviderRefs":["rooms","timeslots"]"#));
696 assert!(json.contains(r#""allowsUnassigned":true"#));
697
698 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
699 assert_eq!(parsed, ann);
700 }
701
702 #[test]
703 fn test_json_planning_list_variable_default() {
704 let ann = PlanningAnnotation::planning_list_variable(vec![]);
705 let json = serde_json::to_string(&ann).unwrap();
706 assert_eq!(json, r#"{"annotation":"PlanningListVariable"}"#);
707
708 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
709 assert_eq!(parsed, ann);
710 }
711
712 #[test]
713 fn test_json_planning_list_variable_with_refs() {
714 let ann = PlanningAnnotation::planning_list_variable(vec!["visits".to_string()]);
715 let json = serde_json::to_string(&ann).unwrap();
716 assert_eq!(
717 json,
718 r#"{"annotation":"PlanningListVariable","valueRangeProviderRefs":["visits"]}"#
719 );
720
721 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
722 assert_eq!(parsed, ann);
723 }
724
725 #[test]
726 fn test_json_planning_list_variable_allows_unassigned() {
727 let ann = PlanningAnnotation::planning_list_variable_unassigned(vec!["visits".to_string()]);
728 let json = serde_json::to_string(&ann).unwrap();
729 assert!(json.contains(r#""valueRangeProviderRefs":["visits"]"#));
730 assert!(json.contains(r#""allowsUnassignedValues":true"#));
731
732 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
733 assert_eq!(parsed, ann);
734 }
735
736 #[test]
737 fn test_json_planning_score() {
738 let ann = PlanningAnnotation::PlanningScore {
739 bendable_hard_levels: None,
740 bendable_soft_levels: None,
741 };
742 let json = serde_json::to_string(&ann).unwrap();
743 assert_eq!(json, r#"{"annotation":"PlanningScore"}"#);
744
745 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
746 assert_eq!(parsed, ann);
747 }
748
749 #[test]
750 fn test_json_planning_score_bendable() {
751 let ann = PlanningAnnotation::planning_score_bendable(2, 3);
752 let json = serde_json::to_string(&ann).unwrap();
753 assert!(json.contains(r#""bendable_hard_levels":2"#));
754 assert!(json.contains(r#""bendable_soft_levels":3"#));
755
756 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
757 assert_eq!(parsed, ann);
758 }
759
760 #[test]
761 fn test_json_value_range_provider() {
762 let ann = PlanningAnnotation::ValueRangeProvider { id: None };
763 let json = serde_json::to_string(&ann).unwrap();
764 assert_eq!(json, r#"{"annotation":"ValueRangeProvider"}"#);
765
766 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
767 assert_eq!(parsed, ann);
768 }
769
770 #[test]
771 fn test_json_value_range_provider_with_id() {
772 let ann = PlanningAnnotation::value_range_provider_with_id("rooms");
773 let json = serde_json::to_string(&ann).unwrap();
774 assert_eq!(json, r#"{"annotation":"ValueRangeProvider","id":"rooms"}"#);
775
776 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
777 assert_eq!(parsed, ann);
778 }
779
780 #[test]
781 fn test_json_inverse_relation_shadow() {
782 let ann = PlanningAnnotation::inverse_relation_shadow("visits");
783 let json = serde_json::to_string(&ann).unwrap();
784 assert_eq!(
785 json,
786 r#"{"annotation":"InverseRelationShadowVariable","source_variable_name":"visits"}"#
787 );
788
789 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
790 assert_eq!(parsed, ann);
791 }
792
793 #[test]
794 fn test_json_simple_annotations() {
795 let annotations = vec![
796 (
797 PlanningAnnotation::PlanningEntity,
798 r#"{"annotation":"PlanningEntity"}"#,
799 ),
800 (
801 PlanningAnnotation::PlanningSolution,
802 r#"{"annotation":"PlanningSolution"}"#,
803 ),
804 (
805 PlanningAnnotation::ProblemFactProperty,
806 r#"{"annotation":"ProblemFactProperty"}"#,
807 ),
808 (
809 PlanningAnnotation::ProblemFactCollectionProperty,
810 r#"{"annotation":"ProblemFactCollectionProperty"}"#,
811 ),
812 (
813 PlanningAnnotation::PlanningEntityProperty,
814 r#"{"annotation":"PlanningEntityProperty"}"#,
815 ),
816 (
817 PlanningAnnotation::PlanningEntityCollectionProperty,
818 r#"{"annotation":"PlanningEntityCollectionProperty"}"#,
819 ),
820 (
821 PlanningAnnotation::PlanningPin,
822 r#"{"annotation":"PlanningPin"}"#,
823 ),
824 ];
825
826 for (ann, expected_json) in annotations {
827 let json = serde_json::to_string(&ann).unwrap();
828 assert_eq!(json, expected_json);
829
830 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
831 assert_eq!(parsed, ann);
832 }
833 }
834
835 #[test]
836 fn test_json_deserialization_defaults() {
837 let json = r#"{"annotation":"PlanningVariable"}"#;
839 let parsed: PlanningAnnotation = serde_json::from_str(json).unwrap();
840 match parsed {
841 PlanningAnnotation::PlanningVariable {
842 value_range_provider_refs,
843 allows_unassigned,
844 } => {
845 assert!(value_range_provider_refs.is_empty());
846 assert!(!allows_unassigned);
847 }
848 _ => panic!("Expected PlanningVariable"),
849 }
850 }
851
852 #[test]
853 fn test_json_deserialization_with_refs() {
854 let json = r#"{"annotation":"PlanningVariable","valueRangeProviderRefs":["a","b"]}"#;
855 let parsed: PlanningAnnotation = serde_json::from_str(json).unwrap();
856 match parsed {
857 PlanningAnnotation::PlanningVariable {
858 value_range_provider_refs,
859 allows_unassigned,
860 } => {
861 assert_eq!(
862 value_range_provider_refs,
863 vec!["a".to_string(), "b".to_string()]
864 );
865 assert!(!allows_unassigned);
866 }
867 _ => panic!("Expected PlanningVariable"),
868 }
869 }
870
871 #[test]
874 fn test_index_shadow() {
875 let ann = PlanningAnnotation::index_shadow("visits");
876 match &ann {
877 PlanningAnnotation::IndexShadowVariable {
878 source_variable_name,
879 } => {
880 assert_eq!(source_variable_name, "visits");
881 }
882 _ => panic!("Expected IndexShadowVariable"),
883 }
884 assert!(ann.is_shadow_variable());
885 }
886
887 #[test]
888 fn test_next_element_shadow() {
889 let ann = PlanningAnnotation::next_element_shadow("visits");
890 match &ann {
891 PlanningAnnotation::NextElementShadowVariable {
892 source_variable_name,
893 } => {
894 assert_eq!(source_variable_name, "visits");
895 }
896 _ => panic!("Expected NextElementShadowVariable"),
897 }
898 assert!(ann.is_shadow_variable());
899 }
900
901 #[test]
902 fn test_previous_element_shadow() {
903 let ann = PlanningAnnotation::previous_element_shadow("visits");
904 match &ann {
905 PlanningAnnotation::PreviousElementShadowVariable {
906 source_variable_name,
907 } => {
908 assert_eq!(source_variable_name, "visits");
909 }
910 _ => panic!("Expected PreviousElementShadowVariable"),
911 }
912 assert!(ann.is_shadow_variable());
913 }
914
915 #[test]
916 fn test_anchor_shadow() {
917 let ann = PlanningAnnotation::anchor_shadow("chain");
918 match &ann {
919 PlanningAnnotation::AnchorShadowVariable {
920 source_variable_name,
921 } => {
922 assert_eq!(source_variable_name, "chain");
923 }
924 _ => panic!("Expected AnchorShadowVariable"),
925 }
926 assert!(ann.is_shadow_variable());
927 }
928
929 #[test]
930 fn test_cascading_update_shadow() {
931 use crate::wasm::Expression;
932 let expr = Expression::Int64Literal { value: 0 };
933 let ann = PlanningAnnotation::cascading_update_shadow("updateArrivalTime", expr);
934 match &ann {
935 PlanningAnnotation::CascadingUpdateShadowVariable {
936 target_method_name,
937 compute_expression: _,
938 } => {
939 assert_eq!(target_method_name, "updateArrivalTime");
940 }
941 _ => panic!("Expected CascadingUpdateShadowVariable"),
942 }
943 assert!(ann.is_shadow_variable());
944 }
945
946 #[test]
947 fn test_piggyback_shadow() {
948 let ann = PlanningAnnotation::piggyback_shadow("arrivalTime");
949 match &ann {
950 PlanningAnnotation::PiggybackShadowVariable {
951 shadow_variable_name,
952 } => {
953 assert_eq!(shadow_variable_name, "arrivalTime");
954 }
955 _ => panic!("Expected PiggybackShadowVariable"),
956 }
957 assert!(ann.is_shadow_variable());
958 }
959
960 #[test]
961 fn test_json_index_shadow() {
962 let ann = PlanningAnnotation::index_shadow("visits");
963 let json = serde_json::to_string(&ann).unwrap();
964 assert_eq!(
965 json,
966 r#"{"annotation":"IndexShadowVariable","source_variable_name":"visits"}"#
967 );
968 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
969 assert_eq!(parsed, ann);
970 }
971
972 #[test]
973 fn test_json_next_element_shadow() {
974 let ann = PlanningAnnotation::next_element_shadow("visits");
975 let json = serde_json::to_string(&ann).unwrap();
976 assert_eq!(
977 json,
978 r#"{"annotation":"NextElementShadowVariable","source_variable_name":"visits"}"#
979 );
980 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
981 assert_eq!(parsed, ann);
982 }
983
984 #[test]
985 fn test_json_previous_element_shadow() {
986 let ann = PlanningAnnotation::previous_element_shadow("visits");
987 let json = serde_json::to_string(&ann).unwrap();
988 assert_eq!(
989 json,
990 r#"{"annotation":"PreviousElementShadowVariable","source_variable_name":"visits"}"#
991 );
992 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
993 assert_eq!(parsed, ann);
994 }
995
996 #[test]
997 fn test_json_anchor_shadow() {
998 let ann = PlanningAnnotation::anchor_shadow("chain");
999 let json = serde_json::to_string(&ann).unwrap();
1000 assert_eq!(
1001 json,
1002 r#"{"annotation":"AnchorShadowVariable","source_variable_name":"chain"}"#
1003 );
1004 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
1005 assert_eq!(parsed, ann);
1006 }
1007
1008 #[test]
1009 fn test_json_cascading_update_shadow() {
1010 use crate::wasm::Expression;
1011 let expr = Expression::Int64Literal { value: 42 };
1012 let ann = PlanningAnnotation::cascading_update_shadow("updateArrivalTime", expr);
1013 let json = serde_json::to_string(&ann).unwrap();
1014 assert!(json.contains(r#""annotation":"CascadingUpdateShadowVariable""#));
1016 assert!(json.contains(r#""target_method_name":"updateArrivalTime""#));
1017 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
1018 assert_eq!(parsed, ann);
1019 }
1020
1021 #[test]
1022 fn test_json_piggyback_shadow() {
1023 let ann = PlanningAnnotation::piggyback_shadow("arrivalTime");
1024 let json = serde_json::to_string(&ann).unwrap();
1025 assert_eq!(
1026 json,
1027 r#"{"annotation":"PiggybackShadowVariable","shadow_variable_name":"arrivalTime"}"#
1028 );
1029 let parsed: PlanningAnnotation = serde_json::from_str(&json).unwrap();
1030 assert_eq!(parsed, ann);
1031 }
1032
1033 #[test]
1034 fn test_all_shadow_variables_are_shadows() {
1035 use crate::wasm::Expression;
1036 let shadows = vec![
1037 PlanningAnnotation::inverse_relation_shadow("test"),
1038 PlanningAnnotation::index_shadow("test"),
1039 PlanningAnnotation::next_element_shadow("test"),
1040 PlanningAnnotation::previous_element_shadow("test"),
1041 PlanningAnnotation::anchor_shadow("test"),
1042 PlanningAnnotation::cascading_update_shadow(
1043 "test",
1044 Expression::Int64Literal { value: 0 },
1045 ),
1046 PlanningAnnotation::piggyback_shadow("test"),
1047 ];
1048 for shadow in shadows {
1049 assert!(shadow.is_shadow_variable(), "{:?} should be shadow", shadow);
1050 assert!(
1051 !shadow.is_any_variable(),
1052 "{:?} should not be any_variable",
1053 shadow
1054 );
1055 }
1056 }
1057}