stepxmlclient 1.0.0__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 (70) hide show
  1. stepxmlclient/__init__.py +22 -0
  2. stepxmlclient/client.py +373 -0
  3. stepxmlclient/creator.py +317 -0
  4. stepxmlclient/model/__init__.py +418 -0
  5. stepxmlclient/model/asset.py +250 -0
  6. stepxmlclient/model/attribute.py +288 -0
  7. stepxmlclient/model/business.py +233 -0
  8. stepxmlclient/model/classification.py +409 -0
  9. stepxmlclient/model/complex_elements.py +260 -0
  10. stepxmlclient/model/deletion.py +87 -0
  11. stepxmlclient/model/entity.py +368 -0
  12. stepxmlclient/model/metadata.py +199 -0
  13. stepxmlclient/model/organization.py +167 -0
  14. stepxmlclient/model/product.py +519 -0
  15. stepxmlclient/model/relations.py +105 -0
  16. stepxmlclient/model/replacement.py +417 -0
  17. stepxmlclient/parser.py +2805 -0
  18. stepxmlclient/rest_client/__init__.py +16 -0
  19. stepxmlclient/rest_client/base.py +388 -0
  20. stepxmlclient/rest_client/client.py +127 -0
  21. stepxmlclient/rest_client/exceptions.py +97 -0
  22. stepxmlclient/rest_client/models/__init__.py +175 -0
  23. stepxmlclient/rest_client/models/asset.py +253 -0
  24. stepxmlclient/rest_client/models/attribute.py +112 -0
  25. stepxmlclient/rest_client/models/background_process.py +23 -0
  26. stepxmlclient/rest_client/models/batch.py +41 -0
  27. stepxmlclient/rest_client/models/classification.py +57 -0
  28. stepxmlclient/rest_client/models/collection.py +26 -0
  29. stepxmlclient/rest_client/models/common.py +192 -0
  30. stepxmlclient/rest_client/models/context.py +16 -0
  31. stepxmlclient/rest_client/models/data_type_group.py +15 -0
  32. stepxmlclient/rest_client/models/entity.py +63 -0
  33. stepxmlclient/rest_client/models/event_processor.py +15 -0
  34. stepxmlclient/rest_client/models/import_export.py +43 -0
  35. stepxmlclient/rest_client/models/integration_endpoint.py +16 -0
  36. stepxmlclient/rest_client/models/product.py +200 -0
  37. stepxmlclient/rest_client/models/relations.py +280 -0
  38. stepxmlclient/rest_client/models/system_information.py +11 -0
  39. stepxmlclient/rest_client/models/user.py +28 -0
  40. stepxmlclient/rest_client/models/workflow.py +30 -0
  41. stepxmlclient/rest_client/operations/__init__.py +54 -0
  42. stepxmlclient/rest_client/operations/assets.py +652 -0
  43. stepxmlclient/rest_client/operations/attributes.py +252 -0
  44. stepxmlclient/rest_client/operations/background_processes.py +84 -0
  45. stepxmlclient/rest_client/operations/batch.py +28 -0
  46. stepxmlclient/rest_client/operations/classifications.py +248 -0
  47. stepxmlclient/rest_client/operations/collection_groups.py +46 -0
  48. stepxmlclient/rest_client/operations/collections.py +67 -0
  49. stepxmlclient/rest_client/operations/contexts.py +88 -0
  50. stepxmlclient/rest_client/operations/data_type_groups.py +68 -0
  51. stepxmlclient/rest_client/operations/entities.py +295 -0
  52. stepxmlclient/rest_client/operations/event_processors.py +109 -0
  53. stepxmlclient/rest_client/operations/exports.py +153 -0
  54. stepxmlclient/rest_client/operations/gateway.py +53 -0
  55. stepxmlclient/rest_client/operations/inbound.py +472 -0
  56. stepxmlclient/rest_client/operations/outbound.py +64 -0
  57. stepxmlclient/rest_client/operations/products.py +489 -0
  58. stepxmlclient/rest_client/operations/relations.py +349 -0
  59. stepxmlclient/rest_client/operations/reports.py +27 -0
  60. stepxmlclient/rest_client/operations/system_information.py +28 -0
  61. stepxmlclient/rest_client/operations/user_groups.py +79 -0
  62. stepxmlclient/rest_client/operations/users.py +119 -0
  63. stepxmlclient/rest_client/operations/workflow_tasks.py +61 -0
  64. stepxmlclient/rest_client/operations/workflows.py +50 -0
  65. stepxmlclient/upload.py +293 -0
  66. stepxmlclient-1.0.0.dist-info/METADATA +666 -0
  67. stepxmlclient-1.0.0.dist-info/RECORD +70 -0
  68. stepxmlclient-1.0.0.dist-info/WHEEL +5 -0
  69. stepxmlclient-1.0.0.dist-info/licenses/LICENSE +21 -0
  70. stepxmlclient-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,288 @@
