Skip to content

Commit 6029da6

Browse files
committed
Work-in-progress
1 parent 18e4de0 commit 6029da6

File tree

1 file changed

+113
-127
lines changed

1 file changed

+113
-127
lines changed

Core/COSerialization.m

Lines changed: 113 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -119,54 +119,52 @@ - (id)serializedValueForScalarValue: (NSValue *)value
119119

120120
- (id)serializedReferenceForObject: (COObject *)value
121121
{
122-
/* Some root object relationships are special in the sense the value can be
123-
a core object but its persistency isn't enabled. We interpret these
124-
one-to-one relationships as transient.
125-
Usually a root object belongs to some other objects at run-time, in some
126-
cases the root object want to hold a backward pointer (inverse
127-
relationship) to those non-persistent object(s).
128-
For example, a root object can be a layout item whose parent item is the
129-
window group... In such a case, we don't want to persist the window
130-
group, but ignore it. At deseserialiation time, the app is responsible
131-
to add the item back to the window group (the parent item would be
132-
restored then). */
133-
if ([value isPersistent] || [value objectGraphContext] == [self objectGraphContext])
122+
/* Some root object relationships are special in the sense the value can be
123+
a core object but its persistency isn't enabled. We interpret these
124+
one-to-one relationships as transient.
125+
Usually a root object belongs to some other objects at run-time, in some
126+
cases the root object want to hold a backward pointer (inverse
127+
relationship) to those non-persistent object(s).
128+
For example, a root object can be a layout item whose parent item is the
129+
window group... In such a case, we don't want to persist the window
130+
group, but ignore it. At deseserialiation time, the app is responsible
131+
to add the item back to the window group (the parent item would be
132+
restored then). */
133+
if (![value isPersistent] && [value objectGraphContext] != [self objectGraphContext])
134+
{
135+
ETAssert([value isRoot]);
136+
return [NSNull null];
137+
}
138+
139+
if ([value persistentRoot] == [self persistentRoot])
140+
{
141+
return [value UUID];
142+
}
143+
else
144+
{
145+
// Serialize this cross-persistent root reference as a COPath
146+
147+
NSAssert([value isRoot], @"A property must point to a root object "
148+
"for references accross persistent roots");
149+
150+
COPersistentRoot *referencedPersistentRoot = [value persistentRoot];
151+
COObjectGraphContext *referencedPersistentRootCurrentBranchGraph =
152+
[referencedPersistentRoot objectGraphContext];
153+
COObjectGraphContext *referencedObjectGraph = [value objectGraphContext];
154+
COBranch *referencedBranch = [value branch];
155+
156+
if (referencedObjectGraph == referencedPersistentRootCurrentBranchGraph)
134157
{
135-
if ([value persistentRoot] == [self persistentRoot])
136-
{
137-
return [value UUID];
138-
}
139-
else
140-
{
141-
// Serialize this cross-persistent root reference as a COPath
142-
143-
NSAssert([value isRoot], @"A property must point to a root object "
144-
"for references accross persistent roots");
145-
146-
COPersistentRoot *referencedPersistentRoot = [value persistentRoot];
147-
COObjectGraphContext *referencedPersistentRootCurrentBranchGraph =
148-
[referencedPersistentRoot objectGraphContext];
149-
COObjectGraphContext *referencedObjectGraph = [value objectGraphContext];
150-
COBranch *referencedBranch = [value branch];
151-
152-
if (referencedObjectGraph == referencedPersistentRootCurrentBranchGraph)
153-
{
154-
// Serialize as a reference to the current branch
155-
return [COPath pathWithPersistentRoot: [referencedPersistentRoot UUID]];
156-
}
157-
else
158-
{
159-
// Serialize as a reference to a specific branch
160-
return [COPath pathWithPersistentRoot: [referencedPersistentRoot UUID]
161-
branch: [referencedBranch UUID]];
162-
}
163-
}
158+
// Serialize as a reference to the current branch
159+
return [COPath pathWithPersistentRoot: [referencedPersistentRoot UUID]];
164160
}
165161
else
166162
{
167-
ETAssert([value isRoot]);
168-
return [NSNull null];
163+
// Serialize as a reference to a specific branch
164+
return [COPath pathWithPersistentRoot: [referencedPersistentRoot UUID]
165+
branch: [referencedBranch UUID]];
169166
}
167+
}
170168
}
171169

