1
2
3
4
5
6 using System;
7 using System.Collections;
8
9 namespace System.Xml.Serialization
10 {
11 public class XmlContainer
12 {
13 public XmlContainer()
14 {
15 }
16 public virtual ~XmlContainer()
17 {
18 Clear();
19 }
20 public virtual void SetRootObjectId(const Uuid& objectId)
21 {
22 }
23 public inline long Count() const
24 {
25 return objectProxyMap.Count();
26 }
27 public inline bool IsEmpty() const
28 {
29 return objectProxyMap.IsEmpty();
30 }
31 public void Clear()
32 {
33 for (const Pair<void*, XmlSerializableProxy*>& p : objectProxyMap)
34 {
35 delete p.second;
36 }
37 idProxyMap.Clear();
38 objectProxyMap.Clear();
39
40 }
41 [nodiscard]
42 public Result<bool> Add(XmlSerializable xmlSerializable)
43 {
44 XmlSerializableProxy* prev = Get(xmlSerializable.ObjectId());
45 if (prev != null)
46 {
47 auto objectIdStrResult = ToString(prev->ObjectId());
48 if (objectIdStrResult.Error()) return Result<bool>(ErrorId(objectIdStrResult.GetErrorId()));
49 string objectIdStr = Rvalue(objectIdStrResult.Value());
50 int errorId = AllocateError("object \'" + objectIdStr + "\' already added to XML container");
51 return Result<bool>(ErrorId(errorId));
52 }
53 XmlSerializableProxy* proxy = new XmlSerializableProxy(xmlSerializable);
54 idProxyMap[proxy->ObjectId()] = proxy;
55 objectProxyMap[proxy->Object()] = proxy;
56 proxy->SetContainer(this);
57 return Result<bool>(true);
58 }
59 public XmlSerializableProxy* Get(const Uuid& objectId) const
60 {
61 auto it = idProxyMap.Find(objectId);
62 if (it != idProxyMap.End())
63 {
64 return it->second;
65 }
66 else
67 {
68 return null;
69 }
70 }
71 public void Remove(const Uuid& objectId)
72 {
73 XmlSerializableProxy* proxy = Get(objectId);
74 if (proxy != null)
75 {
76 objectProxyMap.Remove(proxy->Object());
77 idProxyMap.Remove(objectId);
78 delete proxy;
79 }
80 }
81 public XmlSerializableProxy* GetProxy(void* object)
82 {
83 auto it = objectProxyMap.Find(object);
84 if (it != objectProxyMap.End())
85 {
86 XmlSerializableProxy* proxy = it->second;
87 return proxy;
88 }
89 else
90 {
91 return null;
92 }
93 }
94 public List<XmlSerializableProxy*> GetProxies() const
95 {
96 List<XmlSerializableProxy*> proxies;
97 for (const Pair<void*, XmlSerializableProxy*>& p : objectProxyMap)
98 {
99 if (p.second != null)
100 {
101 proxies.Add(p.second);
102 }
103 }
104 return proxies;
105 }
106 [nodiscard]
107 public Result<bool> AddToBundle(XmlBundle& bundle, XmlBundleKind kind, int hops, XmlSerializable intf, HashSet<Uuid>& addedSet)
108 {
109 if (intf.ObjectId() == Uuid())
110 {
111 return Result<bool>(false);
112 }
113 if (addedSet.Find(intf.ObjectId()) != addedSet.End())
114 {
115 return Result<bool>(false);
116 }
117 auto addResult = bundle.Add(intf);
118 if (addResult.Error()) return addResult;
119 addedSet.Insert(intf.ObjectId());
120 if (kind == XmlBundleKind.deep && (hops == -1 || hops > 0))
121 {
122 List<XmlPtrBase*> ptrs = intf.GetPtrs();
123 for (XmlPtrBase* ptr : ptrs)
124 {
125 if (ptr->TargetObjectId() != Uuid())
126 {
127 XmlSerializableProxy* target = Get(ptr->TargetObjectId());
128 if (target != null)
129 {
130 int nextHops = -1;
131 if (hops > 0)
132 {
133 nextHops = hops - 1;
134 }
135 auto addResult = AddToBundle(bundle, kind, nextHops, target->Interface(), addedSet);
136 if (addResult.Error()) return addResult;
137 }
138 else
139 {
140 XmlSerializable intf = ptr->Interface();
141 XmlContainer* container = intf.Container();
142 if (container != null)
143 {
144 target = container->Get(ptr->TargetObjectId());
145 if (target != null)
146 {
147 int nextHops = -1;
148 if (hops > 0)
149 {
150 nextHops = hops - 1;
151 }
152 auto addResult = container->AddToBundle(bundle, kind, nextHops, intf, addedSet);
153 if (addResult.Error()) return addResult;
154 }
155 }
156 }
157 }
158 }
159 }
160 return Result<bool>(true);
161 }
162 public Result<XmlBundle> CreateBundle(void* object)
163 {
164 return CreateBundle(object, XmlBundleKind.shallow);
165 }
166 public Result<XmlBundle> CreateBundle(void* object, XmlBundleKind kind)
167 {
168 return CreateBundle(object, kind, -1);
169 }
170 public Result<XmlBundle> CreateBundle(void* object, XmlBundleKind kind, int hops)
171 {
172 HashSet<Uuid> addedSet;
173 XmlBundle bundle;
174 XmlSerializableProxy* proxy = GetProxy(object);
175 if (proxy != null)
176 {
177 bundle.SetRootObjectId(proxy->ObjectId());
178 XmlSerializable intf = proxy->Interface();
179 auto addResult = AddToBundle(bundle, kind, hops, intf, addedSet);
180 if (addResult.Error()) return Result<XmlBundle>(ErrorId(addResult.GetErrorId()));
181 }
182 return Result<XmlBundle>(Rvalue(bundle));
183 }
184 public HashMap<Uuid, XmlSerializableProxy*> idProxyMap;
185 public HashMap<void*, XmlSerializableProxy*> objectProxyMap;
186 }
187
188 public Result<bool> Add<T>(T* object, XmlContainer* container)
189 {
190 XmlSerializable xmlSerializable(*object);
191 return container->Add(xmlSerializable);
192 }
193
194 public Result<bool> AddOrReplace<T>(T* object, XmlContainer* container)
195 {
196 XmlSerializable xmlSerializable(*object);
197 container->Remove(xmlSerializable.ObjectId());
198 return container->Add(xmlSerializable);
199 }
200
201 public void RemoveFromContainer<T>(T* object)
202 {
203 XmlSerializable xmlSerializable(*object);
204 XmlContainer* container = xmlSerializable.Container();
205 if (container != null)
206 {
207 container->Remove(xmlSerializable.ObjectId());
208 }
209 }
210 }