public with sharing class SharePointFeature extends CloudStorageBase { private static final String SHAREPOINT_API_BASE_URL = 'https://graph.microsoft.com/v1.0'; private static String externalStorage = 'SharePoint'; //List files public override OperationResult listFiles(Map params) { try { Boolean isServiceMode = (Boolean) params.get('isServiceMode'); Boolean myDrive = (Boolean) params.get('myDrive'); Boolean isRootFolder = (Boolean) params.get('isRootFolder'); String folderId = (String) params.get('folderId'); String accessToken = (String) params.get('accessToken'); String level = (String) params.get('level'); //get all sites if (level == 'getAllSite' || level == 'getSites') { if(myDrive == true){ return getAllFollowedSites(accessToken); } else { return getAllSharePointSites(accessToken); } } else if (level == 'getDocumentDrive') { if (String.isBlank(folderId)) { return OperationResult.error('SiteId required '); } return getAllDocumentDrives(accessToken, folderId); } else if (level == 'getFilesInsideDocDrive') { if (String.isBlank(folderId)) { return OperationResult.error('DriveId required'); } return getFilesInsideDrive(accessToken, folderId); } return OperationResult.error('Invalid level provided'); } catch (Exception e) { return OperationResult.error('ERROR: ' + e.getMessage()); } } // all sharepoint sites private OperationResult getAllSharePointSites(String accessToken) { String url = SHAREPOINT_API_BASE_URL + '/sites?search=*'; HttpRequest req = new HttpRequest(); req.setEndpoint(url); req.setMethod('GET'); req.setHeader('Authorization', 'Bearer ' + accessToken); req.setHeader('Accept', 'application/json'); Http http = new Http(); HttpResponse res = http.send(req); if (res.getStatusCode() != 200) return OperationResult.error('Error fetching SharePoint Sites: ' + res.getBody()); Map json = (Map) JSON.deserializeUntyped(res.getBody()); List siteList = (List) json.get('value'); System.debug('siteList: ' + siteList); System.debug('siteList: ' + siteList.size()); List> result = new List>(); System.debug('result: ' + result); for (Object allsites : siteList) { Map site = (Map) allsites; Map row = new Map(); // getAllSharePointSites & getAllFollowedSites row.put('id', (String) site.get('id')); row.put('name', (String) site.get('displayName')); row.put('url', (String) site.get('webUrl')); row.put('type', 'site'); row.put('nextLevel', 'getDocumentDrive'); row.put('disableCheck', 'true'); result.add(row); } return OperationResult.success(result); } //get the followed sites private OperationResult getAllFollowedSites(String accessToken) { String url = SHAREPOINT_API_BASE_URL + '/me/followedSites'; HttpRequest req = new HttpRequest(); req.setEndpoint(url); req.setMethod('GET'); req.setHeader('Authorization', 'Bearer ' + accessToken); req.setHeader('Accept', 'application/json'); Http http = new Http(); HttpResponse res = http.send(req); if (res.getStatusCode() != 200) { return OperationResult.error( 'Error fetching followed SharePoint Sites: ' + res.getBody() ); } Map resbody = (Map) JSON.deserializeUntyped(res.getBody()); List siteList = (List) resbody.get('value'); List> result = new List>(); System.debug('result>>>' + result); for (Object obj : siteList) { Map s = (Map) obj; Map row = new Map(); row.put('id', (String) s.get('id')); row.put('name', (String) s.get('displayName')); row.put('url', (String) s.get('webUrl')); row.put('type', 'followedSite'); row.put('nextLevel', 'getDocumentDrive'); row.put('disableCheck', 'true'); result.add(row); } return OperationResult.success(result); } // all doc drive private OperationResult getAllDocumentDrives(String accessToken, String siteId) { String url = SHAREPOINT_API_BASE_URL + '/sites/' + siteId + '/drives'; HttpRequest req = new HttpRequest(); req.setEndpoint(url); req.setMethod('GET'); req.setHeader('Authorization', 'Bearer ' + accessToken); req.setHeader('Accept', 'application/json'); Http http = new Http(); HttpResponse res = http.send(req); if (res.getStatusCode() != 200) return OperationResult.error('Error fetching drives: ' + res.getBody()); Map json = (Map) JSON.deserializeUntyped(res.getBody()); List driveList = (List) json.get('value'); List> result = new List>(); for (Object alldrives : driveList) { Map drive = (Map) alldrives; Map row = new Map(); // getAllDocumentDrives // row.put('id', (String) drive.get('id')); //change row.put('id', drive.get('id') + ':' + siteId); row.put('name', (String) drive.get('name')); row.put('driveType', (String) drive.get('driveType')); row.put('type', 'drive'); row.put('nextLevel', 'getFilesInsideDocDrive'); row.put('disableCheck', 'true'); result.add(row); } return OperationResult.success(result); } private OperationResult getFilesInsideDrive(String accessToken, String compositeId) { List parts = compositeId.split(':'); String driveId = parts[0]; String siteId = parts.size() > 1 ? parts[1] : null; String itemId = parts.size() > 2 ? parts[2] : null; String url; // ROOT of document library if (itemId == null) { url = SHAREPOINT_API_BASE_URL + '/drives/' + driveId + '/root/children'; } // INSIDE a folder else { url = SHAREPOINT_API_BASE_URL + '/drives/' + driveId + '/items/' + itemId + '/children'; } HttpRequest req = new HttpRequest(); req.setEndpoint(url); req.setMethod('GET'); req.setHeader('Authorization', 'Bearer ' + accessToken); req.setHeader('Accept', 'application/json'); Http http = new Http(); HttpResponse res = http.send(req); if (res.getStatusCode() != 200) { return OperationResult.error('Error getting drive items: ' + res.getBody()); } Map json = (Map) JSON.deserializeUntyped(res.getBody()); List items = (List) json.get('value'); List> result = new List>(); for (Object obj : items) { Map f = (Map) obj; Map row = new Map(); // Preserve composite ID for next navigation // row.put('id', driveId + ':' + (String) f.get('id')); //changes row.put('id', driveId + ':' + siteId + ':' + (String) f.get('id')); // changes // NORMALIZED ID (used by download/delete/rename) // String normalizedFileId = driveId + ':' + (String) f.get('id'); // row.put('id', normalizedFileId); // String itemGraphId = (String) f.get('id'); // NAVIGATION ID (USED FOR FOLDER CLICK / BACK / BREADCRUMB) // String navigationId = driveId + ':' + siteId + ':' + itemGraphId; // row.put('id', navigationId); // OPERATION ID (USED FOR DOWNLOAD / DELETE / RENAME) // String normalizedId = driveId + ':' + itemGraphId; // row.put('normalizedId', normalizedId); row.put('name', (String) f.get('name')); row.put('openUrl', (String) f.get('webUrl')); row.put('createdTime', (String) f.get('createdDateTime')); row.put('disableCheck', 'false'); row.put('type', f.containsKey('folder') ? 'folder' : 'file'); row.put('nextLevel', 'getFilesInsideDocDrive'); if (f.containsKey('folder')) { row.put('mimeType', 'doctype:folder'); } else { Map fileObj = (Map) f.get('file'); row.put('mimeType', fileObj != null && fileObj.containsKey('mimeType') ? (String) fileObj.get('mimeType') : 'doctype:unknown' ); } Map createdBy = (Map) f.get('createdBy'); if (createdBy != null) { Map userMap = (Map) createdBy.get('user'); row.put('displayName', userMap != null ? (String) userMap.get('displayName') : '-'); } result.add(row); } return OperationResult.success(result); } //adding method to linkfiles // change custom object -- linkedFolder public override OperationResult linkFiles(String recordId) { List> resultFolders = new List>(); try { List linkedFolders = [ SELECT Id,Name,CreatedDate,CreatedBy.Name,HIC_FilesME__External_Folder_ID__c, HIC_FilesME__Folder_Name__c, HIC_FilesME__Folder_URL__c, HIC_FilesME__Storage_Provider__c, HIC_FilesME__Access_Level__c FROM HIC_FilesME__Linked_Folder__c WHERE HIC_FilesME__Linked_Record__c = :recordId AND HIC_FilesME__Is_Active__c = true ]; for (HIC_FilesME__Linked_Folder__c folder : linkedFolders) { Map folderData = new Map(); folderData.put('id', folder.HIC_FilesME__External_Folder_ID__c); folderData.put('recordId', folder.Id); folderData.put('name', folder.HIC_FilesME__Folder_Name__c); folderData.put('externalStorageType', folder.HIC_FilesME__Storage_Provider__c); folderData.put('accessLevel', folder.HIC_FilesME__Access_Level__c); folderData.put('createdTime', String.valueOf(folder.CreatedDate)); folderData.put('createdBy', folder.CreatedBy != null ? folder.CreatedBy.Name : '-'); folderData.put('url', folder.HIC_FilesME__Folder_URL__c); resultFolders.add(folderData); } return OperationResult.success(resultFolders); } catch (Exception e) {FME_Logger.error(e.getMessage(),'LinkedFolderFeature' + e.getLineNumber(),'linkFiles'); return OperationResult.error('Failed to fetch linked folders. ' + e.getMessage()); } } // change custom object -- linkedFolder public override OperationResult toLinkFiles(String recordId,String folderDetails,String providerType) { try { System.debug('providerType >>>> ' + providerType); System.debug('recordId >>>> ' + recordId); System.debug('JSON.deserializeUntyped folderDetails >>>> ' + JSON.deserializeUntyped(folderDetails)); Map folderMap = (Map) JSON.deserializeUntyped(folderDetails); HIC_FilesME__Linked_Folder__c linkedFolder = new HIC_FilesME__Linked_Folder__c(); linkedFolder.HIC_FilesME__Linked_Record__c = recordId; linkedFolder.HIC_FilesME__External_Folder_ID__c = (String) folderMap.get('id'); linkedFolder.HIC_FilesME__Folder_Name__c = (String) folderMap.get('name'); //add linkedFolder.HIC_FilesME__Created__c = UserInfo.getUserId(); linkedFolder.HIC_FilesME__Created_Date__c = System.now(); linkedFolder.HIC_FilesME__Folder_URL__c = (String) folderMap.get('url'); linkedFolder.HIC_FilesME__Storage_Provider__c = providerType; // linkedFolder.HIC_FilesME__Access_Level__c = (String) folderMap.get('accessLevel'); linkedFolder.HIC_FilesME__Is_Active__c = true; String key = providerType +' '+ recordId +' '+ (String) folderMap.get('id'); linkedFolder.HIC_FilesME__Key__c = key; upsert linkedFolder HIC_FilesME__Key__c; System.debug('linkedFolder >>>> ' + linkedFolder); return OperationResult.success(linkedFolder); } catch (Exception e) { FME_Logger.error(e.getMessage(),'LinkedFolderFeature' + e.getLineNumber(),'toLinkFiles' ); return OperationResult.error('Error linking folder: ' + e.getMessage()); } } //to create folder public override OperationResult createFolder(Map params) { Map resultMap = new Map(); OperationResult result; try { String parentFolderId = (String) params.get('parentFolderId'); Boolean isServiceMode = (Boolean) params.get('isServiceMode'); String folderName = (String) params.get('folderName'); String userId = (String) SalesforceEnvironmentUtil.getUserId(); String accessToken = (String) params.get('accessToken'); List ids = parentFolderId != null ? parentFolderId.split(':') : null; String driveId = ids != null ? ids[0] : null; String itemId = (ids != null && ids.size() > 2) ? ids[2] : null; if (String.isBlank(driveId)) { return OperationResult.error('DriveId is required to create folder in SharePoint'); } String endpoint; if (String.isBlank(itemId)) { endpoint = SHAREPOINT_API_BASE_URL + '/drives/' + driveId + '/root/children'; } else { endpoint = SHAREPOINT_API_BASE_URL + '/drives/' + driveId + '/items/' + itemId + '/children'; } String folderMetadata = JSON.serialize(new Map{ 'name' => folderName, 'folder' => new Map(), '@microsoft.graph.conflictBehavior' => 'rename' }); Map headers = new Map{ 'Authorization' => 'Bearer ' + accessToken, 'Content-Type' => 'application/json' }; HttpResponse res = CloudStorageUtlilty.makeCallout(folderMetadata,endpoint,headers,'POST'); if (res.getStatusCode() == 201 || res.getStatusCode() == 200) { resultMap = (Map) JSON.deserializeUntyped(res.getBody()); resultMap.put('code', '200'); result = OperationResult.success(resultMap); } else { System.debug('SharePoint create folder failed: ' + res.getBody()); result = OperationResult.error(res.getBody()); } } catch (Exception e) { FME_Logger.error( e.getMessage(), 'SharePointFeature.createFolder line ' + e.getLineNumber(), 'createFolder' ); result = OperationResult.error('Error creating SharePoint folder: ' + e.getMessage()); } System.debug('resultMap >>> ' + resultMap); System.debug('result >>> ' + result); return result; } //to delete file or folder public override OperationResult deleteFile(Map params) { try { String fileId = (String) params.get('fileId'); String userId = SalesforceEnvironmentUtil.getUserId(); Boolean isServiceMode = (Boolean) params.get('isServiceMode'); String accessToken = (String) params.get('accessToken'); System.debug('SharePoint delete >>> fileId=' + fileId); if (String.isBlank(fileId)) { return OperationResult.error('FileId is required'); } // Parse the complex SharePoint ID format // Format: driveId:siteId:itemId List ids = fileId.split(':'); if (ids.size() < 3) { return OperationResult.error('Invalid SharePoint fileId format. Expected format: driveId:siteId:itemId'); } String driveId = ids[0]; String siteId = ids[1]; String itemId = ids[2]; // Build the correct endpoint for SharePoint String endpoint = SHAREPOINT_API_BASE_URL + '/drives/' + driveId + '/items/' + itemId; System.debug('SharePoint delete endpoint >>> ' + endpoint); // Headers Map headers = new Map(); headers.put('Authorization', 'Bearer ' + accessToken); HttpResponse res = CloudStorageUtlilty.makeCallout(null,endpoint,headers,'DELETE'); System.debug('Delete response code >>> ' + res.getStatusCode()); if (res.getStatusCode() == 204) { return OperationResult.success('Deleted successfully'); } else { return OperationResult.error(res.getBody()); } } catch (Exception e) { FME_Logger.error(e.getMessage(),'SharePointFeature.deleteFile line ' + e.getLineNumber(),'deleteFile'); return OperationResult.error( 'Error deleting SharePoint file: ' + e.getMessage() ); } } //rename folder -- Done public override OperationResult renameFile(Map params) { OperationResult result; Map accessTokenMap = new Map(); try { String fileId = (String) params.get('fileId'); Boolean isServiceMode = (Boolean) params.get('isServiceMode'); String newFileName = (String) params.get('newFileName'); String accessToken = (String) params.get('accessToken'); if (String.isBlank(fileId) || String.isBlank(newFileName)) { return OperationResult.error('FileId and newFileName are required'); } // Parse the complex SharePoint ID format // Format: driveId:siteId:itemId List ids = fileId.split(':'); if (ids.size() < 3) { return OperationResult.error('Invalid SharePoint fileId format. Expected format: driveId:siteId:itemId'); } String driveId = ids[0]; String siteId = ids[1]; String itemId = ids[2]; String url = SHAREPOINT_API_BASE_URL + '/drives/' + driveId + '/items/' + itemId; System.debug('SharePoint rename url >>> ' + url); System.debug('New file name >>> ' + newFileName); String body = JSON.serialize(new Map{ 'name' => newFileName }); Map headers = new Map{ 'Authorization' => 'Bearer ' + accessToken, 'Content-Type' => 'application/json' }; HttpResponse res = CloudStorageUtlilty.makeCallout(body, url, headers, 'PATCH'); System.debug('Rename response code >>> ' + res.getStatusCode()); if (res.getStatusCode() == 200) { result = OperationResult.success(res.getBody()); } else { result = OperationResult.error(res.getBody()); } } catch (Exception e) { FME_Logger.error(e.getMessage(),'SharePointFeature.renameFile line ' + e.getLineNumber(),'renameFile'); result = OperationResult.error('Error renaming SharePoint file: ' + e.getMessage()); } System.debug('SharePoint rename result >>> ' + result); return result; } //to share done public override OperationResult moveFileAndFolder(Map params) { OperationResult result; try { String fileId = (String) params.get('fileId'); Boolean isServiceMode= (Boolean) params.get('isServiceMode'); String newFolderId = (String) params.get('newFolderId'); String oldFolderId = (String) params.get('oldFolderId'); String accessToken = (String) params.get('accessToken'); String userId = (String) SalesforceEnvironmentUtil.getUserId(); System.debug('SharePoint move >>> fileId=' + fileId); System.debug('SharePoint move >>> newFolderId=' + newFolderId); System.debug('SharePoint move >>> oldFolderId=' + oldFolderId); List fileIds = fileId.split(':'); if (fileIds.size() < 3) { return OperationResult.error( 'Invalid SharePoint fileId format' ); } String driveId = fileIds[0]; String siteId = fileIds[1]; String itemId = fileIds[2]; List newFolderParts = newFolderId.split(':'); String newParentId = newFolderParts.size() > 2 ? newFolderParts[2] : null; String endpoint =SHAREPOINT_API_BASE_URL + '/drives/' + driveId + '/items/' + itemId; Map bodyMap = new Map(); if (newParentId != null) { bodyMap.put('parentReference',new Map{ 'id' => newParentId } ); } String body = JSON.serialize(bodyMap); Map headers = new Map{ 'Authorization' => 'Bearer ' + accessToken, 'Content-Type' => 'application/json' }; HttpResponse res = CloudStorageUtlilty.makeCallout(body,endpoint,headers,'PATCH'); if (res.getStatusCode() == 200) { System.debug('SharePoint move success'); result = OperationResult.success(res.getBody()); } else { System.debug('SharePoint move failed: ' + res.getBody()); result = OperationResult.error(res.getBody()); } } catch (Exception e) { FME_Logger.error(e.getMessage(),'SharePointFeature ' + e.getLineNumber(),'moveFileAndFolder'); result = OperationResult.error('Error moving SharePoint item: ' + e.getMessage()); } return result; } public override OperationResult downloadFile(Map params) { // System.debug('SharePointFeature.downloadFile'); // System.debug('isServiceMode: ' + isServiceMode); // System.debug('userId: ' + userId); // System.debug('fileId: ' + fileId); OperationResult result; try { Blob fileBlob = fetchFileAndConvertToBase64(params); System.debug('fileBlob: ' + fileBlob); if (fileBlob != null) { result = OperationResult.success(EncodingUtil.base64Encode(fileBlob)); System.debug('SharePoint file downloaded successfully.'); } else { result = OperationResult.error('Failed to download SharePoint file. fileId: ' ); } } catch (Exception e) { result = OperationResult.error('Error downloading SharePoint file: ' + e.getMessage()); FME_Logger.error(e.getMessage(),'SharePointFeature' + e.getLineNumber(),'downloadFile'); } return result; } public static Blob fetchFileAndConvertToBase64(Map params) { Blob fileBlob; try { Boolean isServiceMode = (Boolean) params.get('isServiceMode'); String fileId = (String) params.get('fileId'); String fileName = (String) params.get('fileName'); String accessToken = (String) params.get('accessToken'); String userId = (String) SalesforceEnvironmentUtil.getUserId(); System.debug('isServiceMode: ' + isServiceMode); System.debug('fileId: ' + fileId); System.debug('fileName: ' + fileName); System.debug('accessToken: ' + accessToken); Map credentials = CloudStorageUtlilty.getAccessToken(isServiceMode, userId, externalStorage); // String accessToken = (String) credentials.get('ACCESS_TOKEN'); String refreshToken = (String) credentials.get('REFRESH_TOKEN'); // Parse the 3-part SharePoint ID correctly // Format: driveId:siteId:itemId List parts = fileId.split(':'); if (parts.size() < 3) { System.debug('Invalid SharePoint fileId format. Expected: driveId:siteId:itemId'); return null; } String driveId = parts[0]; String siteId = parts[1]; String itemId = parts[2]; Map headers = new Map{ 'Authorization' => 'Bearer ' + accessToken }; String metaUrl = 'https://graph.microsoft.com/v1.0/drives/' + driveId + '/items/' + itemId + '?select=@microsoft.graph.downloadUrl'; System.debug('SharePoint download URL request: ' + metaUrl); HttpResponse metaRes = CloudStorageUtlilty.makeCallout(null, metaUrl, headers, 'GET'); // 4. Handle token refresh if needed if (metaRes.getStatusCode() == 401) { SharePointAuth auth = new SharePointAuth(); String newAccessToken = auth.refreshAccessToken(refreshToken); CloudStorageUtlilty.updateAccessToken(isServiceMode, userId, newAccessToken, externalStorage); headers.put('Authorization', 'Bearer ' + newAccessToken); metaRes = CloudStorageUtlilty.makeCallout(null, metaUrl, headers, 'GET'); } if (metaRes.getStatusCode() != 200) { System.debug('Failed to fetch SharePoint download URL. Status: ' + metaRes.getStatusCode() + ' Body: ' + metaRes.getBody()); return null; } Map meta = (Map) JSON.deserializeUntyped(metaRes.getBody()); String downloadUrl = (String) meta.get('@microsoft.graph.downloadUrl'); if (String.isBlank(downloadUrl)) { System.debug('No download URL returned from SharePoint'); return null; } System.debug('SharePoint download URL obtained successfully'); HttpResponse fileRes = CloudStorageUtlilty.makeCallout(null, downloadUrl, null, 'GET'); if (fileRes.getStatusCode() == 200) { fileBlob = fileRes.getBodyAsBlob(); System.debug('SharePoint file downloaded successfully. Size: ' + fileBlob.size() + ' bytes'); } else { System.debug('SharePoint file download failed. Status: ' + fileRes.getStatusCode() + ' Body: ' + fileRes.getBody()); } } catch (Exception e) { System.debug('Error in SharePoint fetchFileAndConvertToBase64: ' + e.getMessage() + ' | Line: ' + e.getLineNumber()); } return fileBlob; } public override OperationResult emailFile(Map params) { OperationResult result; try { //maildetails Map mailDetails =(Map) JSON.deserializeUntyped(JSON.serialize(params.get('mailDetails'))); String fileId = (String) params.get('fileId'); String fileName = (String) params.get('fileName'); String mimeType = (String) params.get('toSendFileNameMimeType'); String senderId = (String) mailDetails.get('fromUser'); String toUser = (String) mailDetails.get('toUser'); String ccUser = (String) mailDetails.get('ccUser'); String bccUser = (String) mailDetails.get('bccUser'); String subject = (String) mailDetails.get('subject'); String body = (String) mailDetails.get('body'); Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); // Required mail.setToAddresses(new List{ toUser }); // Optional if (String.isNotBlank(ccUser)) mail.setCcAddresses(new List{ ccUser }); if (String.isNotBlank(bccUser)) mail.setBccAddresses(new List{ bccUser }); mail.setSubject(subject); // Remove HTML tags safely mail.setPlainTextBody(body != null ? body.replaceAll('<[^>]+>', '') : ''); if (String.isNotBlank(senderId) && senderId.startsWith('0D2')) { mail.setOrgWideEmailAddressId(senderId); } Map downloadParams = new Map(params); downloadParams.put('fileId', fileId); downloadParams.put('fileName', fileName); OperationResult op = downloadFile(downloadParams); if (op != null && op.data != null) { Blob fileBlob = EncodingUtil.base64Decode((String) op.data); Messaging.EmailFileAttachment attachment = new Messaging.EmailFileAttachment(); attachment.setFileName(fileName); attachment.setBody(fileBlob); attachment.setContentType(String.isNotBlank(mimeType) ? mimeType: 'application/octet-stream'); mail.setFileAttachments(new List{ attachment }); } Messaging.SendEmailResult[] results = Messaging.sendEmail( new List{ mail }); if (!results.isEmpty() && results[0].isSuccess()) { result = OperationResult.success(null); System.debug(' Email sent successfully'); } else { String errMsg = (!results.isEmpty() && results[0].getErrors().size() > 0)? results[0].getErrors()[0].getMessage(): 'Unknown send failure'; result = OperationResult.error(errMsg); } } catch (Exception e) { FME_Logger.error(e.getMessage(),'EmailFeature ' + e.getLineNumber(),'emailFile'); result = OperationResult.error('Error sending email: ' + e.getMessage()); } System.debug('result:' + result); return result; } //unlinkfile public override OperationResult unlinkFiles(String recordId, String filesId, Boolean deleteFromDrive) { System.debug('recordId >>>> ' + recordId); System.debug('filesId >>>> ' + filesId); System.debug('deleteFromDrive >>>> ' + deleteFromDrive); OperationResult result; try { List fileLinks = [SELECT Id FROM HIC_FilesME__Linked_Folder__c WHERE HIC_FilesME__Linked_Record__c = :recordId AND HIC_FilesME__External_Folder_ID__c = :filesId]; if (fileLinks.size() > 0) { delete fileLinks; // if (deleteFromDrive) { // deleteFile(filesId, true, null); // } result = OperationResult.success(null); } else { result = OperationResult.error('No record found'); } } catch (Exception e) { result = OperationResult.error('Error unlinking file: ' + e.getMessage()); FME_Logger.error(e.getMessage(), 'GoogleDriveFeature' + e.getLineNumber(), 'unlinkFiles'); } return result; } }