exonware-xwnode 0.0.1.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. exonware/__init__.py +14 -0
  2. exonware/xwnode/__init__.py +127 -0
  3. exonware/xwnode/base.py +676 -0
  4. exonware/xwnode/config.py +178 -0
  5. exonware/xwnode/contracts.py +730 -0
  6. exonware/xwnode/errors.py +503 -0
  7. exonware/xwnode/facade.py +460 -0
  8. exonware/xwnode/strategies/__init__.py +158 -0
  9. exonware/xwnode/strategies/advisor.py +463 -0
  10. exonware/xwnode/strategies/edges/__init__.py +32 -0
  11. exonware/xwnode/strategies/edges/adj_list.py +227 -0
  12. exonware/xwnode/strategies/edges/adj_matrix.py +391 -0
  13. exonware/xwnode/strategies/edges/base.py +169 -0
  14. exonware/xwnode/strategies/flyweight.py +328 -0
  15. exonware/xwnode/strategies/impls/__init__.py +13 -0
  16. exonware/xwnode/strategies/impls/_base_edge.py +403 -0
  17. exonware/xwnode/strategies/impls/_base_node.py +307 -0
  18. exonware/xwnode/strategies/impls/edge_adj_list.py +353 -0
  19. exonware/xwnode/strategies/impls/edge_adj_matrix.py +445 -0
  20. exonware/xwnode/strategies/impls/edge_bidir_wrapper.py +455 -0
  21. exonware/xwnode/strategies/impls/edge_block_adj_matrix.py +539 -0
  22. exonware/xwnode/strategies/impls/edge_coo.py +533 -0
  23. exonware/xwnode/strategies/impls/edge_csc.py +447 -0
  24. exonware/xwnode/strategies/impls/edge_csr.py +492 -0
  25. exonware/xwnode/strategies/impls/edge_dynamic_adj_list.py +503 -0
  26. exonware/xwnode/strategies/impls/edge_flow_network.py +555 -0
  27. exonware/xwnode/strategies/impls/edge_hyperedge_set.py +516 -0
  28. exonware/xwnode/strategies/impls/edge_neural_graph.py +650 -0
  29. exonware/xwnode/strategies/impls/edge_octree.py +574 -0
  30. exonware/xwnode/strategies/impls/edge_property_store.py +655 -0
  31. exonware/xwnode/strategies/impls/edge_quadtree.py +519 -0
  32. exonware/xwnode/strategies/impls/edge_rtree.py +820 -0
  33. exonware/xwnode/strategies/impls/edge_temporal_edgeset.py +558 -0
  34. exonware/xwnode/strategies/impls/edge_tree_graph_basic.py +271 -0
  35. exonware/xwnode/strategies/impls/edge_weighted_graph.py +411 -0
  36. exonware/xwnode/strategies/manager.py +775 -0
  37. exonware/xwnode/strategies/metrics.py +538 -0
  38. exonware/xwnode/strategies/migration.py +432 -0
  39. exonware/xwnode/strategies/nodes/__init__.py +50 -0
  40. exonware/xwnode/strategies/nodes/_base_node.py +307 -0
  41. exonware/xwnode/strategies/nodes/adjacency_list.py +267 -0
  42. exonware/xwnode/strategies/nodes/aho_corasick.py +345 -0
  43. exonware/xwnode/strategies/nodes/array_list.py +209 -0
  44. exonware/xwnode/strategies/nodes/base.py +247 -0
  45. exonware/xwnode/strategies/nodes/deque.py +200 -0
  46. exonware/xwnode/strategies/nodes/hash_map.py +135 -0
  47. exonware/xwnode/strategies/nodes/heap.py +307 -0
  48. exonware/xwnode/strategies/nodes/linked_list.py +232 -0
  49. exonware/xwnode/strategies/nodes/node_aho_corasick.py +520 -0
  50. exonware/xwnode/strategies/nodes/node_array_list.py +175 -0
  51. exonware/xwnode/strategies/nodes/node_avl_tree.py +371 -0
  52. exonware/xwnode/strategies/nodes/node_b_plus_tree.py +542 -0
  53. exonware/xwnode/strategies/nodes/node_bitmap.py +420 -0
  54. exonware/xwnode/strategies/nodes/node_bitset_dynamic.py +513 -0
  55. exonware/xwnode/strategies/nodes/node_bloom_filter.py +347 -0
  56. exonware/xwnode/strategies/nodes/node_btree.py +357 -0
  57. exonware/xwnode/strategies/nodes/node_count_min_sketch.py +470 -0
  58. exonware/xwnode/strategies/nodes/node_cow_tree.py +473 -0
  59. exonware/xwnode/strategies/nodes/node_cuckoo_hash.py +392 -0
  60. exonware/xwnode/strategies/nodes/node_fenwick_tree.py +301 -0
  61. exonware/xwnode/strategies/nodes/node_hash_map.py +269 -0
  62. exonware/xwnode/strategies/nodes/node_heap.py +191 -0
  63. exonware/xwnode/strategies/nodes/node_hyperloglog.py +407 -0
  64. exonware/xwnode/strategies/nodes/node_linked_list.py +409 -0
  65. exonware/xwnode/strategies/nodes/node_lsm_tree.py +400 -0
  66. exonware/xwnode/strategies/nodes/node_ordered_map.py +390 -0
  67. exonware/xwnode/strategies/nodes/node_ordered_map_balanced.py +565 -0
  68. exonware/xwnode/strategies/nodes/node_patricia.py +512 -0
  69. exonware/xwnode/strategies/nodes/node_persistent_tree.py +378 -0
  70. exonware/xwnode/strategies/nodes/node_radix_trie.py +452 -0
  71. exonware/xwnode/strategies/nodes/node_red_black_tree.py +497 -0
  72. exonware/xwnode/strategies/nodes/node_roaring_bitmap.py +570 -0
  73. exonware/xwnode/strategies/nodes/node_segment_tree.py +289 -0
  74. exonware/xwnode/strategies/nodes/node_set_hash.py +354 -0
  75. exonware/xwnode/strategies/nodes/node_set_tree.py +480 -0
  76. exonware/xwnode/strategies/nodes/node_skip_list.py +316 -0
  77. exonware/xwnode/strategies/nodes/node_splay_tree.py +393 -0
  78. exonware/xwnode/strategies/nodes/node_suffix_array.py +487 -0
  79. exonware/xwnode/strategies/nodes/node_treap.py +387 -0
  80. exonware/xwnode/strategies/nodes/node_tree_graph_hybrid.py +1434 -0
  81. exonware/xwnode/strategies/nodes/node_trie.py +252 -0
  82. exonware/xwnode/strategies/nodes/node_union_find.py +187 -0
  83. exonware/xwnode/strategies/nodes/node_xdata_optimized.py +369 -0
  84. exonware/xwnode/strategies/nodes/priority_queue.py +209 -0
  85. exonware/xwnode/strategies/nodes/queue.py +161 -0
  86. exonware/xwnode/strategies/nodes/sparse_matrix.py +206 -0
  87. exonware/xwnode/strategies/nodes/stack.py +152 -0
  88. exonware/xwnode/strategies/nodes/trie.py +274 -0
  89. exonware/xwnode/strategies/nodes/union_find.py +283 -0
  90. exonware/xwnode/strategies/pattern_detector.py +603 -0
  91. exonware/xwnode/strategies/performance_monitor.py +487 -0
  92. exonware/xwnode/strategies/queries/__init__.py +24 -0
  93. exonware/xwnode/strategies/queries/base.py +236 -0
  94. exonware/xwnode/strategies/queries/cql.py +201 -0
  95. exonware/xwnode/strategies/queries/cypher.py +181 -0
  96. exonware/xwnode/strategies/queries/datalog.py +70 -0
  97. exonware/xwnode/strategies/queries/elastic_dsl.py +70 -0
  98. exonware/xwnode/strategies/queries/eql.py +70 -0
  99. exonware/xwnode/strategies/queries/flux.py +70 -0
  100. exonware/xwnode/strategies/queries/gql.py +70 -0
  101. exonware/xwnode/strategies/queries/graphql.py +240 -0
  102. exonware/xwnode/strategies/queries/gremlin.py +181 -0
  103. exonware/xwnode/strategies/queries/hiveql.py +214 -0
  104. exonware/xwnode/strategies/queries/hql.py +70 -0
  105. exonware/xwnode/strategies/queries/jmespath.py +219 -0
  106. exonware/xwnode/strategies/queries/jq.py +66 -0
  107. exonware/xwnode/strategies/queries/json_query.py +66 -0
  108. exonware/xwnode/strategies/queries/jsoniq.py +248 -0
  109. exonware/xwnode/strategies/queries/kql.py +70 -0
  110. exonware/xwnode/strategies/queries/linq.py +238 -0
  111. exonware/xwnode/strategies/queries/logql.py +70 -0
  112. exonware/xwnode/strategies/queries/mql.py +68 -0
  113. exonware/xwnode/strategies/queries/n1ql.py +210 -0
  114. exonware/xwnode/strategies/queries/partiql.py +70 -0
  115. exonware/xwnode/strategies/queries/pig.py +215 -0
  116. exonware/xwnode/strategies/queries/promql.py +70 -0
  117. exonware/xwnode/strategies/queries/sparql.py +220 -0
  118. exonware/xwnode/strategies/queries/sql.py +275 -0
  119. exonware/xwnode/strategies/queries/xml_query.py +66 -0
  120. exonware/xwnode/strategies/queries/xpath.py +223 -0
  121. exonware/xwnode/strategies/queries/xquery.py +258 -0
  122. exonware/xwnode/strategies/queries/xwnode_executor.py +332 -0
  123. exonware/xwnode/strategies/queries/xwquery_strategy.py +424 -0
  124. exonware/xwnode/strategies/registry.py +604 -0
  125. exonware/xwnode/strategies/simple.py +273 -0
  126. exonware/xwnode/strategies/utils.py +532 -0
  127. exonware/xwnode/types.py +912 -0
  128. exonware/xwnode/version.py +78 -0
  129. exonware_xwnode-0.0.1.12.dist-info/METADATA +169 -0
  130. exonware_xwnode-0.0.1.12.dist-info/RECORD +132 -0
  131. exonware_xwnode-0.0.1.12.dist-info/WHEEL +4 -0
  132. exonware_xwnode-0.0.1.12.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,432 @@
