private boolean applyModel(Program program, ProgramModule root, TaskMonitor monitor)
			throws NotFoundException, NotEmptyException, DuplicateNameException {

		Group group = groupPath.getGroup(program, treeName);
		if (group == null) {
			setStatusMsg(PROGRAM_CHANGED_MESSAGE);
			return true; // ignore this because the program has changed since this command was
		}                // scheduled

		SubroutineBlockModel partitioningModel = null;
		if (partitioningModelName == null) {
			partitioningModel =
				(SubroutineBlockModel) blockModelService.getActiveSubroutineModel(program);
		}
		else {
			partitioningModel = (SubroutineBlockModel) blockModelService
					.getNewModelByName(partitioningModelName, program);
		}
		SubroutineBlockModel baseModel = partitioningModel.getBaseSubroutineModel();

		ProgramModule parent = null;
		GroupPath parentPath = groupPath.getParentPath();
		if (parentPath != null) {
			parent = (ProgramModule) parentPath.getGroup(program, treeName);
			if (parent == null && parentPath.getPathCount() > 1) {
				setStatusMsg(PROGRAM_CHANGED_MESSAGE);
				return true;// ignore this because the program has changed since this command was
			}                // scheduled
		}
		int index = 0;
		if (parent != null) {
			index = parent.getIndex(group.getName());
		}

		try {
			CodeBlockIterator cbi = null;
			ProgramModule module = null;
			if (group instanceof ProgramModule) {
				if (group.equals(root)) {
					cbi = baseModel.getCodeBlocks(monitor);
					module = program.getListing().getRootModule(treeName);
				}
				else {
					module = (ProgramModule) group;
					String name = module.getName();
					if (name.indexOf(NEW_MODULE_SUFFIX) < 0) {
						module.setName(module.getName() + NEW_MODULE_SUFFIX);
					}
					cbi = baseModel.getCodeBlocksContaining(module.getAddressSet(), monitor);
				}
			}
			else {  // group is fragment
				if (parent == null) {
					parent = program.getListing().getRootModule(treeName);
				}
				ProgramFragment fragment = (ProgramFragment) group;
				cbi = baseModel.getCodeBlocksContaining(fragment, monitor);
				module = createModule(parent, fragment.getName() + NEW_MODULE_SUFFIX);
				String newName = module.getName();
				parent.moveChild(newName, index);
			}
			while (cbi.hasNext()) {
				monitor.checkCancelled();
				CodeBlock cb = cbi.next();
				monitor.setMessage("Processing code block @ " + cb.getMinAddress().toString(true));
				ArrayList<CodeBlock> list = new ArrayList<CodeBlock>();
				CodeBlockIterator cbi2 = partitioningModel.getCodeBlocksContaining(cb, monitor);
				while (cbi2.hasNext() && !monitor.isCancelled()) {
					CodeBlock cb2 = cbi2.next();
					list.add(cb2);
				}
				ProgramModule parentModule;
				if (list.size() > 1) {
					parentModule = createModule(module, cb);
				}
				else {
					parentModule = module;
				}
				for (CodeBlock codeBlock : list) {
					monitor.checkCancelled();
					ProgramFragment fragment = createFragment(parentModule, codeBlock);
					moveCodeUnits(fragment, codeBlock, monitor);
				}
			}
		}
		catch (CancelledException e) {
			setStatusMsg("Modularize was cancelled");
			return false;
		}
		cleanTree(root);
		return true;
	}
Constructor
@param path path the source module or fragment where the algorithm
will be applied
@param treeName name of the tree
@param blockModelService service that has the known block models
@param partitioningModelName name of the model to use
Ghidra/Features/Base/src/main/java/ghidra/app/cmd/module/ModuleAlgorithmCmd.java