/** * Add this module to the sorted list. If current is the 'root' of a loop, then all elements of * that loops are added before. */ private void addToSortList(List sortedList) { for (Iterator it = loopElements.iterator(); it.hasNext(); ) { ModuleInSort moduleInLoop = (ModuleInSort) it.next(); moduleInLoop.addToSortList(sortedList); } if (!this.isSorted()) { sortedList.add(module); this.isSorted = true; } }
/** * If current module has already been added to list, returns, Otherwise invokes * sortModuleDescriptorsHelp for all dependencies contained within set of moduleDescriptors. Then * finally adds self to list of sorted.<br> * When a loop is detected by a recursive call, the moduleDescriptors are not added immediately * added to the sorted list. They are added as loop dependencies of the root, and will be added to * the sorted list only when the root itself will be added. * * @param current Current module to add to sorted list. * @throws CircularDependencyException */ private void sortModuleDescriptorsHelp(ModuleInSort current, ModuleInSort caller) throws CircularDependencyException { // if already sorted return if (current.isProcessed()) { return; } if (current.checkLoop(caller, circularDepStrategy)) { return; } DependencyDescriptor[] descriptors = current.getDependencies(); Message.debug( "Sort dependencies of : " + current.toString() + " / Number of dependencies = " + descriptors.length); current.setCaller(caller); for (int i = 0; i < descriptors.length; i++) { ModuleInSort child = moduleDescriptors.getModuleDescriptorDependency(descriptors[i]); if (child != null) { sortModuleDescriptorsHelp(child, current); } } current.endOfCall(); Message.debug("Sort done for : " + current.toString()); current.addToSortedListIfRequired(sorted); }
/** * Check if a adding this element as a dependency of caller will introduce a circular dependency. * If it is, all the elements of the loop are flaged as 'loopIntermediateElement', and the * loopElements of this module (which is the root of the loop) is updated. The depStrategy is * invoked on order to report a correct circular loop message. * * @param futurCaller * @param depStrategy * @return true if a loop is detected. */ public boolean checkLoop(ModuleInSort futurCaller, CircularDependencyStrategy depStrategy) { if (caller != null) { LinkedList elemOfLoop = new LinkedList(); elemOfLoop.add(this.module.getModuleRevisionId()); for (ModuleInSort stackEl = futurCaller; stackEl != this; stackEl = stackEl.caller) { elemOfLoop.add(stackEl.module.getModuleRevisionId()); stackEl.isLoopIntermediateElement = true; loopElements.add(stackEl); } elemOfLoop.add(this.module.getModuleRevisionId()); ModuleRevisionId[] mrids = (ModuleRevisionId[]) elemOfLoop.toArray(new ModuleRevisionId[elemOfLoop.size()]); depStrategy.handleCircularDependency(mrids); return true; } else { return false; } }