1
+ """
2
+ Strategy Migration System
3
+
4
+ This module implements seamless migration between different node and edge
5
+ strategies while preserving data integrity.
6
+ """
7
+
8
+ from typing import Any, Dict, List, Optional, Set, Tuple, Type
9
+ from enum import Enum
10
+ import threading
11
+ import time
12
+ from ..types import NodeMode, EdgeMode, NodeTrait, EdgeTrait
13
+ from .registry import get_registry
14
+ from ..errors import XWNodeStrategyError, XWNodeError
15
+ import logging
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class MigrationPlan:
21
+ """Represents a strategy migration plan with validation and cost estimation."""
22
+
23
+ def __init__(self, source_mode: Any, target_mode: Any, strategy_type: str):
24
+ self.source_mode = source_mode
25
+ self.target_mode = target_mode
26
+ self.strategy_type = strategy_type # 'node' or 'edge'
27
+ self.cost_estimate = 0
28
+ self.data_loss_risk = 'none' # 'none', 'low', 'medium', 'high'
29
+ self.warnings: List[str] = []
30
+ self.required_operations: List[str] = []
31
+ self.estimated_time_ms = 0
32
+
33
+ def add_warning(self, warning: str) -> None:
34
+ """Add a migration warning."""
35
+ self.warnings.append(warning)
36
+
37
+ def add_operation(self, operation: str) -> None:
38
+ """Add a required migration operation."""
39
+ self.required_operations.append(operation)
40
+
41
+ def is_safe(self) -> bool:
42
+ """Check if migration is considered safe."""
43
+ return self.data_loss_risk in ['none', 'low'] and len(self.warnings) <= 2
44
+
45
+
46
+ class xStrategyMigrator:
47
+ """
48
+ Handles migration between different node and edge strategies.
49
+
50
+ Provides safe, efficient migration with rollback capabilities
51
+ and data integrity guarantees.
52
+ """
53
+
54
+ def __init__(self):
55
+ self._registry = get_registry()
56
+ self._migration_lock = threading.RLock()
57
+ self._migration_history: List[Dict[str, Any]] = []
58
+
59
+ # ============================================================================
60
+ # MIGRATION PLANNING
61
+ # ============================================================================
62
+
63
+ def plan_node_migration(self, source_mode: NodeMode, target_mode: NodeMode,
64
+ source_traits: NodeTrait = NodeTrait.NONE,
65
+ target_traits: NodeTrait = NodeTrait.NONE,
66
+ data_size: int = 0) -> MigrationPlan:
67
+ """Plan a migration between node strategies."""
68
+ plan = MigrationPlan(source_mode, target_mode, 'node')
69
+
70
+ # Basic validation
71
+ if source_mode == target_mode and source_traits == target_traits:
72
+ plan.add_warning("Source and target are identical")
73
+ return plan
74
+
75
+ # Check strategy availability
76
+ if not self._registry.has_node_strategy(target_mode):
77
+ raise XWNodeStrategyError(f"Target node strategy {target_mode.name} not available")
78
+
79
+ # Analyze compatibility
80
+ self._analyze_node_compatibility(plan, source_mode, target_mode,
81
+ source_traits, target_traits, data_size)
82
+
83
+ return plan
84
+
85
+ def plan_edge_migration(self, source_mode: EdgeMode, target_mode: EdgeMode,
86
+ source_traits: EdgeTrait = EdgeTrait.NONE,
87
+ target_traits: EdgeTrait = EdgeTrait.NONE,
88
+ edge_count: int = 0, vertex_count: int = 0) -> MigrationPlan:
89
+ """Plan a migration between edge strategies."""
90
+ plan = MigrationPlan(source_mode, target_mode, 'edge')
91
+
92
+ # Basic validation
93
+ if source_mode == target_mode and source_traits == target_traits:
94
+ plan.add_warning("Source and target are identical")
95
+ return plan
96
+
97
+ # Check strategy availability
98
+ if not self._registry.has_edge_strategy(target_mode):
99
+ raise XWNodeStrategyError(f"Target edge strategy {target_mode.name} not available")
100
+
101
+ # Analyze compatibility
102
+ self._analyze_edge_compatibility(plan, source_mode, target_mode,
103
+ source_traits, target_traits, edge_count, vertex_count)
104
+
105
+ return plan
106
+
107
+ def _analyze_node_compatibility(self, plan: MigrationPlan, source: NodeMode, target: NodeMode,
108
+ source_traits: NodeTrait, target_traits: NodeTrait,
109
+ data_size: int) -> None:
110
+ """Analyze compatibility between node strategies."""
111
+ # Define migration rules and costs
112
+ migration_matrix = {
113
+ # From LEGACY
114
+ (NodeMode.LEGACY, NodeMode.HASH_MAP): {'cost': 1, 'risk': 'none', 'ops': ['copy_dict']},
115
+ (NodeMode.LEGACY, NodeMode.ARRAY_LIST): {'cost': 1, 'risk': 'low', 'ops': ['copy_list']},
116
+ (NodeMode.LEGACY, NodeMode.TRIE): {'cost': 2, 'risk': 'low', 'ops': ['copy_dict', 'build_trie']},
117
+ (NodeMode.LEGACY, NodeMode.HEAP): {'cost': 3, 'risk': 'medium', 'ops': ['extract_values', 'heapify']},
118
+ (NodeMode.LEGACY, NodeMode.B_TREE): {'cost': 3, 'risk': 'low', 'ops': ['sort_keys', 'build_btree']},
119
+
120
+ # From HASH_MAP
121
+ (NodeMode.HASH_MAP, NodeMode.LEGACY): {'cost': 1, 'risk': 'none', 'ops': ['copy_dict']},
122
+ (NodeMode.HASH_MAP, NodeMode.ARRAY_LIST): {'cost': 2, 'risk': 'high', 'ops': ['convert_dict_to_list']},
123
+ (NodeMode.HASH_MAP, NodeMode.TRIE): {'cost': 2, 'risk': 'low', 'ops': ['rebuild_trie']},
124
+ (NodeMode.HASH_MAP, NodeMode.B_TREE): {'cost': 2, 'risk': 'low', 'ops': ['sort_rebuild']},
125
+
126
+ # From ARRAY_LIST
127
+ (NodeMode.ARRAY_LIST, NodeMode.LEGACY): {'cost': 1, 'risk': 'none', 'ops': ['copy_list']},
128
+ (NodeMode.ARRAY_LIST, NodeMode.HASH_MAP): {'cost': 1, 'risk': 'low', 'ops': ['index_as_keys']},
129
+ (NodeMode.ARRAY_LIST, NodeMode.HEAP): {'cost': 2, 'risk': 'low', 'ops': ['heapify_list']},
130
+
131
+ # Specialized migrations
132
+ (NodeMode.HEAP, NodeMode.ARRAY_LIST): {'cost': 2, 'risk': 'medium', 'ops': ['heap_sort', 'to_list']},
133
+ (NodeMode.B_TREE, NodeMode.HASH_MAP): {'cost': 2, 'risk': 'low', 'ops': ['flatten_tree']},
134
+ (NodeMode.TRIE, NodeMode.HASH_MAP): {'cost': 2, 'risk': 'low', 'ops': ['flatten_trie']},
135
+ }
136
+
137
+ migration_key = (source, target)
138
+ if migration_key in migration_matrix:
139
+ rules = migration_matrix[migration_key]
140
+ plan.cost_estimate = rules['cost']
141
+ plan.data_loss_risk = rules['risk']
142
+ for op in rules['ops']:
143
+ plan.add_operation(op)
144
+ else:
145
+ # Default fallback through LEGACY
146
+ plan.cost_estimate = 4
147
+ plan.data_loss_risk = 'medium'
148
+ plan.add_operation('migrate_via_legacy')
149
+ plan.add_warning(f"No direct migration path from {source.name} to {target.name}")
150
+
151
+ # Adjust based on data size
152
+ if data_size > 10000:
153
+ plan.cost_estimate += 2
154
+ plan.estimated_time_ms = data_size * 0.1
155
+ elif data_size > 1000:
156
+ plan.cost_estimate += 1
157
+ plan.estimated_time_ms = data_size * 0.05
158
+ else:
159
+ plan.estimated_time_ms = max(10, data_size * 0.01)
160
+
161
+ # Trait compatibility warnings
162
+ self._check_trait_compatibility(plan, source_traits, target_traits, 'node')
163
+
164
+ def _analyze_edge_compatibility(self, plan: MigrationPlan, source: EdgeMode, target: EdgeMode,
165
+ source_traits: EdgeTrait, target_traits: EdgeTrait,
166
+ edge_count: int, vertex_count: int) -> None:
167
+ """Analyze compatibility between edge strategies."""
168
+ # Define edge migration rules
169
+ migration_matrix = {
170
+ # From LEGACY
171
+ (EdgeMode.LEGACY, EdgeMode.ADJ_LIST): {'cost': 2, 'risk': 'low', 'ops': ['extract_edges', 'build_adj_list']},
172
+ (EdgeMode.LEGACY, EdgeMode.ADJ_MATRIX): {'cost': 3, 'risk': 'medium', 'ops': ['extract_edges', 'build_matrix']},
173
+ (EdgeMode.LEGACY, EdgeMode.CSR): {'cost': 3, 'risk': 'low', 'ops': ['extract_edges', 'build_csr']},
174
+
175
+ # Between modern formats
176
+ (EdgeMode.ADJ_LIST, EdgeMode.ADJ_MATRIX): {'cost': 2, 'risk': 'low', 'ops': ['list_to_matrix']},
177
+ (EdgeMode.ADJ_LIST, EdgeMode.CSR): {'cost': 2, 'risk': 'low', 'ops': ['list_to_csr']},
178
+ (EdgeMode.ADJ_MATRIX, EdgeMode.ADJ_LIST): {'cost': 2, 'risk': 'low', 'ops': ['matrix_to_list']},
179
+ (EdgeMode.ADJ_MATRIX, EdgeMode.CSR): {'cost': 2, 'risk': 'low', 'ops': ['matrix_to_csr']},
180
+ (EdgeMode.CSR, EdgeMode.ADJ_LIST): {'cost': 2, 'risk': 'low', 'ops': ['csr_to_list']},
181
+ (EdgeMode.CSR, EdgeMode.ADJ_MATRIX): {'cost': 3, 'risk': 'medium', 'ops': ['csr_to_matrix']},
182
+ }
183
+
184
+ migration_key = (source, target)
185
+ if migration_key in migration_matrix:
186
+ rules = migration_matrix[migration_key]
187
+ plan.cost_estimate = rules['cost']
188
+ plan.data_loss_risk = rules['risk']
189
+ for op in rules['ops']:
190
+ plan.add_operation(op)
191
+ else:
192
+ # Default fallback
193
+ plan.cost_estimate = 5
194
+ plan.data_loss_risk = 'high'
195
+ plan.add_operation('migrate_via_legacy')
196
+ plan.add_warning(f"No direct migration path from {source.name} to {target.name}")
197
+
198
+ # Graph density considerations
199
+ density = edge_count / max(1, vertex_count * (vertex_count - 1)) if vertex_count > 1 else 0
200
+
201
+ if target == EdgeMode.ADJ_MATRIX and density < 0.1:
202
+ plan.add_warning("Migrating sparse graph to dense matrix representation")
203
+ plan.cost_estimate += 1
204
+ elif target in [EdgeMode.ADJ_LIST, EdgeMode.CSR] and density > 0.7:
205
+ plan.add_warning("Migrating dense graph to sparse representation")
206
+
207
+ # Size-based adjustments
208
+ if edge_count > 100000:
209
+ plan.cost_estimate += 3
210
+ plan.estimated_time_ms = edge_count * 0.2
211
+ elif edge_count > 10000:
212
+ plan.cost_estimate += 2
213
+ plan.estimated_time_ms = edge_count * 0.1
214
+ else:
215
+ plan.estimated_time_ms = max(10, edge_count * 0.05)
216
+
217
+ # Trait compatibility
218
+ self._check_trait_compatibility(plan, source_traits, target_traits, 'edge')
219
+
220
+ def _check_trait_compatibility(self, plan: MigrationPlan, source_traits: Any,
221
+ target_traits: Any, strategy_type: str) -> None:
222
+ """Check trait compatibility and add warnings."""
223
+ if source_traits == target_traits:
224
+ return
225
+
226
+ # Check for trait loss
227
+ lost_traits = source_traits & ~target_traits if source_traits else None
228
+ if lost_traits and lost_traits != 0:
229
+ plan.add_warning(f"Some {strategy_type} traits will be lost: {lost_traits}")
230
+ if plan.data_loss_risk == 'none':
231
+ plan.data_loss_risk = 'low'
232
+
233
+ # Check for new traits
234
+ new_traits = target_traits & ~source_traits if target_traits else None
235
+ if new_traits and new_traits != 0:
236
+ plan.add_operation(f"configure_{strategy_type}_traits")
237
+
238
+ # ============================================================================
239
+ # MIGRATION EXECUTION
240
+ # ============================================================================
241
+
242
+ def execute_node_migration(self, source_strategy: Any, target_mode: NodeMode,
243
+ target_traits: NodeTrait = NodeTrait.NONE,
244
+ **options) -> Any:
245
+ """Execute migration from source node strategy to target."""
246
+ with self._migration_lock:
247
+ start_time = time.time()
248
+
249
+ # Extract data from source
250
+ source_data = source_strategy.to_native()
251
+ source_size = len(source_strategy) if hasattr(source_strategy, '__len__') else 0
252
+
253
+ # Create migration plan
254
+ source_mode = getattr(source_strategy, '_mode', NodeMode.LEGACY)
255
+ plan = self.plan_node_migration(source_mode, target_mode,
256
+ getattr(source_strategy, '_traits', NodeTrait.NONE),
257
+ target_traits, source_size)
258
+
259
+ logger.info(f"🔄 Executing node migration: {source_mode.name} → {target_mode.name}")
260
+ logger.info(f"📋 Operations: {', '.join(plan.required_operations)}")
261
+
262
+ # Create target strategy
263
+ target_strategy = self._registry.get_node_strategy(target_mode, traits=target_traits, **options)
264
+
265
+ # Migrate data based on type
266
+ try:
267
+ if isinstance(source_data, dict):
268
+ for key, value in source_data.items():
269
+ target_strategy.put(key, value)
270
+ elif isinstance(source_data, list):
271
+ for i, value in enumerate(source_data):
272
+ target_strategy.put(str(i), value)
273
+ else:
274
+ # Leaf node
275
+ target_strategy.put('value', source_data)
276
+
277
+ # Record migration
278
+ migration_record = {
279
+ 'timestamp': time.time(),
280
+ 'type': 'node',
281
+ 'source_mode': source_mode.name,
282
+ 'target_mode': target_mode.name,
283
+ 'data_size': source_size,
284
+ 'duration_ms': (time.time() - start_time) * 1000,
285
+ 'success': True
286
+ }
287
+ self._migration_history.append(migration_record)
288
+
289
+ logger.info(f"✅ Node migration completed in {migration_record['duration_ms']:.1f}ms")
290
+ return target_strategy
291
+
292
+ except Exception as e:
293
+ logger.error(f"❌ Node migration failed: {e}")
294
+ migration_record = {
295
+ 'timestamp': time.time(),
296
+ 'type': 'node',
297
+ 'source_mode': source_mode.name,
298
+ 'target_mode': target_mode.name,
299
+ 'data_size': source_size,
300
+ 'duration_ms': (time.time() - start_time) * 1000,
301
+ 'success': False,
302
+ 'error': str(e)
303
+ }
304
+ self._migration_history.append(migration_record)
305
+ raise XWNodeStrategyError(f"Migration failed: {e}")
306
+
307
+ def execute_edge_migration(self, source_strategy: Any, target_mode: EdgeMode,
308
+ target_traits: EdgeTrait = EdgeTrait.NONE,
309
+ **options) -> Any:
310
+ """Execute migration from source edge strategy to target."""
311
+ with self._migration_lock:
312
+ start_time = time.time()
313
+
314
+ # Extract data from source
315
+ edge_list = list(source_strategy.edges(data=True))
316
+ vertex_list = list(source_strategy.vertices())
317
+
318
+ # Create migration plan
319
+ source_mode = getattr(source_strategy, '_mode', EdgeMode.LEGACY)
320
+ plan = self.plan_edge_migration(source_mode, target_mode,
321
+ getattr(source_strategy, '_traits', EdgeTrait.NONE),
322
+ target_traits, len(edge_list), len(vertex_list))
323
+
324
+ logger.info(f"🔄 Executing edge migration: {source_mode.name} → {target_mode.name}")
325
+ logger.info(f"📊 Graph: {len(vertex_list)} vertices, {len(edge_list)} edges")
326
+
327
+ # Create target strategy
328
+ target_strategy = self._registry.get_edge_strategy(target_mode, traits=target_traits, **options)
329
+
330
+ # Migrate vertices and edges
331
+ try:
332
+ # Add vertices first
333
+ for vertex in vertex_list:
334
+ target_strategy.add_vertex(vertex)
335
+
336
+ # Add edges
337
+ for source, target, edge_data in edge_list:
338
+ properties = edge_data.get('properties', {})
339
+ target_strategy.add_edge(source, target, **properties)
340
+
341
+ # Record migration
342
+ migration_record = {
343
+ 'timestamp': time.time(),
344
+ 'type': 'edge',
345
+ 'source_mode': source_mode.name,
346
+ 'target_mode': target_mode.name,
347
+ 'edge_count': len(edge_list),
348
+ 'vertex_count': len(vertex_list),
349
+ 'duration_ms': (time.time() - start_time) * 1000,
350
+ 'success': True
351
+ }
352
+ self._migration_history.append(migration_record)
353
+
354
+ logger.info(f"✅ Edge migration completed in {migration_record['duration_ms']:.1f}ms")
355
+ return target_strategy
356
+
357
+ except Exception as e:
358
+ logger.error(f"❌ Edge migration failed: {e}")
359
+ migration_record = {
360
+ 'timestamp': time.time(),
361
+ 'type': 'edge',
362
+ 'source_mode': source_mode.name,
363
+ 'target_mode': target_mode.name,
364
+ 'edge_count': len(edge_list),
365
+ 'vertex_count': len(vertex_list),
366
+ 'duration_ms': (time.time() - start_time) * 1000,
367
+ 'success': False,
368
+ 'error': str(e)
369
+ }
370
+ self._migration_history.append(migration_record)
371
+ raise XWNodeStrategyError(f"Edge migration failed: {e}")
372
+
373
+ # ============================================================================
374
+ # MIGRATION HISTORY AND ANALYSIS
375
+ # ============================================================================
376
+
377
+ def get_migration_history(self) -> List[Dict[str, Any]]:
378
+ """Get the history of all migrations."""
379
+ return self._migration_history.copy()
380
+
381
+ def get_migration_stats(self) -> Dict[str, Any]:
382
+ """Get statistics about migrations."""
383
+ if not self._migration_history:
384
+ return {'total_migrations': 0}
385
+
386
+ successful = [m for m in self._migration_history if m['success']]
387
+ failed = [m for m in self._migration_history if not m['success']]
388
+
389
+ avg_duration = sum(m['duration_ms'] for m in successful) / len(successful) if successful else 0
390
+
391
+ return {
392
+ 'total_migrations': len(self._migration_history),
393
+ 'successful': len(successful),
394
+ 'failed': len(failed),
395
+ 'success_rate': len(successful) / len(self._migration_history) * 100,
396
+ 'average_duration_ms': round(avg_duration, 2),
397
+ 'most_common_source': self._most_common_field('source_mode'),
398
+ 'most_common_target': self._most_common_field('target_mode')
399
+ }
400
+
401
+ def _most_common_field(self, field: str) -> Optional[str]:
402
+ """Find the most common value for a field in migration history."""
403
+ if not self._migration_history:
404
+ return None
405
+
406
+ from collections import Counter
407
+ values = [m.get(field) for m in self._migration_history if field in m]
408
+ if not values:
409
+ return None
410
+
411
+ counter = Counter(values)
412
+ return counter.most_common(1)[0][0]
413
+
414
+ def clear_migration_history(self) -> None:
415
+ """Clear the migration history."""
416
+ self._migration_history.clear()
417
+ logger.info("🧹 Migration history cleared")
418
+
419
+
420
+ # Global migrator instance
421
+ _migrator = None
422
+ _migrator_lock = threading.Lock()
423
+
424
+
425
+ def get_migrator() -> xStrategyMigrator:
426
+ """Get the global strategy migrator instance."""
427
+ global _migrator
428
+ if _migrator is None:
429
+ with _migrator_lock:
430
+ if _migrator is None:
431
+ _migrator = xStrategyMigrator()
432
+ return _migrator
@@ -0,0 +1,50 @@
1
+ """
2
+ Node Strategies Package
3
+
4
+ This package contains all node strategy implementations organized by type:
5
+ - Linear strategies (arrays, lists, stacks, queues)
6
+ - Tree strategies (tries, heaps, BSTs)
7
+ - Graph strategies (union-find, neural graphs)
8
+
9
+ Company: eXonware.com
10
+ Author: Eng. Muhammad AlShehri
11
+ Email: connect@exonware.com
12
+ Version: 0.0.1.12
13
+ Generation Date: January 2, 2025
14
+ """
15
+
16
+ from .base import ANodeStrategy, ANodeLinearStrategy, ANodeTreeStrategy, ANodeGraphStrategy
17
+
18
+ # Linear strategies
19
+ from .array_list import ArrayListStrategy
20
+ from .linked_list import LinkedListStrategy
21
+
22
+ # Tree strategies
23
+ from .trie import xTrieStrategy
24
+ from .heap import xHeapStrategy
25
+ from .aho_corasick import xAhoCorasickStrategy
26
+
27
+ # Graph strategies
28
+ from .hash_map import HashMapStrategy
29
+ from .union_find import xUnionFindStrategy
30
+
31
+ __all__ = [
32
+ # Base classes
33
+ 'ANodeStrategy',
34
+ 'ANodeLinearStrategy',
35
+ 'ANodeTreeStrategy',
36
+ 'ANodeGraphStrategy',
37
+
38
+ # Linear strategies
39
+ 'ArrayListStrategy',
40
+ 'LinkedListStrategy',
41
+
42
+ # Tree strategies
43
+ 'xTrieStrategy',
44
+ 'xHeapStrategy',
45
+ 'xAhoCorasickStrategy',
46
+
47
+ # Graph strategies
48
+ 'HashMapStrategy',
49
+ 'xUnionFindStrategy'
50
+ ]