@@ -14,7 +14,7 @@ namespace LinqInfer.Data
14
14
/// General purpose document for serialising vector and general object data.
15
15
/// The document supports serialising as XML and to a binary stream
16
16
/// </summary>
17
- public class BinaryVectorDocument : IBinaryPersistable , IXmlExportable , IXmlImportable
17
+ public class BinaryVectorDocument : IBinaryPersistable , IXmlExportable , IXmlImportable , IEquatable < BinaryVectorDocument >
18
18
{
19
19
private const string PropertiesName = "PROP" ;
20
20
private const string BlobName = "BLOB" ;
@@ -102,8 +102,22 @@ public long Checksum
102
102
{
103
103
var type = instance ? . GetType ( ) ?? typeof ( T ) ;
104
104
105
- Properties [ "AssemblyQualifiedName" ] = type . AssemblyQualifiedName ;
106
- Properties [ "TypeName" ] = type . Name ;
105
+ SetType ( type ) ;
106
+ }
107
+
108
+ internal void SetType ( Type type )
109
+ {
110
+ Properties [ nameof ( AssemblyQualifiedName ) ] = type . AssemblyQualifiedName ;
111
+ Properties [ nameof ( TypeName ) ] = type . Name ;
112
+ }
113
+
114
+ internal string AssemblyQualifiedName => PropertyOrDefault ( nameof ( AssemblyQualifiedName ) , string . Empty ) ;
115
+
116
+ internal string TypeName => PropertyOrDefault ( nameof ( TypeName ) , string . Empty ) ;
117
+
118
+ public BinaryVectorDocument FindChild < T > ( )
119
+ {
120
+ return QueryChildren ( new { AssemblyQualifiedName = typeof ( T ) . AssemblyQualifiedName } ) . FirstOrDefault ( ) ;
107
121
}
108
122
109
123
public IDictionary < string , string > Properties
@@ -122,6 +136,29 @@ public IDictionary<string, byte[]> Blobs
122
136
}
123
137
}
124
138
139
+ public IEnumerable < BinaryVectorDocument > QueryChildren ( object propertyQuery )
140
+ {
141
+ var query = propertyQuery . ToDictionary ( ) ;
142
+
143
+ return Children . Where ( c =>
144
+ {
145
+ bool found = true ;
146
+
147
+ foreach ( var q in query )
148
+ {
149
+ if ( c . Properties . TryGetValue ( q . Key , out string v ) && v == q . Value ? . ToString ( ) )
150
+ {
151
+ continue ;
152
+ }
153
+
154
+ found = false ;
155
+ break ;
156
+ }
157
+
158
+ return found ;
159
+ } ) ;
160
+ }
161
+
125
162
public bool HasProperty ( string name )
126
163
{
127
164
return _properties . ContainsKey ( name ) ;
@@ -212,12 +249,20 @@ internal T PropertyOrDefault<T>(Expression<Func<object>> keyExpression, T defaul
212
249
return PropertyOrDefault ( propName , defaultValue ) ;
213
250
}
214
251
215
- internal void SetPropertyFromExpression ( Expression < Func < object > > expression )
252
+ internal void SetPropertyFromExpression ( Expression < Func < object > > expression , object value = null )
216
253
{
217
254
var propName = LinqExtensions . GetPropertyName ( expression ) ;
218
- var value = expression . Compile ( ) . Invoke ( ) ;
219
255
220
- if ( value != null )
256
+ if ( value == null )
257
+ {
258
+ value = expression . Compile ( ) . Invoke ( ) ;
259
+
260
+ if ( value != null )
261
+ {
262
+ Properties [ propName ] = value . ToString ( ) ;
263
+ }
264
+ }
265
+ else
221
266
{
222
267
Properties [ propName ] = value . ToString ( ) ;
223
268
}
@@ -227,7 +272,7 @@ internal BinaryVectorDocument GetChildDoc<T>(Type type = null, int? index = null
227
272
{
228
273
var tname = ( type ?? typeof ( T ) ) . GetTypeInf ( ) . Name ;
229
274
230
- var childNode = index . HasValue ? Children [ index . Value ] : Children . SingleOrDefault ( c => c . HasProperty ( " TypeName" ) && c . Properties [ "TypeName" ] == tname ) ;
275
+ var childNode = index . HasValue ? Children [ index . Value ] : Children . SingleOrDefault ( c => c . TypeName == tname ) ;
231
276
232
277
if ( childNode == null && ! ignoreIfMissing ) throw new FormatException ( "Child object not found : " + tname ) ;
233
278
@@ -259,22 +304,23 @@ internal T ReadChildObject<T>(T obj, int? index = null, bool ignoreIfMissing = f
259
304
throw new NotSupportedException ( ) ;
260
305
}
261
306
262
- internal void WriteChildObject ( object obj )
307
+ internal void WriteChildObject ( object obj , object attributes = null )
263
308
{
264
309
if ( obj == null ) return ;
265
310
266
- var childType = obj . GetType ( ) . GetTypeInf ( ) ;
267
- var tc = Type . GetTypeCode ( obj . GetType ( ) ) ;
311
+ var childType = obj . GetType ( ) ;
312
+ var tc = Type . GetTypeCode ( childType ) ;
268
313
269
314
if ( tc == TypeCode . Object )
270
315
{
271
- if ( obj is IExportableAsVectorDocument && obj is IImportableAsVectorDocument )
316
+ if ( obj is IExportableAsVectorDocument )
272
317
{
273
318
var childDoc = ( ( IExportableAsVectorDocument ) obj ) . ToVectorDocument ( ) ;
274
319
275
- childDoc . Properties [ "TypeName" ] = childType . Name ;
276
- childDoc . Properties [ "QualifiedTypeName" ] = childType . AssemblyQualifiedName ;
320
+ SetProperties ( childDoc , attributes ) ;
277
321
322
+ childDoc . SetType ( childType ) ;
323
+
278
324
Children . Add ( childDoc ) ;
279
325
}
280
326
else
@@ -283,8 +329,8 @@ internal void WriteChildObject(object obj)
283
329
{
284
330
var childDoc = new BinaryVectorDocument ( ) ;
285
331
286
- childDoc . Properties [ "TypeName" ] = childType . Name ;
287
- childDoc . Properties [ "QualifiedTypeName" ] = childType . AssemblyQualifiedName ;
332
+ SetProperties ( childDoc , attributes ) ;
333
+ childDoc . SetType ( childType ) ;
288
334
childDoc . Properties [ "Data" ] = ( ( IBinaryPersistable ) obj ) . ToClob ( ) ;
289
335
290
336
Children . Add ( childDoc ) ;
@@ -354,6 +400,19 @@ protected void Read(BinaryReader reader, int level)
354
400
}
355
401
}
356
402
403
+ private void SetProperties ( BinaryVectorDocument doc , object obj )
404
+ {
405
+ if ( obj != null )
406
+ {
407
+ var data = obj . ToDictionary ( ) ;
408
+
409
+ foreach ( var item in data )
410
+ {
411
+ doc . Properties [ item . Key ] = item . Value . ToString ( ) ;
412
+ }
413
+ }
414
+ }
415
+
357
416
private XDocument ExportAsXml ( bool isRoot , bool base64v )
358
417
{
359
418
var date = DateTime . UtcNow ;
@@ -518,5 +577,30 @@ protected void Write(BinaryWriter writer, int level)
518
577
child . Write ( writer , level + 1 ) ;
519
578
}
520
579
}
580
+
581
+ public bool Equals ( BinaryVectorDocument other )
582
+ {
583
+ if ( other == null ) return false ;
584
+ if ( ReferenceEquals ( this , other ) ) return true ;
585
+ if ( Checksum != other . Checksum ) return false ;
586
+
587
+ var xml1 = ExportAsXml ( ) ;
588
+ var xml2 = other . ExportAsXml ( ) ;
589
+
590
+ xml1 . Root . Attribute ( "exported" ) . Remove ( ) ;
591
+ xml2 . Root . Attribute ( "exported" ) . Remove ( ) ;
592
+
593
+ return string . Equals ( xml1 . ToString ( ) , xml2 . ToString ( ) ) ;
594
+ }
595
+
596
+ public override bool Equals ( object obj )
597
+ {
598
+ return Equals ( obj as BinaryVectorDocument ) ;
599
+ }
600
+
601
+ public override int GetHashCode ( )
602
+ {
603
+ return ExportAsXml ( ) . ToString ( ) . GetHashCode ( ) ;
604
+ }
521
605
}
522
606
}
0 commit comments