@@ -165,17 +165,13 @@ export class SerializationOptions {
165
165
return resource ? new SerializationOptions ( resource ) : null ;
166
166
}
167
167
168
- getParentRelation ( relationName ?: string ) : JSData . RelationDefinition {
168
+ getBelongsToRelation ( parentType : string , relationName ? : string ) : JSData . RelationDefinition {
169
169
if ( this . resourceDef . relations && this . resourceDef . relations . belongsTo ) {
170
170
171
171
if ( relationName ) {
172
- return this . resourceDef . relations . belongsTo [ relationName ] ;
172
+ return this . resourceDef . relations . belongsTo [ parentType ] ;
173
173
} else {
174
- for ( var r in this . resourceDef . relations . belongsTo ) {
175
- if ( this . resourceDef . relations . belongsTo [ r ] && this . resourceDef . relations . belongsTo [ r ] [ 0 ] ) {
176
- return this . resourceDef . relations . belongsTo [ r ] [ 0 ] ;
177
- }
178
- }
174
+ return this . resourceDef . relations . belongsTo [ parentType ] ;
179
175
}
180
176
}
181
177
@@ -286,6 +282,31 @@ export class SerializationOptions {
286
282
} ) ;
287
283
}
288
284
285
+ /**
286
+ * @name enumerateAllParentRelations
287
+ * @desc Encapsulates enumerating child relationships
288
+ * @param callback A function tobe called back with child relationship data
289
+ */
290
+ enumerateAllParentRelations ( callback : ( relation : JSData . RelationDefinition , index ?: number , source ?: Object ) => boolean ) : void {
291
+ DSUTILS . forEach ( this . resourceDef . relationList , ( relation : JSData . RelationDefinition , index ?: number , source ?: Object ) => {
292
+ if ( relation . type === jsDataBelongsTo ) {
293
+ return callback ( relation , index , source ) ;
294
+ }
295
+ } ) ;
296
+ }
297
+
298
+ /**
299
+ * @name enumerateRelations
300
+ * @desc Encapsulates enumerating child relationships
301
+ * @param callback A function tobe called back with child relationship data
302
+ */
303
+ enumerateRelations ( callback : ( relation : JSData . RelationDefinition , index ?: number , source ?: Object ) => boolean ) : void {
304
+ DSUTILS . forEach ( this . resourceDef . relationList , ( relation : JSData . RelationDefinition , index ?: number , source ?: Object ) => {
305
+ return callback ( relation , index , source ) ;
306
+ } ) ;
307
+ }
308
+
309
+
289
310
//Find relationship by relationship name
290
311
private getChildRelations ( relationType : string ) : Array < JSData . RelationDefinition > {
291
312
relationType = relationType . toLowerCase ( ) ;
@@ -1075,7 +1096,7 @@ export class JsonApiHelper {
1075
1096
}
1076
1097
1077
1098
// Get the parent relation of the joining type
1078
- var joiningTableChildRelation = joiningTypeResourceDef . getParentRelation ( joinMetaData . type ) ;
1099
+ var joiningTableChildRelation = joiningTypeResourceDef . getBelongsToRelation ( joinMetaData . type ) ;
1079
1100
if ( ! joiningTableChildRelation || ! joiningTableChildRelation [ 0 ] ) {
1080
1101
throw new Error (
1081
1102
'Expected Many-To-Many Joining table to have a "belongsTo" relation of type:' + joinMetaData . type +
@@ -1323,39 +1344,44 @@ export class JsonApiHelper {
1323
1344
* links in the links object provided.
1324
1345
* This will modify the response object.
1325
1346
*/
1326
- private static setParentIds ( options : SerializationOptions , data : JsonApi . JsonApiData , fields : any , metaData : MetaData ) : string {
1327
- // This object belongs to a parent then search backwards in url for the
1347
+ private static setParentIds ( options : SerializationOptions , data : JsonApi . JsonApiData , fields : any , metaData : MetaData ) : void {
1348
+ // This object belongs to a parent so search backwards in the self link url for the
1328
1349
// parent resource and then the next field we assume contains the parent reource id
1329
- // e.g. api/Parent/1/Children
1330
- var parentRel = options . getParentRelation ( ) ;
1331
- if ( parentRel ) {
1332
- // If Type is set and it has links and links has a self link
1333
- if ( data . type && data . GetSelfLink && data . GetSelfLink ( ) ) {
1350
+ // e.g. api/Parent/1/Childrelation
1351
+ //Here 'Parent' should be the data.type of the parent, follows by its id, then the child relationship
1334
1352
1335
- var parentName = parentRel . relation ;
1336
- // Get configured local key
1337
- var localKey = parentRel . localKey ;
1353
+ //Here:
1354
+ // - Parent is the name of the parent type , follows by the id.
1355
+ // - ChildRelation - is the localField/relationName on the parent
1338
1356
1339
- if ( ! localKey ) {
1340
- throw new Error (
1341
- 'ERROR: Incorrect js-data, relationship definition on js-data resource, Name:' + options . type + 'Relationship Name:' + parentRel . relation +
1342
- 'A "belongsTo" relationship requires a "localKey" to be configured' ) ;
1343
- }
1344
1357
1345
- var selfLinkArray = data . GetSelfLink ( ) . split ( '/' ) ;
1346
- var parentResourceIndex = selfLinkArray . lastIndexOf ( parentName ) ;
1347
- if ( parentResourceIndex > 0 ) {
1348
- fields [ localKey ] = selfLinkArray [ parentResourceIndex + 1 ] ; // Set Parent Id
1358
+ // Get parent link
1359
+ if ( data . type && data . GetSelfLink && data . GetSelfLink ( ) ) {
1360
+ var selfLinkArray = data . GetSelfLink ( ) . split ( '/' ) ;
1361
+
1362
+ // Iterate over parent relations
1363
+ // Look for parent type in self link.
1364
+ // If found get the id and set to loalKey
1365
+ options . enumerateAllParentRelations ( ( rel : JSData . RelationDefinition ) => {
1366
+
1367
+ // If we find a parent/belongsTo relationship with the same type as the parent then use it.
1368
+ // There should only ever be one parent relationship of a given type.
1369
+ var parentResourceIndex = selfLinkArray . lastIndexOf ( rel . relation ) ;
1370
+ if ( parentResourceIndex >= 0 && rel . localKey ) {
1371
+ //We found a match
1372
+ fields [ rel . localKey ] = selfLinkArray [ parentResourceIndex + 1 ] ; // Set Parent Id
1349
1373
var parentLink = selfLinkArray . slice ( 0 , parentResourceIndex + 2 ) . join ( '/' ) ;
1350
1374
1351
- metaData . WithRelationshipLink ( JSONAPI_PARENT_LINK , JSONAPI_PARENT_LINK , parentRel . relation , parentLink ) ;
1352
- return parentLink ;
1375
+ // This will allow loadRelations to load this a parent relationship!!
1376
+ // Im not sure when it would make sense to call loadRelations on a parent link?
1377
+ // Maybe if somehow you got an object without first loading its parent and called load relations on the
1378
+ // parent relation ?
1379
+ metaData . WithRelationshipLink ( rel . localField , JSONAPI_PARENT_LINK , rel . relation , parentLink ) ;
1380
+ return false ;
1353
1381
}
1354
- } else {
1355
- LogWarning ( 'Resource ' + options . type + ' has a "belongsTo" relation but is missing a self link and so its parent relation can not be set' ) ;
1356
- }
1382
+ return true ;
1383
+ } ) ;
1357
1384
}
1358
- return null ;
1359
1385
}
1360
1386
1361
1387
/**
@@ -1386,10 +1412,10 @@ export class JsonApiHelper {
1386
1412
// This is not required oneach data item this applies to the Resource Definition
1387
1413
var def : SerializationOptions = new SerializationOptions ( resource ) ;
1388
1414
1389
- def . enumerateAllChildRelations ( ( relationDef : JSData . RelationDefinition ) => {
1415
+ def . enumerateRelations ( ( relationDef : JSData . RelationDefinition ) => {
1390
1416
if ( typeof relationDef . load !== 'function' ) {
1391
1417
1392
- // This adds a customrelationship load method that is called by loadRelations to override default behaviour
1418
+ // This adds a custom relationship load method that is called by loadRelations to override default behaviour
1393
1419
// Here we add the relationship url to options and store a reference to this functon, set the relationshipDef load functions to undefined
1394
1420
// and call loadRelations again, this time options will contain the stored relatedLink and the load function will not get re-called as we have removed it
1395
1421
// Then after loadRelations completes or fails, restore the load function once again
@@ -1400,11 +1426,17 @@ export class JsonApiHelper {
1400
1426
optionsOrig : JSData . DSAdapterOperationConfiguration ) => {
1401
1427
1402
1428
var meta = MetaData . TryGetMetaData ( instance ) ;
1403
- var relatedLink = meta . getRelationshipLink ( relationDef . localField , JSONAPI_RELATED_LINK ) ;
1404
- var options : JsonApiAdapter . DSJsonApiAdapterOptions = < any > optionsOrig ;
1405
- if ( relatedLink ) {
1406
- options . jsonApi = options . jsonApi || < JsonApiAdapter . DSJsonApiOptions > { } ;
1407
- options . jsonApi . jsonApiPath = options . jsonApi . jsonApiPath || relatedLink . url ;
1429
+ if ( meta ) {
1430
+ var relatedLink = meta . getRelationshipLink (
1431
+ relationDef . localField ,
1432
+ ( relationDef . type === jsDataBelongsTo ) ? JSONAPI_PARENT_LINK : JSONAPI_RELATED_LINK
1433
+ ) ;
1434
+
1435
+ if ( relatedLink ) {
1436
+ var options : JsonApiAdapter . DSJsonApiAdapterOptions = < any > optionsOrig ;
1437
+ options . jsonApi = options . jsonApi || < JsonApiAdapter . DSJsonApiOptions > { } ;
1438
+ options . jsonApi . jsonApiPath = options . jsonApi . jsonApiPath || relatedLink . url ;
1439
+ }
1408
1440
}
1409
1441
1410
1442
var tmp = { target : relationDef , func : relationDef . load } ;
0 commit comments