Skip to content

Commit 955a835

Browse files
Merge pull request #248 from salesforcecli/u/abhinavkumar2/apex_parser_fix
U/abhinavkumar2/apex parser fix
2 parents fd63214 + fed216e commit 955a835

File tree

4 files changed

+308
-80
lines changed

4 files changed

+308
-80
lines changed

src/commands/omnistudio/migration/OmnistudioRelatedObjectMigrationFacade.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,22 @@ export default class OmnistudioRelatedObjectMigrationFacade {
3434
this.allversions = allversions;
3535
this.org = org;
3636
}
37+
public static intializeProject(projectPath?: string): string {
38+
if (projectPath) {
39+
sfProject.create(defaultProjectName, projectPath);
40+
return projectPath + '/' + defaultProjectName;
41+
} else {
42+
sfProject.create(defaultProjectName);
43+
return process.cwd() + '/' + defaultProjectName;
44+
}
45+
}
3746
public migrateAll(migrationResult: MigratedObject[], relatedObjects: string[]): any {
3847
// Start the debug timer
3948
DebugTimer.getInstance().start();
4049

4150
// Declare an array of MigrationTool
4251
const migrationTools: RelatedObjectsMigrate[] = [];
43-
const projectDirectory: string = this.intializeProject();
52+
const projectDirectory: string = OmnistudioRelatedObjectMigrationFacade.intializeProject();
4453
const debugTimer = DebugTimer.getInstance();
4554
debugTimer.start();
4655
// Initialize migration tools based on the relatedObjects parameter
@@ -60,6 +69,7 @@ export default class OmnistudioRelatedObjectMigrationFacade {
6069
migrationTool.migrateRelatedObjects(null, null);
6170
} catch (Error) {
6271
// Log the error
72+
Logger.ux.error(Error.message);
6373
Logger.logger.error(Error.message);
6474
return { migrationResult };
6575
}
@@ -90,13 +100,4 @@ export default class OmnistudioRelatedObjectMigrationFacade {
90100
// Return an instance of ApexClassMigrationTool when implemented
91101
return new ApexMigration(projectPath, this.namespace, this.org);
92102
}
93-
private intializeProject(projectPath?: string): string {
94-
if (projectPath) {
95-
sfProject.create(defaultProjectName, projectPath);
96-
return projectPath + '/' + defaultProjectName;
97-
} else {
98-
sfProject.create(defaultProjectName);
99-
return process.cwd() + '/' + defaultProjectName;
100-
}
101-
}
102103
}

src/migration/related/ApexMigration.ts

Lines changed: 110 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,40 @@
11
import * as fs from 'fs';
2-
// import { RetrieveResult } from '@salesforce/source-deploy-retrieve';
3-
// import { sfcclicommand } from '../../utils/sfcli/commands/sfclicommand';
42
import * as shell from 'shelljs';
53
import { Org } from '@salesforce/core';
6-
import { ApexASTParser, MethodCall } from '../../utils/apex/parser/apexparser';
4+
import {
5+
ApexASTParser,
6+
InsertAfterTokenUpdate,
7+
InterfaceImplements,
8+
MethodCall,
9+
MethodParameter,
10+
ParameterType,
11+
RangeTokenUpdate,
12+
SingleTokenUpdate,
13+
TokenUpdater,
14+
} from '../../utils/apex/parser/apexparser';
715
import { MigrationResult, RelatedObjectsMigrate } from '../interfaces';
816
import { sfProject } from '../../utils/sfcli/project/sfProject';
917
import { fileutil, File } from '../../utils/file/fileutil';
18+
import { Logger } from '../../utils/logger';
1019
import { BaseRelatedObjectMigration } from './BaseRealtedObjectMigration';
20+
1121
const APEXCLASS = 'Apexclass';
1222
const APEX_CLASS_PATH = '/force-app/main/default/classes';
23+
const CALLABLE = 'Callable';
24+
const VLOCITY_OPEN_INTERFACE2 = 'VlocityOpenInterface2';
25+
const VLOCITY_OPEN_INTERFACE = 'VlocityOpenInterface';
26+
1327
export class ApexMigration extends BaseRelatedObjectMigration implements RelatedObjectsMigrate {
28+
private readonly callableInterface: InterfaceImplements;
29+
private readonly vlocityOpenInterface2: InterfaceImplements;
30+
private readonly vlocityOpenInterface: InterfaceImplements;
31+
private updatedNamespace = this.namespace;
32+
public constructor(projectPath: string, namespace: string, org: Org) {
33+
super(projectPath, namespace, org);
34+
this.callableInterface = new InterfaceImplements(CALLABLE, this.namespace);
35+
this.vlocityOpenInterface2 = new InterfaceImplements(VLOCITY_OPEN_INTERFACE2, this.namespace);
36+
this.vlocityOpenInterface = new InterfaceImplements(VLOCITY_OPEN_INTERFACE, this.namespace);
37+
}
1438
public identifyObjects(migrationResults: MigrationResult[]): Promise<JSON[]> {
1539
throw new Error('Method not implemented.');
1640
}
@@ -32,23 +56,98 @@ export class ApexMigration extends BaseRelatedObjectMigration implements Related
3256
files = fileutil.readFilesSync(dir);
3357
for (const file of files) {
3458
if (file.ext !== '.cls') continue;
35-
this.processApexFile(file);
59+
try {
60+
this.processApexFile(file);
61+
} catch (err) {
62+
Logger.logger.error(`Error processing ${file.name}`);
63+
Logger.logger.error(err);
64+
}
3665
}
3766
return files;
3867
}
3968

