Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/change-log.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const {
getEntityByContextPath,
getObjIdElementNamesInArray,
getValueEntityType,
splitPath,
} = require("./entity-helper")
const { localizeLogFields } = require("./localization")
const isRoot = "change-tracking-isRootEntity"
Expand Down Expand Up @@ -193,7 +194,7 @@ const _formatCompositionContext = async function (changes, reqData) {
}
for (const childNodeChange of change.valueChangedTo) {
const curChange = Object.assign({}, change)
const path = childNodeChange._path.split('/')
const path = splitPath(childNodeChange._path)
const curNodePathVal = path.pop()
curChange.modification = childNodeChange._op
const objId = await _getChildChangeObjId(
Expand Down Expand Up @@ -270,7 +271,7 @@ const _getObjectIdByPath = async function (
const _formatObjectID = async function (changes, reqData) {
const objectIdCache = new Map()
for (const change of changes) {
const path = change.serviceEntityPath.split('/')
const path = splitPath(change.serviceEntityPath)
const curNodePathVal = path.pop()
const parentNodePathVal = path.pop()

Expand Down
22 changes: 21 additions & 1 deletion lib/entity-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const getCurObjFromDbQuery = async function (entityName, queryVal, /**optional*/
}

const getCurObjFromReqData = function (reqData, nodePathVal, pathVal) {
const pathVals = pathVal.split('/')
const pathVals = splitPath(pathVal);
const rootNodePathVal = pathVals[0]
let curReqObj = reqData || {}

Expand Down Expand Up @@ -183,6 +183,25 @@ const _getCompositionObjFromReq = function (obj, targetID) {
return null;
};

function splitPath (path) {
let result = [];
let buf = "";
let paren = 0;
for (let i = 0; i < path.length; i++) {
const c = path[i];
if (c === "(") paren++;
if (c === ")") paren--;
if (c === "/" && paren === 0) {
result.push(buf);
buf = "";
} else {
buf += c;
}
}
if (buf) result.push(buf);
return result;
}

module.exports = {
getCurObjFromReqData,
getCurObjFromDbQuery,
Expand All @@ -193,4 +212,5 @@ module.exports = {
getEntityByContextPath,
getObjIdElementNamesInArray,
getValueEntityType,
splitPath,
}
4 changes: 2 additions & 2 deletions lib/localization.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const cds = require("@sap/cds/lib");
const LOG = cds.log("change-log");
const { getNameFromPathVal, getDBEntity } = require("./entity-helper");
const { getNameFromPathVal, getDBEntity, splitPath } = require("./entity-helper");

const MODIF_I18N_MAP = {
create: "{i18n>ChangeLog.modification.create}",
Expand Down Expand Up @@ -36,7 +36,7 @@ const _localizeDefaultObjectID = function (change, locale) {
change.objectID = change.entity ? change.entity : "";
}
if (change.objectID && change.serviceEntityPath && !change.parentObjectID && change.parentKey) {
const path = change.serviceEntityPath.split('/');
const path = splitPath(change.serviceEntityPath);
const parentNodePathVal = path[path.length - 2];
const parentEntityName = getNameFromPathVal(parentNodePathVal);
const dbEntity = getDBEntity(parentEntityName);
Expand Down
3 changes: 3 additions & 0 deletions tests/bookshop/db/data/sap.capire.bookshop-Level1Sample.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ID;title;parent_ID
/level1one;Level1Sample title1;/one
/level1two;Level1Sample title2;/two
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ID;title;parent_ID
/level1draftone;Level1SampleDraft title;/draftone
3 changes: 3 additions & 0 deletions tests/bookshop/db/data/sap.capire.bookshop-Level2Sample.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ID;title;parent_ID
/level2one;Level2Sample title1;/level1one
/level2two;Level2Sample title2;/level1two
3 changes: 3 additions & 0 deletions tests/bookshop/db/data/sap.capire.bookshop-RootSample.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ID;title
/one;RootSample title1
/two;RootSample title2
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ID;title
/draftone;Draft title
46 changes: 46 additions & 0 deletions tests/bookshop/db/schema.cds
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,49 @@ entity Schools : managed, cuid {
teacher : String;
};
}

// Test for key which include special character: '/' -- draft enabled
@title: 'Root Sample Draft'
entity RootSampleDraft @(cds.autoexpose) : managed {
key ID : String;
child : Composition of many Level1SampleDraft
on child.parent = $self;
title : String;
}

@title: 'Level1 Sample Draft'
entity Level1SampleDraft : managed {
key ID : String;
parent : Association to one RootSampleDraft;
child : Composition of many Level2SampleDraft
on child.parent = $self;
title : String;
}

entity Level2SampleDraft : managed {
key ID : String;
title : String;
parent : Association to one Level1SampleDraft;
}

// Test for key which include special character: '/' -- draft disabled
entity RootSample : managed {
key ID : String;
child : Composition of many Level1Sample
on child.parent = $self;
title : String;
}

entity Level1Sample : managed {
key ID : String;
parent : Association to one RootSample;
child : Composition of many Level2Sample
on child.parent = $self;
title : String;
}

entity Level2Sample : managed {
key ID : String;
title : String;
parent : Association to one Level1Sample;
}
165 changes: 114 additions & 51 deletions tests/bookshop/srv/admin-service.cds
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,57 @@ service AdminService {
entity RootEntity @(cds.autoexpose) as projection on my.RootEntity;

@odata.draft.enabled
entity Schools @(cds.autoexpose) as projection on my.Schools;

entity RootObject as projection on my.RootObject;
entity Level1Object as projection on my.Level1Object;
entity Level2Object as projection on my.Level2Object;
entity Level3Object as projection on my.Level3Object;
entity Level1Entity as projection on my.Level1Entity;
entity Level2Entity as projection on my.Level2Entity;
entity Level3Entity as projection on my.Level3Entity;
entity AssocOne as projection on my.AssocOne;
entity AssocTwo as projection on my.AssocTwo;
entity AssocThree as projection on my.AssocThree;
entity Authors as projection on my.Authors;
entity Report as projection on my.Report;
entity Order as projection on my.Order;
entity Order.Items as projection on my.Order.Items;
entity OrderItem as projection on my.OrderItem;

entity OrderItemNote as projection on my.OrderItemNote actions {
@cds.odata.bindingparameter.name: 'self'
@Common.SideEffects : {TargetEntities: [self]}
action activate();
};

entity Volumns as projection on my.Volumns actions {
@cds.odata.bindingparameter.name: 'self'
@Common.SideEffects : {TargetEntities: [self]}
action activate();
};
entity Schools @(cds.autoexpose) as projection on my.Schools;

@odata.draft.enabled
entity RootSampleDraft as projection on my.RootSampleDraft;

entity RootObject as projection on my.RootObject;
entity Level1Object as projection on my.Level1Object;
entity Level2Object as projection on my.Level2Object;
entity Level3Object as projection on my.Level3Object;
entity Level1Entity as projection on my.Level1Entity;
entity Level2Entity as projection on my.Level2Entity;
entity Level3Entity as projection on my.Level3Entity;
entity RootSample as projection on my.RootSample;
entity Level1Sample as projection on my.Level1Sample;
entity AssocOne as projection on my.AssocOne;
entity AssocTwo as projection on my.AssocTwo;
entity AssocThree as projection on my.AssocThree;
entity Authors as projection on my.Authors;
entity Report as projection on my.Report;
entity Order as projection on my.Order;
entity Order.Items as projection on my.Order.Items;
entity OrderItem as projection on my.OrderItem;

entity OrderItemNote as projection on my.OrderItemNote
actions {
@cds.odata.bindingparameter.name: 'self'
@Common.SideEffects : {TargetEntities: [self]}
action activate();
};

entity Volumns as projection on my.Volumns
actions {
@cds.odata.bindingparameter.name: 'self'
@Common.SideEffects : {TargetEntities: [self]}
action activate();
};

entity Level2Sample as projection on my.Level2Sample
actions {
@cds.odata.bindingparameter.name: 'self'
@Common.SideEffects : {TargetEntities: [self]}
action activate();
};

entity Customers as projection on my.Customers;
}

annotate AdminService.RootEntity with @changelog: [name] {
name @changelog;
child @changelog : [child.child.child.title];
lifecycleStatus @changelog : [lifecycleStatus.name];
lifecycleStatus @changelog : [lifecycleStatus.name];
info @changelog : [info.info.info.name];
};

Expand All @@ -63,13 +77,13 @@ annotate AdminService.Level3Entity with @changelog: [parent.parent.parent.lifecy
}

annotate AdminService.AssocOne with {
name @changelog;
info @changelog: [info.info.name]
name @changelog;
info @changelog: [info.info.name]
};

annotate AdminService.AssocTwo with {
name @changelog;
info @changelog: [info.name]
name @changelog;
info @changelog: [info.name]
};

annotate AdminService.AssocThree with {
Expand All @@ -96,47 +110,47 @@ annotate AdminService.Level3Object with {
};

annotate AdminService.Authors with {
name @(Common.Label : '{i18n>serviceAuthors.name}');
name @(Common.Label: '{i18n>serviceAuthors.name}');
};

annotate AdminService.BookStores with @changelog : [name]{
annotate AdminService.BookStores with @changelog: [name] {
name @changelog;
location @changelog;
books @changelog : [books.title];
lifecycleStatus @changelog : [lifecycleStatus.name];
city @changelog : [
books @changelog : [books.title];
lifecycleStatus @changelog : [lifecycleStatus.name];
city @changelog : [
city.name,
city.country.countryName.code
]
};


annotate AdminService.Books with @changelog : [
annotate AdminService.Books with @changelog: [
title,
author.name.firstName,
author.name.lastName
]{
] {
title @changelog;
descr @changelog;
isUsed @changelog;
author @changelog : [
author @changelog : [
author.name.firstName,
author.name.lastName
];
genre @changelog;
bookType @changelog : [
bookType @changelog : [
bookType.name,
bookType.descr
];
};

annotate AdminService.Authors with @changelog : [
annotate AdminService.Authors with @changelog: [
name.firstName,
name.lastName
]{
] {
name @changelog;
placeOfBirth @changelog;
books @changelog : [
books @changelog : [
books.name,
books.title
];
Expand All @@ -152,20 +166,20 @@ annotate AdminService.OrderHeader with {

annotate AdminService.OrderItem with {
quantity @changelog;
customer @changelog : [
customer @changelog: [
customer.country,
customer.name,
customer.city,
];
order @changelog : [
order @changelog: [
order.report.comment,
order.status
];
}

annotate AdminService.OrderItemNote with {
content @changelog;
ActivationStatus @changelog : [ActivationStatus.name];
content @changelog;
ActivationStatus @changelog: [ActivationStatus.name];
}

annotate AdminService.Customers with {
Expand All @@ -176,5 +190,54 @@ annotate AdminService.Customers with {
}

annotate AdminService.Schools with {
classes @changelog : [classes.name, classes.teacher]
classes @changelog: [
classes.name,
classes.teacher
]
};

annotate AdminService.RootSampleDraft with @changelog: [
ID,
title
] {
title @changelog @title: 'Root Draft Title';
}

annotate AdminService.Level1SampleDraft with @changelog: [
ID,
title,
parent.ID
] {
title @changelog @title: 'Level1 Draft Title';
}

annotate AdminService.Level2SampleDraft with @changelog: [
ID,
title,
parent.parent.ID
] {
title @changelog @title: 'Level2 Draft Title';
};

annotate AdminService.RootSample with @changelog: [
ID,
title
] {
title @changelog @title: 'Root Sample Title';
}

annotate AdminService.Level1Sample with @changelog: [
ID,
title,
parent.ID
] {
title @changelog @title: 'Level1 Sample Title';
}

annotate AdminService.Level2Sample with @changelog: [
ID,
title,
parent.parent.ID
] {
title @changelog @title: 'Level2 Sample Title';
};
Loading