class CreateFunctionCmd extends BackgroundCommand {

	@Override
	public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
		program = (Program) obj;

		Namespace globalNameSpace = program.getGlobalNamespace();

		int functionsCreated = 0;
		int count = 0;

		monitor.initialize(origEntries.getNumAddresses());

		CodeBlockModel functionModel = null;
		AddressIterator iter = origEntries.getAddresses(true);
		while (iter.hasNext() && !monitor.isCancelled()) {
			monitor.setProgress(++count);
			SourceType tmpSource = source;
			Address origEntry = iter.next();
			String funcName = name;

			try {
				if (origEntry.isExternalAddress()) {
					Symbol oldSym = program.getSymbolTable().getPrimarySymbol(origEntry);
					if (oldSym == null) {
						// skip bad external address
						continue;
					}
					Function extFunc;
					Object symObj = oldSym.getObject();
					if (symObj instanceof Function) {
						extFunc = (Function) symObj;
					}
					else if (symObj instanceof ExternalLocation) {
						extFunc = ((ExternalLocation) symObj).createFunction();
					}
					else {
						Msg.error(this, "Unexpected external symbol object: " + obj.getClass());
						continue;
					}
					if (funcName != null) {
						monitor.setMessage("Function " + funcName);
						extFunc.setName(funcName, source);
					}
				}
				else {
					Namespace nameSpace = globalNameSpace;
					if (funcName == null) {
						Symbol oldSym = program.getSymbolTable().getPrimarySymbol(origEntry);
						if (oldSym != null && oldSym.getSource() != SourceType.DEFAULT) {
							funcName = oldSym.getName();
							tmpSource = oldSym.getSource();
							Namespace oldParentNamespace = oldSym.getParentNamespace();
							// A function can't have another function as its parent.
							if (oldParentNamespace.getSymbol().getSymbolType() != SymbolType.FUNCTION) {
								nameSpace = oldParentNamespace;
							}
						}
						else {
							funcName = SymbolUtilities.getDefaultFunctionName(origEntry);
							tmpSource = SourceType.DEFAULT;
						}
					}

					monitor.setMessage("Function " + funcName);

					if (functionModel == null) {
						functionModel = new PartitionCodeSubModel(program);
					}
// TODO: What if function already exists ??
					if (createFunction(monitor, funcName, functionModel, nameSpace, origEntry,
						origBody, tmpSource)) {
						functionsCreated++;
					}
					else {
						setStatusMsg("Unable to create function at " + origEntry);
					}
				}
			}
			catch (CancelledException e) {
				// TODO: Should we roll-back due to half-baked function bodies??
				// throw new RollbackException("Function creation was canceled");
			}
			catch (Exception e) {
				String errMsg = e.getMessage();
				if (errMsg == null) {
					errMsg = e.toString();
				}
				setStatusMsg(errMsg);
			}
		}

		if (functionsCreated == origEntries.getNumAddresses()) {
			return true;
		}
		return false;
	}

	public  CreateFunctionCmd(String name, AddressSetView entries, AddressSetView body,
			SourceType source, boolean findEntryPoint, boolean recreateFunction);
	public  CreateFunctionCmd(String name, Address entry, AddressSetView body, SourceType source,
			boolean findEntryPoint, boolean recreateFunction);
	public  CreateFunctionCmd(AddressSetView entries, boolean findEntryPoint);
	public  CreateFunctionCmd(AddressSetView entries);
	public  CreateFunctionCmd(AddressSetView entries, SourceType source);
	public  CreateFunctionCmd(String name, Address entry, AddressSetView body, SourceType source);
	  CreateFunctionCmd(Address entry, List<Address> referringThunkAddresses);
	public  CreateFunctionCmd(Address entry);
	public  CreateFunctionCmd(Address entry, boolean findEntryPoint);

}