4069
public processApexFile(file: File): void {
4170
const fileContent = fs.readFileSync(file.location, 'utf8');
42-
const interfaces = new Set<string>(['VlocityOpenInterface', 'VlocityOpenInterface2', 'Callable']);
71+
const interfaces: InterfaceImplements[] = [];
72+
interfaces.push(this.vlocityOpenInterface, this.vlocityOpenInterface2, this.callableInterface);
4373
const methodCalls = new Set<MethodCall>();
44-
methodCalls.add(new MethodCall('process', 'DRGlobal', this.namespace));
45-
methodCalls.add(new MethodCall('processObjectsJSON', 'DRGlobal', this.namespace));
74+
const drNameParameter = new MethodParameter(2, ParameterType.DR_NAME);
75+
const ipNameParameter = new MethodParameter(1, ParameterType.IP_NAME);
76+
methodCalls.add(new MethodCall('DRGlobal', 'process', this.namespace, drNameParameter));
77+
methodCalls.add(new MethodCall('DRGlobal', 'processObjectsJSON', this.namespace, drNameParameter));
78+
methodCalls.add(new MethodCall('DRGlobal', 'processString', this.namespace, drNameParameter));
79+
methodCalls.add(new MethodCall('DRGlobal', 'processFromApex', this.namespace, drNameParameter));
80+
methodCalls.add(
81+
new MethodCall('IntegrationProcedureService', 'runIntegrationService', this.namespace, ipNameParameter)
82+
);
4683
const parser = new ApexASTParser(fileContent, interfaces, methodCalls, this.namespace);
4784
parser.parse();
48-
this.processApexFileforDRCalls(file, fileContent);
85+
const tokenUpdates: TokenUpdater[] = [];
86+
const tokenUpdatesForRemoteCalls = this.processApexFileForRemotecalls(file, parser);
87+
const tokeUpdatesForMethodCalls = this.processApexFileForMethodCalls(file, parser);
88+
const updateMessages: string[] = [];
89+
90+
if (tokenUpdatesForRemoteCalls && tokenUpdatesForRemoteCalls.length > 0) {
91+
tokenUpdates.push(...tokenUpdatesForRemoteCalls);
92+
updateMessages.push('File has been updated to allow remote calls from the Omnistudio components');
93+
}
94+
if (tokeUpdatesForMethodCalls && tokeUpdatesForMethodCalls.length > 0) {
95+
updateMessages.push('File has been updated to allow calls to Omnistudio components');
96+
tokenUpdates.push(...tokeUpdatesForMethodCalls);
97+
}
98+
if (tokenUpdates && tokenUpdates.length > 0) {
99+
fs.writeFileSync(file.location, parser.rewrite(tokenUpdates));
100+
}
101+
const warningMessage: string[] = this.processNonReplacableMethodCalls(file, parser);
102+
Logger.logger.warn(warningMessage);
49103
}
50-
public processApexFileforDRCalls(file: File, fileContent: string): void {
51-
// fileContent = fileContent.replace(this.namespace + '.', 'omnistudio.');
52-
fs.writeFileSync(file.location, fileContent, 'utf-8');
104+
105+
private processApexFileForRemotecalls(file: File, parser: ApexASTParser): TokenUpdater[] {
106+
const implementsInterface = parser.implementsInterfaces;
107+
const tokenUpdates: TokenUpdater[] = [];
108+
if (implementsInterface.has(this.callableInterface)) {
109+
Logger.logger.info('file ${file.name} already implements callable no changes will be applied');
110+
} else if (implementsInterface.has(this.vlocityOpenInterface2)) {
111+
const tokens = implementsInterface.get(this.vlocityOpenInterface2);
112+
tokenUpdates.push(new RangeTokenUpdate(CALLABLE, tokens[0], tokens[1]));
113+
tokenUpdates.push(new InsertAfterTokenUpdate(this.callMethodBody(), parser.classDeclaration));
114+
} else if (implementsInterface.has(this.vlocityOpenInterface)) {
115+
Logger.logger.error('file ${file.name} implements VlocityOpenInterface please implement Callable');
116+
}
117+
return tokenUpdates;
118+
}
119+
120+
private processApexFileForMethodCalls(file: File, parser: ApexASTParser): TokenUpdater[] {
121+
const namespaceChanges = parser.namespaceChanges;
122+
const tokenUpdates: TokenUpdater[] = [];
123+
if (namespaceChanges && namespaceChanges.has(this.namespace)) {
124+
for (const tokenChange of namespaceChanges.get(this.namespace))
125+
tokenUpdates.push(new SingleTokenUpdate(this.updatedNamespace, tokenChange));
126+
}
127+
return tokenUpdates;
128+
}
129+
130+
private processNonReplacableMethodCalls(file: File, parser: ApexASTParser): string[] {
131+
const methodCalls = parser.nonReplacableMethodParameters;
132+
const messages: string[] = [];
133+
if (methodCalls.length === 0) return messages;
134+
for (const methodCall of methodCalls) {
135+
messages.push(
136+
`${file.name} has method call ${methodCall.className} ${methodCall.methodName} for which bundleName could have been updated please check and replace with new value if updated.`
137+
);
138+
}
139+
return messages;
140+
}
141+
private callMethodBody(): string {
142+
return `
143+
public Object call(String action, Map<String,Object> args)
144+
{
145+
Map<String,Object> inputMap = (Map<String,Object>)args.get('input');
146+
Map<String,Object> outMap = (Map<String,Object>)args.get('output');
147+
Map<String,Object> options = (Map<String,Object>)args.get('options');
148+
149+
return invokeMethod(action, inputMap, outMap, options);
150+
}
151+
`;
53152
}
54153
}

0 commit comments

Comments
 (0)