1
+ """Attribute model for STEP XML Client.
2
+
3
+ Defines the Attribute entity class for representing attribute definitions in STEP MDM.
4
+ Attributes define the properties that can be assigned to products, assets, and entities.
5
+ """
6
+
7
+ from typing import List, Optional, Any, Dict, TYPE_CHECKING
8
+ from . import BaseObject
9
+
10
+ if TYPE_CHECKING:
11
+ pass
12
+
13
+
14
+ class Attribute(BaseObject):
15
+ """Attribute definition in STEP MDM.
16
+
17
+ Defines a property/characteristic that can be assigned to products, assets, and entities.
18
+ Supports multiple data types, validation rules, units, and dimensional analysis.
19
+
20
+ Attributes:
21
+ ID: Unique attribute identifier
22
+ DefaultUnitID: Default unit for numeric values
23
+ ProductMode: 'Normal' or 'Property' (property attributes have limited usage)
24
+ CryptographicKeyID: Optional encryption key for sensitive data
25
+ HierarchicalFiltering: Whether to use hierarchical filtering
26
+ ClassificationHierarchicalFiltering: Whether to use classification hierarchy filtering
27
+ ExternallyMaintained: Whether values are maintained externally
28
+ FullTextIndexed: Whether to index for full-text search
29
+ MultiValued: Whether attribute can have multiple values
30
+ Mandatory: Whether attribute is required
31
+ Derived: Whether value is computed/derived
32
+ Selected: Whether attribute is selected in UI
33
+ Referenced: Whether attribute is referenced elsewhere
34
+ Changed: Whether attribute was modified
35
+ Deleted: Whether attribute is marked for deletion
36
+ Name: Attribute name (localized)
37
+ Validation: Data type validation configuration
38
+ ListOfValueLink: Link to List-of-Values for choice attributes
39
+ ValueTemplate: Template for attribute values
40
+ UnitTemplate: Template for units
41
+ DimensionLink: Links to dimensional definitions
42
+ MetaData: Metadata associated with attribute
43
+ AttributeGroupLink: Links to attribute groups
44
+ UserTypeLink: Links to user types
45
+ LinkType: Link type associations
46
+ ValueFilter: Filters for attribute values
47
+ CurrentTasks: Current task information
48
+ """
49
+ _GROUP_NAME: str = 'attributes'
50
+ _TAG_NAME: str = 'Attribute'
51
+ _ATTRIBUTE_NAMES: List[str] = [
52
+ "ID", "DefaultUnitID", "ProductMode", "CryptographicKeyID",
53
+ "HierarchicalFiltering", "ClassificationHierarchicalFiltering",
54
+ "ExternallyMaintained", "FullTextIndexed", "MultiValued",
55
+ "Mandatory", "Derived", "Selected", "Referenced", "Changed", "Deleted"
56
+ ]
57
+ _TEXT_NAMES: List[str] = ["Name"]
58
+ _CHILDREN_NAMES: List[str] = [
59
+ "Validation",
60
+ "ListOfValueLink",
61
+ "ValueTemplate",
62
+ "UnitTemplate",
63
+ "DimensionLink",
64
+ "MetaData",
65
+ "AttributeGroupLink",
66
+ "UserTypeLink",
67
+ "LinkType",
68
+ "ValueFilter",
69
+ "CurrentTasks"
70
+ ]
71
+
72
+ def __init__(self, data: Dict[str, Any]) -> None:
73
+ super().__init__(data)
74
+ # Initialize link lists if not provided
75
+ for link_name in ["DimensionLink", "AttributeGroupLink", "UserTypeLink", "LinkType"]:
76
+ if link_name not in self._data:
77
+ self._data[link_name] = []
78
+
79
+
80
+ class AttributeGroup(BaseObject):
81
+ """AttributeGroup - hierarchical grouping of attributes for organizational purposes.
82
+
83
+ Supports:
84
+ - Nested attribute groups (parent/child hierarchy)
85
+ - Workbench visibility settings
86
+ - Manual sorting control
87
+ - Profiling exclusion options
88
+ - Configuration/view definitions
89
+ - Boolean state tracking (ShowInWorkbench, ExcludeFromProfiling, Selected, Referenced, etc.)
90
+ """
91
+ _GROUP_NAME: str = 'attributegroups'
92
+ _TAG_NAME: str = 'AttributeGroup'
93
+ _ATTRIBUTE_NAMES: List[str] = [
94
+ "ID", "ParentID", "ShowInWorkbench", "ExcludeFromProfiling",
95
+ "Referenced", "ManuallySorted", "Selected", "Changed", "Deleted"
96
+ ]
97
+ _TEXT_NAMES: List[str] = ["Name"]
98
+ _CHILDREN_NAMES: List[str] = [
99
+ "MetaData",
100
+ "Configuration",
101
+ "AttributeSequence",
102
+ "AttributeGroup" # Nested attribute groups
103
+ ]
104
+
105
+ def __init__(self, data: Dict[str, Any]) -> None:
106
+ super().__init__(data)
107
+ # Initialize nested attribute groups list
108
+ if "AttributeGroup" not in self._data:
109
+ self._data["AttributeGroup"] = []
110
+
111
+ def add_nested_attribute_group(self, attribute_group: Optional['AttributeGroup'] = None,
112
+ **kwargs) -> None:
113
+ """Add nested child attribute group.
114
+
115
+ Can be called two ways:
116
+ 1. With object: add_nested_attribute_group(attribute_group=child_group)
117
+ 2. With parameters: add_nested_attribute_group(ID="AG002", Name="Child Group")
118
+ """
119
+ if attribute_group is not None:
120
+ nested = attribute_group
121
+ else:
122
+ nested = AttributeGroup(kwargs)
123
+
124
+ if not isinstance(self._data["AttributeGroup"], list):
125
+ self._data["AttributeGroup"] = []
126
+ self._data["AttributeGroup"].append(nested)
127
+
128
+
129
+ class ListOfValues(BaseObject):
130
+ """ListOfValues - defines a set of allowed values for an attribute with optional grouping.
131
+
132
+ Supports:
133
+ - Hierarchical value groups (parent/child)
134
+ - Value definitions and deletion
135
+ - User-contributed values
136
+ - Value ID usage control
137
+ - Validation rules
138
+ - Dimensional analysis (DimensionLink)
139
+ - Unit definitions (DefaultUnitID)
140
+ - Boolean state tracking (AllowUserValueAddition, UseValueID, ReplaceListOfValuesValues, etc.)
141
+ """
142
+ _GROUP_NAME: str = 'listofvalues'
143
+ _TAG_NAME: str = 'ListOfValues'
144
+ _ATTRIBUTE_NAMES: List[str] = [
145
+ "ID", "ParentID", "AllowUserValueAddition", "UseValueID",
146
+ "IDPattern", "ReplaceListOfValuesValues", "DefaultUnitID"
147
+ ]
148
+ _TEXT_NAMES: List[str] = ["Name"]
149
+ _CHILDREN_NAMES: List[str] = [
150
+ "Validation",
151
+ "DimensionLink",
152
+ "MetaData",
153
+ "AttributeGroupLink",
154
+ "Value",
155
+ "ValueGroup",
156
+ "DeleteValue",
157
+ "ListOfValuesGroup" # Nested groups
158
+ ]
159
+
160
+ def __init__(self, data: Dict[str, Any]) -> None:
161
+ super().__init__(data)
162
+ # Initialize link lists if not provided
163
+ for link_name in ["DimensionLink", "AttributeGroupLink"]:
164
+ if link_name not in self._data:
165
+ self._data[link_name] = []
166
+
167
+ # Initialize value lists
168
+ for value_name in ["Value", "ValueGroup", "DeleteValue", "ListOfValuesGroup"]:
169
+ if value_name not in self._data:
170
+ self._data[value_name] = []
171
+
172
+ def add_value(self, value_id: Optional[str] = None,
173
+ name: Optional[str] = None,
174
+ **kwargs) -> None:
175
+ """Add a value to this list of values.
176
+
177
+ Args:
178
+ value_id: ID of the value (if UseValueID=true)
179
+ name: Display name of the value
180
+ **kwargs: Additional attributes to pass to Value element
181
+ """
182
+ value_dict = {}
183
+ if value_id is not None:
184
+ value_dict["ID"] = value_id
185
+ if name is not None:
186
+ value_dict["Name"] = name
187
+ value_dict.update(kwargs)
188
+
189
+ if not isinstance(self._data["Value"], list):
190
+ self._data["Value"] = []
191
+ self._data["Value"].append(value_dict)
192
+
193
+ def delete_value(self, value_id: str) -> None:
194
+ """Mark a value for deletion from this list of values.
195
+
196
+ Args:
197
+ value_id: ID of the value to delete
198
+ """
199
+ delete_dict = {"ID": value_id}
200
+
201
+ if not isinstance(self._data["DeleteValue"], list):
202
+ self._data["DeleteValue"] = []
203
+ self._data["DeleteValue"].append(delete_dict)
204
+
205
+ def add_value_group(self, value_group: Optional['ValueGroup'] = None,
206
+ **kwargs) -> None:
207
+ """Add a value group (for grouped value organization).
208
+
209
+ Can be called two ways:
210
+ 1. With object: add_value_group(value_group=group_obj)
211
+ 2. With parameters: add_value_group(ID="VG001", Name="Group Name")
212
+ """
213
+ if value_group is not None:
214
+ group = value_group
215
+ else:
216
+ group = ValueGroup(kwargs)
217
+
218
+ if not isinstance(self._data["ValueGroup"], list):
219
+ self._data["ValueGroup"] = []
220
+ self._data["ValueGroup"].append(group)
221
+
222
+ def add_nested_list_of_values_group(self, group: Optional['ListOfValuesGroup'] = None,
223
+ **kwargs) -> None:
224
+ """Add nested list of values group for hierarchical organization.
225
+
226
+ Can be called two ways:
227
+ 1. With object: add_nested_list_of_values_group(group=child_group)
228
+ 2. With parameters: add_nested_list_of_values_group(ID="LOG001", Name="Group")
229
+ """
230
+ if group is not None:
231
+ nested = group
232
+ else:
233
+ nested = ListOfValuesGroup(kwargs)
234
+
235
+ if not isinstance(self._data["ListOfValuesGroup"], list):
236
+ self._data["ListOfValuesGroup"] = []
237
+ self._data["ListOfValuesGroup"].append(nested)
238
+
239
+
240
+ class ValueGroup(BaseObject):
241
+ """ValueGroup - groups related values within a ListOfValues for organizational purposes."""
242
+ _GROUP_NAME: Optional[str] = None # Used as child element only
243
+ _TAG_NAME: str = 'ValueGroup'
244
+ _ATTRIBUTE_NAMES: List[str] = ["ID"]
245
+ _TEXT_NAMES: List[str] = ["Name"]
246
+ _CHILDREN_NAMES: List[str] = ["Value"]
247
+
248
+ def __init__(self, data: Dict[str, Any]) -> None:
249
+ super().__init__(data)
250
+ if "Value" not in self._data:
251
+ self._data["Value"] = []
252
+
253
+
254
+ class ListOfValuesGroup(BaseObject):
255
+ """ListOfValuesGroup - hierarchical grouping of lists of values."""
256
+ _GROUP_NAME: Optional[str] = None # Used as child element only
257
+ _TAG_NAME: str = 'ListOfValuesGroup'
258
+ _ATTRIBUTE_NAMES: List[str] = ["ID", "ParentID", "Selected", "Referenced", "Changed"]
259
+ _TEXT_NAMES: List[str] = ["Name"]
260
+ _CHILDREN_NAMES: List[str] = [
261
+ "MetaData",
262
+ "AttributeGroupLink",
263
+ "ListOfValuesGroup" # Nested groups
264
+ ]
265
+
266
+ def __init__(self, data: Dict[str, Any]) -> None:
267
+ super().__init__(data)
268
+ if "AttributeGroupLink" not in self._data:
269
+ self._data["AttributeGroupLink"] = []
270
+ if "ListOfValuesGroup" not in self._data:
271
+ self._data["ListOfValuesGroup"] = []
272
+
273
+ def add_nested_list_of_values_group(self, group: Optional['ListOfValuesGroup'] = None,
274
+ **kwargs) -> None:
275
+ """Add nested list of values group.
276
+
277
+ Can be called two ways:
278
+ 1. With object: add_nested_list_of_values_group(group=child_group)
279
+ 2. With parameters: add_nested_list_of_values_group(ID="LOG002", Name="Child")
280
+ """
281
+ if group is not None:
282
+ nested = group
283
+ else:
284
+ nested = ListOfValuesGroup(kwargs)
285
+
286
+ if not isinstance(self._data["ListOfValuesGroup"], list):
287
+ self._data["ListOfValuesGroup"] = []
288
+ self._data["ListOfValuesGroup"].append(nested)
@@ -0,0 +1,233 @@
1
+ """Business rules and workflow models for STEP XML Client.
2
+
3
+ Defines business logic execution entities including Business Rules and Workflows
4
+ that control behavior and processes within STEP MDM systems.
5
+ """
6
+
7
+ from typing import List, Optional, Any, Dict, TYPE_CHECKING
8
+ from . import BaseObject
9
+
10
+ if TYPE_CHECKING:
11
+ pass
12
+
13
+
14
+ class BusinessRule(BaseObject):
15
+ """Business logic executable in STEP MDM.
16
+
17
+ Defines executable business logic including actions, conditions, functions, and libraries.
18
+ Business rules contain logic that executes within the STEP system to automate processes.
19
+
20
+ Supports:
21
+ - Multiple rule types (Action, Condition, Function, Library)
22
+ - Rule scope (Local or Global)
23
+ - Privileged execution mode
24
+ - Dependencies on other rules
25
+ - Multi-language names and descriptions
26
+ - Setup group configuration
27
+
28
+ Attributes:
29
+ ID: Unique business rule identifier
30
+ Type: Rule type (Action, Condition, Function, Library, etc.)
31
+ Scope: Scope of execution (Local or Global)
32
+ RunPrivileged: Whether to run with elevated privileges
33
+ Name: Rule name (localized)
34
+ Description: Rule description (localized)
35
+ Dependency: List of dependent rules
36
+ FunctionDependency: List of function dependencies
37
+ OnApprove: On-approval behavior configuration
38
+ Configuration: Rule-specific configuration
39
+ ValidObjectTypes: Object types this rule applies to
40
+ SetupGroupLink: Link to setup groups
41
+ """
42
+ _GROUP_NAME: str = 'businessrules'
43
+ _TAG_NAME: str = 'BusinessRule'
44
+ _ATTRIBUTE_NAMES: List[str] = ["ID", "Type", "Scope", "RunPrivileged", "Selected", "Referenced", "Changed"]
45
+ _TEXT_NAMES: List[str] = ["Name", "Description"]
46
+ _CHILDREN_NAMES: List[str] = [
47
+ "Dependency",
48
+ "FunctionDependency",
49
+ "OnApprove",
50
+ "Configuration",
51
+ "ValidObjectTypes",
52
+ "SetupGroupLink"
53
+ ]
54
+
55
+ def __init__(self, data: Dict[str, Any]) -> None:
56
+ super().__init__(data)
57
+ # Initialize dependency lists if not provided
58
+ for dep_name in ["Dependency", "FunctionDependency"]:
59
+ if dep_name not in self._data:
60
+ self._data[dep_name] = []
61
+
62
+
63
+ class Workflow(BaseObject):
64
+ """Workflow - orchestrates business processes in STEP.
65
+
66
+ Workflows define states, transitions, and validations that control how objects
67
+ move through business processes. Workflows enforce rules about what operations
68
+ are allowed in each state and what data must be valid before transitions.
69
+
70
+ Supports:
71
+ - Object type constraints (ValidUserTypeLink)
72
+ - Start conditions
73
+ - Embedded business rules
74
+ - Business rule references
75
+ - Setup group configuration
76
+ - Multi-language names
77
+ - Boolean state tracking (Selected, Referenced, Changed)
78
+
79
+ Attributes:
80
+ ID: Unique workflow identifier
81
+ Name: Workflow name (localized)
82
+ Description: Workflow description
83
+ ValidUserTypeLink: Links to object types this workflow applies to
84
+ ValidBusinessRuleLink: Links to relevant business rules
85
+ StartCondition: Condition for workflow start
86
+ STEPAction: Workflow actions
87
+ STEPState: Workflow states
88
+ STEPEdge: State transitions
89
+ SetupGroupLink: Setup group associations
90
+ """
91
+ _GROUP_NAME: str = 'workflows'
92
+ _TAG_NAME: str = 'Workflow'
93
+ _ATTRIBUTE_NAMES: List[str] = ["ID", "Selected", "Referenced", "Changed"]
94
+ _TEXT_NAMES: List[str] = ["Name"]
95
+ _CHILDREN_NAMES: List[str] = [
96
+ "MetaData",
97
+ "ValidUserTypeLink",
98
+ "StartCondition",
99
+ "Configuration",
100
+ "LocalBusinessRule",
101
+ "BusinessRuleLink",
102
+ "SetupGroupLink"
103
+ ]
104
+
105
+ def __init__(self, data: Dict[str, Any]) -> None:
106
+ super().__init__(data)
107
+ # Initialize link lists if not provided
108
+ for link_name in ["ValidUserTypeLink", "LocalBusinessRule", "BusinessRuleLink"]:
109
+ if link_name not in self._data:
110
+ self._data[link_name] = []
111
+
112
+ def add_valid_user_type_link(self, user_type_id: str) -> None:
113
+ """Add a valid user type link to this workflow.
114
+
115
+ Args:
116
+ user_type_id: ID of the user type
117
+ """
118
+ if not isinstance(self._data["ValidUserTypeLink"], list):
119
+ self._data["ValidUserTypeLink"] = []
120
+ self._data["ValidUserTypeLink"].append(user_type_id)
121
+
122
+ def add_business_rule_link(self, business_rule_id: str) -> None:
123
+ """Add a business rule link to this workflow.
124
+
125
+ Args:
126
+ business_rule_id: ID of the business rule
127
+ """
128
+ if not isinstance(self._data["BusinessRuleLink"], list):
129
+ self._data["BusinessRuleLink"] = []
130
+ self._data["BusinessRuleLink"].append(business_rule_id)
131
+
132
+
133
+ class Collection(BaseObject):
134
+ """Collection - represents a user-defined collection of objects.
135
+
136
+ Collections group objects based on queries or manual selection.
137
+ They provide flexible organization outside fixed hierarchies.
138
+
139
+ Supports:
140
+ - Query-based membership (QueryURL)
141
+ - Parent collection linking for hierarchies
142
+ - Multi-language names
143
+ - Metadata tracking
144
+ """
145
+ _GROUP_NAME: str = 'collections'
146
+ _TAG_NAME: str = 'Collection'
147
+ _ATTRIBUTE_NAMES: List[str] = ["ID", "ParentID", "QueryURL"]
148
+ _TEXT_NAMES: List[str] = ["Name"]
149
+ _CHILDREN_NAMES: List[str] = ["MetaData", "CollectionGroup"]
150
+
151
+ def __init__(self, data: Dict[str, Any]) -> None:
152
+ super().__init__(data)
153
+ # Initialize nested collection groups list
154
+ if "CollectionGroup" not in self._data:
155
+ self._data["CollectionGroup"] = []
156
+
157
+ def add_nested_collection_group(self, collection_group: Optional['CollectionGroup'] = None,
158
+ **kwargs) -> None:
159
+ """Add nested collection group.
160
+
161
+ Can be called two ways:
162
+ 1. With object: add_nested_collection_group(collection_group=group_obj)
163
+ 2. With parameters: add_nested_collection_group(ID="CG001", Name="Group")
164
+ """
165
+ if collection_group is not None:
166
+ group = collection_group
167
+ else:
168
+ group = CollectionGroup(kwargs)
169
+
170
+ if not isinstance(self._data["CollectionGroup"], list):
171
+ self._data["CollectionGroup"] = []
172
+ self._data["CollectionGroup"].append(group)
173
+
174
+
175
+ class CollectionGroup(BaseObject):
176
+ """CollectionGroup - hierarchical grouping of collections.
177
+
178
+ Collection groups organize collections and nested groups into
179
+ logical hierarchies for better navigation and management.
180
+
181
+ Supports:
182
+ - Nested collection groups (parent/child hierarchy)
183
+ - Nested collections
184
+ - Multi-language names
185
+ - Metadata tracking
186
+ """
187
+ _GROUP_NAME: str = 'collectiongroups'
188
+ _TAG_NAME: str = 'CollectionGroup'
189
+ _ATTRIBUTE_NAMES: List[str] = ["ID", "ParentID"]
190
+ _TEXT_NAMES: List[str] = ["Name"]
191
+ _CHILDREN_NAMES: List[str] = ["MetaData", "CollectionGroup", "Collection"]
192
+
193
+ def __init__(self, data: Dict[str, Any]) -> None:
194
+ super().__init__(data)
195
+ # Initialize nested groups and collections lists
196
+ if "CollectionGroup" not in self._data:
197
+ self._data["CollectionGroup"] = []
198
+ if "Collection" not in self._data:
199
+ self._data["Collection"] = []
200
+
201
+ def add_nested_collection_group(self, collection_group: Optional['CollectionGroup'] = None,
202
+ **kwargs) -> None:
203
+ """Add nested collection group.
204
+
205
+ Can be called two ways:
206
+ 1. With object: add_nested_collection_group(collection_group=group_obj)
207
+ 2. With parameters: add_nested_collection_group(ID="CG002", Name="Nested")
208
+ """
209
+ if collection_group is not None:
210
+ group = collection_group
211
+ else:
212
+ group = CollectionGroup(kwargs)
213
+
214
+ if not isinstance(self._data["CollectionGroup"], list):
215
+ self._data["CollectionGroup"] = []
216
+ self._data["CollectionGroup"].append(group)
217
+
218
+ def add_collection(self, collection: Optional['Collection'] = None,
219
+ **kwargs) -> None:
220
+ """Add a collection to this group.
221
+
222
+ Can be called two ways:
223
+ 1. With object: add_collection(collection=coll_obj)
224
+ 2. With parameters: add_collection(ID="C001", Name="Collection Name")
225
+ """
226
+ if collection is not None:
227
+ coll = collection
228
+ else:
229
+ coll = Collection(kwargs)
230
+
231
+ if not isinstance(self._data["Collection"], list):
232
+ self._data["Collection"] = []
233
+ self._data["Collection"].append(coll)