diff options
author | 2025-03-03 16:53:52 +0100 | |
---|---|---|
committer | 2025-03-03 16:54:04 +0100 | |
commit | 0fc9b3ec08ccf9137eddf1490a6a1f2a3a069de3 (patch) | |
tree | 3956ddab2a6b31e939de374c6c522cd1ac360950 | |
parent | 025618795be67e37ccdfef9c6d179d70cdffeaca (diff) |
fixed augment resolving order
Issue-ID: CCSDK-4094
Change-Id: I03d17f7a76266370df2201b2667a2e10b8fa93dd
Signed-off-by: Michael Dürre <michael.duerre@highstreet-technologies.com>
6 files changed, 168 insertions, 71 deletions
diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/uiModels.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/uiModels.ts index c839f1c91..c9f5e8041 100644 --- a/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/uiModels.ts +++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/models/uiModels.ts @@ -209,7 +209,7 @@ export const isViewElementEmpty = (viewElement: ViewElement): viewElement is Vie return viewElement && viewElement.uiType === 'empty'; }; -export const ResolveFunction = Symbol('IsResolved'); +export const ResolveFunction = Symbol('ResolveFunction'); export type ViewSpecification = { id: string; @@ -219,6 +219,7 @@ export type ViewSpecification = { parentView?: string; language: string; ifFeature?: string; + augmentations?: string[]; when?: WhenAST; uses?: (string[]) & { [ResolveFunction]?: (parent: string) => void }; elements: { [name: string]: ViewElement }; diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt-odlux/odlux/apps/configurationApp/src/views/configurationApplication.tsx index c8a518b9c..6280950e4 100644 --- a/sdnr/wt-odlux/odlux/apps/configurationApp/src/views/configurationApplication.tsx +++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/views/configurationApplication.tsx @@ -939,7 +939,6 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp } render() { - console.log('ConfigurationApplication.render()', this.props); return this.props.collectingData || !this.state.viewData ? this.renderCollectingData() : this.props.listSpecification diff --git a/sdnr/wt-odlux/odlux/apps/configurationApp/src/yang/yangParser.ts b/sdnr/wt-odlux/odlux/apps/configurationApp/src/yang/yangParser.ts index 10f12ddf6..ec242dbdf 100644 --- a/sdnr/wt-odlux/odlux/apps/configurationApp/src/yang/yangParser.ts +++ b/sdnr/wt-odlux/odlux/apps/configurationApp/src/yang/yangParser.ts @@ -490,6 +490,34 @@ export class YangParser { return module; } + private calculateExecutionOrder(moduleName: string, visited: Set<string> = new Set()): number { + if (visited.has(moduleName)) { + return 0; + } + visited.add(moduleName); + + const module = this.modules[moduleName]; + const augments = module?.augments || {}; + const augmentPaths = Object.keys(augments); + + if (augmentPaths.length === 0) { + module.executionOrder = 0; + return 0; + } + + const orders = augmentPaths.map((path) => { + const pathParts = path.split('/'); + const lastPart = pathParts[pathParts.length - 1]; + const [ns] = lastPart.split(':'); + const baseModuleOrder = this.calculateExecutionOrder(ns, visited); + return baseModuleOrder + 1; + }); + + const maxOrder = Math.max(...orders); + module.executionOrder = maxOrder; + return maxOrder; + } + public postProcess() { // process all type refs this._typeRefToResolve.forEach(cb => { @@ -497,26 +525,28 @@ export class YangParser { console.warn(error.message); } }); - /** - * This is to fix the issue for sequential execution of modules based on their child and parent relationship - * We are sorting the module object based on their augment status - */ - Object.keys(this.modules) - .map(elem => { - if (this.modules[elem].augments && Object.keys(this.modules[elem].augments).length > 0) { - const { augments, ..._rest } = this.modules[elem]; - const partsOfKeys = Object.keys(augments).map((key) => (key.split('/').length - 1)); - this.modules[elem].executionOrder = Math.max(...partsOfKeys); - } else { - this.modules[elem].executionOrder = 0; - } - }); - // process all augmentations / sort by namespace changes to ensure proper order - Object.keys(this.modules).sort((a, b) => this.modules[a].executionOrder! - this.modules[b].executionOrder!).forEach(modKey => { - const module = this.modules[modKey]; + // process all groupings + this._groupingsToResolve.filter(vs => vs.uses && vs.uses[ResolveFunction]).forEach(vs => { + try { vs.uses![ResolveFunction] !== undefined && vs.uses![ResolveFunction]!('|'); } catch (error) { + console.warn(`Error resolving: [${vs.name}] [${error.message}]`); + } + }); + + // process all augmentations + Object.keys(this.modules).forEach((moduleName) => { + this.calculateExecutionOrder(moduleName); + }); + + const orderedModules = Object.values(this.modules) + .filter((m) => m.executionOrder) + .sort((a, b) => { + return a.executionOrder! - b.executionOrder!; + }); + + orderedModules.forEach((module) => { const augmentKeysWithCounter = Object.keys(module.augments).map((key) => { - const pathParts = splitVPath(key, /(?:(?:([^\/\:]+):)?([^\/]+))/g); // 1 = opt: namespace / 2 = property + const pathParts = splitVPath(key, /(?:(?:([^\/\:]+):)?([^\/]+))/g); // 1 = opt: namespace / 2 = property let nameSpaceChangeCounter = 0; let currentNS = module.name; // init namespace pathParts.forEach(([ns, _]) => { @@ -531,40 +561,96 @@ export class YangParser { }; }); - const augmentKeys = augmentKeysWithCounter - .sort((a, b) => a.nameSpaceChangeCounter > b.nameSpaceChangeCounter ? 1 : a.nameSpaceChangeCounter === b.nameSpaceChangeCounter ? 0 : -1) - .map((a) => a.key); - - augmentKeys.forEach(augKey => { - const augments = module.augments[augKey]; - const viewSpec = this.resolveView(augKey); - if (!viewSpec) console.warn(`Could not find view to augment [${augKey}] in [${module.name}].`); - if (augments && viewSpec) { - augments.forEach(augment => Object.keys(augment.elements).forEach(key => { - const elm = augment.elements[key]; - - const when = elm.when && augment.when - ? { - type: WhenTokenType.AND, - left: elm.when, - right: augment.when, - } - : elm.when || augment.when; - - const ifFeature = elm.ifFeature - ? `(${augment.ifFeature}) and (${elm.ifFeature})` - : augment.ifFeature; - - viewSpec.elements[key] = { - ...augment.elements[key], - when, - ifFeature, - }; - })); + const augmentKeys = augmentKeysWithCounter.sort((a, b) => (a.nameSpaceChangeCounter > b.nameSpaceChangeCounter ? 1 : a.nameSpaceChangeCounter === b.nameSpaceChangeCounter ? 0 : -1)).map((a) => a.key); + + augmentKeys.forEach((augKey) => { + const viewToAugment = this.resolveView(augKey); + const augmentations = module.augments[augKey]; + + if (!viewToAugment) { + console.warn(`Could not find view to augment [${augKey}] from [${module.name}].`); + return; + } + + if (augmentations && viewToAugment) { + augmentations.forEach(({ id }) => { + viewToAugment.augmentations = viewToAugment.augmentations || []; + viewToAugment.augmentations.push(id); + }); } }); }); + // build a map of views with all their augmentation level + const viewsWithNestedAugmentations = new Map<ViewSpecification, number>(); + + // helper function to get maximum augmentation depth + const calculateAugmentationDepth = (view: ViewSpecification): number => { + // Return cached value if already calculated + if (viewsWithNestedAugmentations.has(view)) { + return viewsWithNestedAugmentations.get(view)!; + } + + // Base case: no augmentations + if (!view.augmentations || view.augmentations.length === 0) { + viewsWithNestedAugmentations.set(view, 0); + return 0; + } + + // Get depths of all child augmentations + let maxDepth = 0; + for (const augId of view.augmentations) { + const augView = this.views[+augId]; + for (const nestedAugId in augView.elements || {}) { + const nestedAug = augView.elements[nestedAugId]; + if (isViewElementObjectOrList(nestedAug)) { + const nestedView = this.views[+nestedAug.viewId]; + maxDepth = nestedView ? Math.max(maxDepth, calculateAugmentationDepth(nestedView)) : maxDepth; + } + } + } + + // Add 1 for current level and cache result + const totalDepth = maxDepth + 1; + viewsWithNestedAugmentations.set(view, totalDepth); + return totalDepth; + }; + + // process views from lowest to highest augmentation depth + const viewEntries = Object.entries(this.views.filter((v) => v.augmentations && v.augmentations.length > 0)) + .map(([, view]) => view) + .sort((a, b) => calculateAugmentationDepth(a) - calculateAugmentationDepth(b)); + + for (const view of viewEntries) { + if (!view.augmentations || view.augmentations.length === 0) continue; + + for (const augId of view.augmentations) { + const augmentation = this.views[+augId]; + + // merge elements from augmentation into main view + Object.keys(augmentation.elements).forEach((key) => { + const elm = augmentation.elements[key]; + + const when = + elm.when && augmentation.when + ? { + type: WhenTokenType.AND, + left: elm.when, + right: augmentation.when, + } + : elm.when || augmentation.when; + + const ifFeature = elm.ifFeature ? `(${augmentation.ifFeature}) and (${elm.ifFeature})` : augmentation.ifFeature; + + view.elements[key] = { + ...augmentation.elements[key], + when, + ifFeature, + }; + }); + } + } + // process Identities const traverseIdentity = (identities: Identity[]) => { const result: Identity[] = []; @@ -614,13 +700,6 @@ export class YangParser { } }); - // process all groupings - this._groupingsToResolve.filter(vs => vs.uses && vs.uses[ResolveFunction]).forEach(vs => { - try { vs.uses![ResolveFunction] !== undefined && vs.uses![ResolveFunction]!('|'); } catch (error) { - console.warn(`Error resolving: [${vs.name}] [${error.message}]`); - } - }); - const knownViews: ViewSpecification[] = []; // resolve readOnly const resolveReadOnly = (view: ViewSpecification, parentConfig: boolean) => { @@ -1561,6 +1640,29 @@ export class YangParser { return [element, resultPathParts.slice(0, -1).map(p => `${moduleName !== p.ns ? `${moduleName = p.ns}:` : ''}${p.property}${p.ind || ''}`).join('/')]; } + + private resolveViewElement(name: string, referenceView: ViewSpecification): ViewElement | null { + let element: ViewElement | null = null; + element = referenceView.elements[name]; + + if (element) { + return element; + } + + const augmentViewIds = referenceView.augmentations; + if (augmentViewIds) { + for (let i = 0; i < augmentViewIds.length; ++i) { + const augmentView = this._views[+augmentViewIds[i]]; + if (augmentView) { + element = this.resolveViewElement(name, augmentView); + if (element) break; + } + } + } + return element; + } + + private resolveView(vPath: string) { const vPathParser = /(?:(?:([^\/\[\]\:]+):)?([^\/\[\]]+)(\[[^\]]+\])?)/g; // 1 = opt: namespace / 2 = property / 3 = opt: indexPath let element: ViewElement | null = null; @@ -1572,16 +1674,17 @@ export class YangParser { if (partMatch) { if (element === null) { moduleName = partMatch[1]!; - const rootModule = this._modules[moduleName]; - if (!rootModule) return null; - element = rootModule.elements[`${moduleName}:${partMatch[2]!}`]; + view = Object.values(this.views).find((v) => v.parentView === '0' && v.ns === moduleName) || null; + if (view) { + element = this.resolveViewElement(`${moduleName}:${partMatch[2]!}`, view); + } } else if (isViewElementObjectOrList(element)) { view = this._views[+element.viewId]; if (moduleName !== partMatch[1]) { moduleName = partMatch[1]; - element = view.elements[`${moduleName}:${partMatch[2]}`]; + element = this.resolveViewElement(`${moduleName}:${partMatch[2]}`, view); } else { - element = view.elements[partMatch[2]]; + element = this.resolveViewElement(partMatch[2], view); } } else { return null; diff --git a/sdnr/wt-odlux/odlux/framework/pom.xml b/sdnr/wt-odlux/odlux/framework/pom.xml index bffbc04a7..eaba5d4e9 100644 --- a/sdnr/wt-odlux/odlux/framework/pom.xml +++ b/sdnr/wt-odlux/odlux/framework/pom.xml @@ -39,7 +39,7 @@ <properties> <buildtime>${maven.build.timestamp}</buildtime> <distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion> - <buildno>172.b89e2c2b(23/10/04)</buildno> + <buildno>179.f46d0ef0(25/03/03)</buildno> <odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version> </properties> diff --git a/sdnr/wt-odlux/odlux/framework/src2/main/resources/version.json b/sdnr/wt-odlux/odlux/framework/src2/main/resources/version.json index 1d9af9029..91bd11cd1 100644 --- a/sdnr/wt-odlux/odlux/framework/src2/main/resources/version.json +++ b/sdnr/wt-odlux/odlux/framework/src2/main/resources/version.json @@ -9,11 +9,9 @@ "faultApp":"##odlux.apps.faultApp.buildno##", "helpApp":"##odlux.apps.helpApp.buildno##", "inventoryApp":"##odlux.apps.inventoryApp.buildno##", - "linkCalculationApp":"##odlux.apps.linkCalculationApp.buildno##", "maintenanceApp":"##odlux.apps.maintenanceApp.buildno##", "mediatorApp":"##odlux.apps.mediatorApp.buildno##", - "networkMapApp":"##odlux.apps.networkMapApp.buildno##", "permanceHistoryApp":"##odlux.apps.permanceHistoryApp.buildno##" - + } }
\ No newline at end of file diff --git a/sdnr/wt-odlux/odlux/odlux.properties b/sdnr/wt-odlux/odlux/odlux.properties index c4424acc2..05f314600 100644 --- a/sdnr/wt-odlux/odlux/odlux.properties +++ b/sdnr/wt-odlux/odlux/odlux.properties @@ -1,14 +1,10 @@ odlux.framework.buildno=172.b89e2c2b(23/10/04) -odlux.apps.configurationApp.buildno=172.b89e2c2b(23/10/04) +odlux.apps.configurationApp.buildno=179.f46d0ef0(25/03/03) odlux.apps.connectApp.buildno=172.b89e2c2b(23/10/04) odlux.apps.eventLogApp.buildno=172.b89e2c2b(23/10/04) odlux.apps.faultApp.buildno=172.b89e2c2b(23/10/04) odlux.apps.helpApp.buildno=172.b89e2c2b(23/10/04) odlux.apps.inventoryApp.buildno=172.b89e2c2b(23/10/04) -odlux.apps.linkCalculationApp.buildno=171.5e3c222(22/09/30) odlux.apps.maintenanceApp.buildno=172.b89e2c2b(23/10/04) odlux.apps.mediatorApp.buildno=172.b89e2c2b(23/10/04) -odlux.apps.networkMapApp.buildno=172.b89e2c2b(23/10/04) -odlux.apps.lineOfSightApp.buildno=168.38fd458(22/09/16) odlux.apps.permanceHistoryApp.buildno=81.1c38886(20/12/04) -odlux.apps.siteManagerApp=164.e02f116(22/08/12) |