172170
- (id) serializedValueForValue: (id)value
@@ -250,20 +248,14 @@ - (id)serializedValueForValue: (id)aValue
250248
{
251249
return [NSNull null];
252250
}
253-
else if ([value isKindOfClass: [ETUUID class]]
254-
|| [value isKindOfClass: [COPath class]])
251+
else if ([value isKindOfClass: [COObject class]])
255252
{
256-
return value;
253+
return [self serializedReferenceForObject: value];
257254
}
258255
else if ([value isKindOfClass: [COAttachmentID class]])
259256
{
260257
return value;
261258
}
262-
else if ([value isKindOfClass: [COObject class]])
263-
{
264-
return [self serializedReferenceForObject: value];
265-
}
266-
267259
else if ([self isSerializablePrimitiveValue: value])
268260
{
269261
return value;
@@ -325,6 +317,59 @@ - (BOOL) isSerializableScalarTypeName: (NSString *)aTypeName
325317
|| [aTypeName isEqualToString: @"NSRange"]);
326318
}
327319

320+
- (COType)serializedTypeForNumber: (NSNumber *)value
321+
{
322+
NSParameterAssert(value == nil || [value isKindOfClass: [NSNumber class]]);
323+
324+
// TODO: A bit ugly, would be better to add new entity descriptions
325+
// such as NSBOOLNumber, NSCGFloatNumber etc.
326+
if (value == nil)
327+
return kCOTypeString;
328+
329+
if (strcmp([value objCType], @encode(BOOL)) == 0
330+
|| strcmp([value objCType], @encode(NSInteger)) == 0
331+
|| strcmp([value objCType], @encode(NSUInteger)) == 0)
332+
{
333+
return kCOTypeInt64;
334+
}
335+
else if (strcmp([value objCType], @encode(CGFloat)) == 0
336+
|| strcmp([value objCType], @encode(double)) == 0
337+
|| strcmp([value objCType], @encode(float)) == 0)
338+
{
339+
return kCOTypeDouble;
340+
}
341+
342+
// FIXME: Finish the above... we should handle all values that NSNumber can encode,
343+
// except unsigned integers larger than the maximum value of int64_t.
344+
ETAssertUnreachable();
345+
return 0;
346+
}
347+
348+
- (NSString *)primitiveTypeNameFromValue: (id)value
349+
{
350+
if ([value isKindOfClass: [COObject class]])
351+
{
352+
return @"COObject";
353+
}
354+
else if ([value isKindOfClass: [NSString class]])
355+
{
356+
return @"NSString";
357+
}
358+
else if ([value isKindOfClass: [NSNumber class]])
359+
{
360+
return @"NSNumber";
361+
}
362+
else if ([value isKindOfClass: [NSData class]])
363+
{
364+
return @"NSData";
365+
}
366+
else if ([value isKindOfClass: [COAttachmentID class]])
367+
{
368+
return @"COAttachmentID";
369+
}
370+
return nil;
371+
}
372+
328373
- (COType)serializedTypeForUnivaluedPropertyDescription: (ETPropertyDescription *)aPropertyDesc
329374
ofValue: (id)value
330375
{
@@ -335,9 +380,22 @@ - (COType)serializedTypeForUnivaluedPropertyDescription: (ETPropertyDescription
335380
if (aPropertyDesc.valueTransformerName != nil)
336381
{
337382
ETAssert(![type isEqual: aPropertyDesc.type]);
338-
return [self.serializablePersistentTypes[type.name] intValue];
383+
return [self.serializablePersistentTypes[typeName] intValue];
339384
}
340-
385+
386+
if ([typeName isEqualToString: @"NSObject"])
387+
{
388+
if (value != nil)
389+
{
390+
typeName = [self primitiveTypeNameFromValue: value];
391+
}
392+
else
393+
{
394+
// NOTE: We use an arbitrary type
395+
return kCOTypeBlob;
396+
}
397+
}
398+
341399
if ([self isCoreObjectEntityType: type])
342400
{
343401
return ([aPropertyDesc isComposite] ? kCOTypeCompositeReference : kCOTypeReference);
@@ -349,7 +407,7 @@ - (COType)serializedTypeForUnivaluedPropertyDescription: (ETPropertyDescription
349407
return kCOTypeInt64;
350408
}
351409
else if ([typeName isEqualToString: @"CGFloat"]
352-
|| [typeName isEqualToString: @"Double"])
410+
|| [typeName isEqualToString: @"Double"])
353411
{
354412
return kCOTypeDouble;
355413
}
@@ -359,29 +417,7 @@ - (COType)serializedTypeForUnivaluedPropertyDescription: (ETPropertyDescription
359417
}
360418
else if ([typeName isEqualToString: @"NSNumber"])
361419
{
362-
NSParameterAssert(value == nil || [value isKindOfClass: [NSNumber class]]);
363-
364-
// TODO: A bit ugly, would be better to add new entity descriptions
365-
// such as NSBOOLNumber, NSCGFloatNumber etc.
366-
if (value == nil)
367-
return kCOTypeString;
368-
369-
if (strcmp([value objCType], @encode(BOOL)) == 0
370-
|| strcmp([value objCType], @encode(NSInteger)) == 0
371-
|| strcmp([value objCType], @encode(NSUInteger)) == 0)
372-
{
373-
return kCOTypeInt64;
374-
}
375-
else if (strcmp([value objCType], @encode(CGFloat)) == 0
376-
|| strcmp([value objCType], @encode(double)) == 0
377-
|| strcmp([value objCType], @encode(float)) == 0)
378-
{
379-
return kCOTypeDouble;
380-
}
381-
382-
// FIXME: Finish the above... we should handle all values that NSNumber can encode,
383-
// except unsigned integers larger than the maximum value of int64_t.
384-
ETAssertUnreachable();
420+
[self serializedTypeForNumber: value];
385421
}
386422
else if ([typeName isEqualToString: @"NSData"])
387423
{
@@ -395,56 +431,6 @@ - (COType)serializedTypeForUnivaluedPropertyDescription: (ETPropertyDescription
395431
{
396432
return kCOTypeAttachment;
397433
}
398-
else if ([self serializationGetterForProperty: [aPropertyDesc name]] != NULL)
399-
{
400-
// For a case like ETShape.pathResizeSelector, the COObject subclass
401-
// implements -serializedPathResizeSelector to return an NSString.
402-
// However, the typeName is "SEL".
403-
404-
/* Serialialization accessors can override the types declared in the
405-
property description using either NSString or NSData, but no other
406-
types.
407-
For a multivalued property, the same applies, since the property
408-
description type is the element type. For example, a serialization
409-
getter can return an array of ETUTI objects as an array of NSString
410-
objects. */
411-
if ([value isKindOfClass: [NSString class]])
412-
{
413-
return kCOTypeString;
414-
}
415-
else if ([value isKindOfClass: [NSData class]])
416-
{
417-
return kCOTypeBlob;
418-
}
419-
else if ([value isKindOfClass: [COObject class]])
420-
{
421-
ETAssert([typeName isEqualToString: @"NSObject"]);
422-
423-
/* For persistent relationship such as -[ETLayoutItem representedObject],
424-
where the value must be a COObject entity type (or some derived kind)
425-
to be persisted. For other NSObject derived instances, the
426-
relationship is treated as transient.
427-
428-
For such property, a serialization getter must be implemented to
429-
return nil when the value is not a persistent COObject instance
430-
(otherwise -serializedValueForValue:propertyDescription: raises
431-
an exception). */
432-
return kCOTypeReference;
433-
}
434-
else if (value == nil)
435-
{
436-
// NOTE: We use an arbitrary type
437-
return kCOTypeBlob;
438-
}
439-
else
440-
{
441-
NSString *getterString =
442-
NSStringFromSelector([self serializationGetterForProperty: [aPropertyDesc name]]);
443-
444-
NSAssert3(NO, @"Unsupported serialization type %@ for %@ returned by "
445-
"serialization getter %@", type, value, getterString);
446-
}
447-
}
448434
else if ([typeName isEqualToString: @"NSDate"])
449435
{
450436
/** For convenience, serialize NSDate as a int64_t using Java semantics. */

0 commit comments

Comments
 (0)