My first thought was very procedural: lets do it do old fashioned way and create a class which will traverse the folder tree of a project and build a list of all the mappings. The class I built looks like this:
import oracle.odi.domain.mapping.Mapping import oracle.odi.domain.mapping.finder.IMappingFinder import oracle.odi.domain.project.OdiProject /** * A class to find all Mapping objects within a project * All folders are traversed recursively and the mappings are returned in a collection. */ class FindMappings { def private allMappings = null def processProject(odiInstance, projectCode) { def odiProjectsList = (odiInstance.getTransactionalEntityManager().getFinder(OdiProject.class).findByCode(projectCode)) odiProjectsList.each { p -> def odiFoldersList = p.getFolders() odiFoldersList.each { f -> /* process interfaces of the current folder */ this.listMappings(odiInstance, p.getCode(), f.getName()) /* Process sub folders recursively */ this.processSubFolder(odiInstance, f, p.getCode()) } } return (allMappings) } def private listMappings(odiInstance, projectCode, folderName) { def mappingList = ((IMappingFinder) odiInstance.getTransactionalEntityManager().getFinder(Mapping.class)).findByProject(projectCode, folderName) if (allMappings == null) { allMappings = mappingList } else { allMappings = allMappings + mappingList } } /* given an odiInstance, folder and project code, we will parse all subfolders (recursively) and print the name of all interfaces found at all levels*/ def private processSubFolder(odiInstance, Folder, projectCode) { def subFolderList = Folder.getSubFolders() if (subFolderList.size() != 0) { subFolderList.each { s -> /* process interfaces of the current folder */ this.listMappings(odiInstance, projectCode, s.getName()) /* Process sub folders recursively */ this.processSubFolder(odiInstance, s, projectCode) } } } }The entry point is the processProject method which we pass a project code. The result is a collection of mappings.
I felt a bit unsatisfied by the result, although it works well I kept thinking there must be a better way to do this. Being fairly new to groovy I have not yet had the opportunity the get to know all the ins and outs of the language, but when I was looking at the documentation for collections I got thinking if I could rewrite the class to a few lines of code, and indeed it is possible.
As I mentioned before there is no findByProject method in the IMappingFinder class, however it does inherit a findAll method from its parent. So we can find all mappings in a repository as follows:
def mappingList = ((IMappingFinder) odiInstance.getTransactionalEntityManager().getFinder(Mapping.class)).findAll()Now we’ve got a list of all mappings in the repository, but I only want the mappings in a specific project. We can select these by using the collection and object methods in combination with closures. The resulting find will look like this:
def mappingList = ((IMappingFinder) odiInstance.getTransactionalEntityManager().getFinder(Mapping.class)).findAll().findAll{w -> w.getProject().getCode() == '<projectCode>'}
This one line of code does the same as the class does I built first.
Slightly rewritten to make it a bit more readable, it could look like this:
def tme = odiInstance.getTransactionalEntityManager() // Shortcut to transaction manager def fm = ((IMappingFinder) tme.getFinder(Mapping.class)) // shorcut to Find Mapping def mappingList = fm.findAll().findAll{w -> w.getProject().getCode() == '<projectCode>'}
We can keep on chaining these commands together like:
// Find all mappings in project DEMO which start with 'DEM' def mappingList = fm.findAll().findAll { w -> w.getProject().getCode() == 'DEMO' }.findAll {w -> w.getName()[0..2] == 'DEM'} // Find all mappings in project DEMO which name contains STG def mappingList = fm.findAll().findAll { w -> w.getProject().getCode() == 'DEMO' }.findAll {w -> w.getName().contains('STG')}