HomeForumSourceResearchGuide
Sign in to contribute to source. how it works
Component composition.RecursiveLoader by barry
expand copy to clipboardexpand
uses Service

data ReqIntf {
	char package[]
	char alias[]
	char semantic[]
	bool isNative
	}

component provides composition.RecursiveLoader requires composition.Search search, Loader loader, NativeLoader nLoader, data.json.JSONParser parser, util.ObjectFile, System system, data.IntUtil iu {
	
	ReqIntf[] getRequiredInterfaces(char com[])
		{
		ReqIntf result[]

		InterfaceSpec ispec[] = loader.load(com).getRequires()

		result = new ReqIntf[ispec.arrayLength]

		for (int i = 0; i < ispec.arrayLength; i++)
			{
			result[i] = new ReqIntf(ispec[i].package, ispec[i].alias, ispec[i].variant, ispec[i].flags == InterfaceSpec.F_NATIVE)
			}
		
		return result
		}
	
	bool isIgnore(String interfaces[], char package[])
		{
		for (int i = 0; i < interfaces.arrayLength; i++)
			{
			if (interfaces[i].string == package) return true
			}
		
		return false
		}
	
	bool isAutoBinding(char package[])
		{
		return isIgnore(system.getAutoBindings(), package)
		}
	
	int loadSupportComponent(char path[], LoadedComponents lc)
		{
		for (int i = 0; i < lc.loadedComponents.arrayLength; i++)
			{
			if (lc.loadedComponents[i].path == path)
				return i
			}
		
		IDC res = loader.load(path)
		
		lc.loadedComponents = new LoadedComponent[](lc.loadedComponents, new LoadedComponent(res, path))
		
		return lc.loadedComponents.arrayLength - 1
		}
	
	void resolveDependency(LoadedComponents lc, int comIndex, char package[], char alias[])
		{
		IDC com = lc.loadedComponents[comIndex].class
		
		char np[] = search.getDefaultComponent(package)
		
		if (np == null) throw new Exception("Failed to find default component to satisfy dependency $package")
		
		int index = loadSupportComponent(np, lc)
		IDC ncom = lc.loadedComponents[index].class
		
		if (com.getComponent(alias) == null)
			{
			com.wire(alias, ncom, alias)
			
			if (lc.graph.arrayLength != 0)
				lc.graph = new char[](lc.graph, ",")
			lc.graph = new char[](lc.graph, "$alias:$comIndex:$index")
			
			loadComponents(index, np, lc, null)
			}
		}
	
	bool loadComponents(int comIndex, char path[], LoadedComponents lc, String ignore[])
		{
		//get the required interfaces of path, and load each one (if not already in lc), then wire up the interfaces
		IDC com = lc.loadedComponents[comIndex].class
		ReqIntf ri[] = getRequiredInterfaces(path)
		
		for (int i = 0; i < ri.arrayLength; i++)
			{
			char pkg[] = ri[i].package
			if (ri[i].semantic.arrayLength != 0) pkg = "$pkg:$(ri[i].semantic)"
			
			if (!ri[i].isNative && !isAutoBinding(ri[i].package) && !isIgnore(ignore, pkg))
				{
				resolveDependency(lc, comIndex, pkg, ri[i].alias)
				}
				else if (ri[i].isNative && !com.isConnected(ri[i].alias))
				{
				IDC ncom = nLoader.load(ri[i].alias)
				com.wire(ri[i].alias, ncom, ri[i].alias)
				}
			}
		
		//service start
		if (com.hasProvides("Service"))
			{
			Service svc = new Service() from com
			svc.start()
			}
		
		return true
		}
	
	LoadedComponents RecursiveLoader:load(char path[], opt String ignoreIntfs[])
		{
		IDC main = loader.load(path)
		LoadedComponents lc = new LoadedComponents(main, "", new LoadedComponent(main, path))
		
		loadComponents(0, path, lc, ignoreIntfs)
		
		//add components to graph
		char cgraph[]
		for (int i = 0; i < lc.loadedComponents.arrayLength; i++)
			{
			if (cgraph.arrayLength != 0)
				cgraph = new char[](cgraph, ",")
			cgraph = new char[](cgraph, lc.loadedComponents[i].path)
			}
		
		lc.graph = new char[](cgraph, "|", lc.graph)
		
		return lc
		}
	
	}
Revision history
To propose a new revision to this entity, use dana source put -uc your/new/version.dn -n composition.RecursiveLoader -m "reason for update" -u yourUsername
Version 1 (this version) by barry
Notes for this version: Standard Library Initialisation