Commits

T. Michael Keesey  committed 406166d

Partway through updating code and fixing compile errors.

  • Participants
  • Parent commits 0af1dff

Comments (0)

Files changed (80)

File src/org/namesonnodes/controls/context/GetNewickString.as

 
 		public function redo():*
 		{
-			baseContext.merge(newickContext);
+			baseContext.mergeWith(newickContext);
 		}
 
 		public function undo():*
 											 popUpCommand_errorHandler);
 			newickContext = popUpCommand.result as Context;
 			baseContextBackup = baseContext.clone();
-			baseContext.merge(newickContext);
+			baseContext.mergeWith(newickContext);
 			popUpCommand = null;
 			setResult(baseContext);
 		}

File src/org/namesonnodes/controls/definitions/MathElementTranslator.as

  */
 package org.namesonnodes.controls.definitions
 {
-	import mx.collections.ArrayCollection;
-	import mx.utils.object_proxy;
 	import asmathema.collections.sets.Set;
 	import asmathema.functions.MathFunction;
 	import asmathema.mathML.MathML;
 	import asmathema.mathML.MathMLError;
 	import asmathema.mathML.evaluators.EvaluationError;
 	import asmathema.mathML.presenters.MathMLPresenter;
+	
+	import mx.collections.ArrayCollection;
+	import mx.utils.object_proxy;
+	
 	import org.namesonnodes.math.SymbolPresentation;
 	import org.namesonnodes.math.Taxon;
 	import org.namesonnodes.models.Context;
-	import org.namesonnodes.models.Declaration;
-	import org.namesonnodes.models.Symbol;
+	import org.namesonnodes.models.NameEntry;
 	import org.namesonnodes.models.definitions.Definition;
 	import org.namesonnodes.models.definitions.elements.ApplyElement;
 	import org.namesonnodes.models.definitions.elements.ConstantElement;
-	import org.namesonnodes.models.definitions.elements.DeclarationElement;
 	import org.namesonnodes.models.definitions.elements.ListElement;
 	import org.namesonnodes.models.definitions.elements.MathElement;
 	import org.namesonnodes.models.definitions.elements.MathElementContainer;
+	import org.namesonnodes.models.definitions.elements.NameElement;
 	import org.namesonnodes.models.definitions.elements.OperatorElement;
 	import org.namesonnodes.models.definitions.elements.OtherwiseElement;
 	import org.namesonnodes.models.definitions.elements.PieceElement;
 		private function csymbol(content:XML):MathElement
 		{
 			default xml namespace=MathML.NAMESPACE.uri;
-			const declaration:Declaration =
-				context.names.getDeclaration(content.@definitionURL);
-			if (declaration)
-				return new DeclarationElement(declaration);
-			const symbol:Symbol =
-				new Symbol(content.@definitionURL,
-						   context.symbolPresentation.getPresentation(content.@definitionURL));
+			const entry:NameEntry =
+				context.names.getEntryForDefinitionURL(content.@definitionURL);
+			if (entry)
+				return new NameElement(entry);
 			const value:Object = context.evaluator.evaluate(content);
-			var toolTip:String = symbol.presentationText;
 			var valueType:ValueType;
 			if (value is Taxon)
-			{
 				valueType = ValueType.fromClass(Set);
-				toolTip += " (taxon)";
-			}
 			else
-				valueType = getValueType(content);
-			return constant(symbol.shortContent, toolTip, valueType);
+				valueType = getValueType(content, value);
+			content = <csymbol xmlns={MathML.NAMESPACE} definitionURL={content.@definitionURL} type={valueType.name}/>;
+			return constant(content, "Constant value: " + value + ".", valueType);
 		}
 
-		private function getValueType(content:XML):ValueType
+		private function getValueType(content:XML, value:* = undefined):ValueType
 		{
 			var valueType:ValueType;
 			if (content.@type.length() == 1)
 				valueType = ValueType.fromName(content.@type);
 			if (valueType == null)
 				valueType =
-					ValueType.fromValue(context.evaluator.evaluate(content));
+					ValueType.fromValue((value === undefined) ? context.evaluator.evaluate(content) : value);
 			if (valueType == null)
 				return ValueType.fromClass(Object);
 			return valueType;

File src/org/namesonnodes/controls/definitions/SetDefinition.as

 package org.namesonnodes.controls.definitions
 {
 	import org.namesonnodes.flow.HistoryItem;
-	import org.namesonnodes.models.Declaration;
+	
+	import org.namesonnodes.models.NameEntry;
 	import org.namesonnodes.models.definitions.Definition;
 
 	public final class SetDefinition implements HistoryItem
 	{
-		public function SetDefinition(declaration:Declaration,
-									  newDef:Definition)
+		public function SetDefinition(entry:NameEntry, newDef:Definition)
 		{
 			super();
-			this.declaration = declaration;
+			this.entry = entry;
 			this.newDef = newDef;
 		}
-		private var declaration:Declaration;
+		private var entry:NameEntry;
 		private var newDef:Definition;
 		private var oldDef:Definition;
 
 		public function execute():*
 		{
-			oldDef = declaration.definition;
-			declaration.definition = newDef;
+			oldDef = entry.definition;
+			entry.definition = newDef;
 		}
 
 		public function get name():String
 
 		public function redo():*
 		{
-			declaration.definition = newDef;
+			entry.definition = newDef;
 		}
 
 		public function undo():*
 		{
-			declaration.definition = oldDef;
+			entry.definition = oldDef;
 		}
 	}
 }

File src/org/namesonnodes/controls/files/SelectDeclarationsPanel.mxml

 			}
 			import org.namesonnodes.math.Taxon;
 			import org.namesonnodes.math.TaxonomicUnion;
-			import org.namesonnodes.models.Declaration;
+			
 			protected function selectAllButton_clickHandler(event:MouseEvent):void
 			{
 				const unitBuilder:FiniteSetBuilder = new HashSetBuilder();
 			{
 				selectionManager.clear();
 			}
-			import org.namesonnodes.ui.names.DeclarationRenderer;
+			import org.namesonnodes.ui.names.NameRenderer;
 			import org.namesonnodes.ui.skins.ControlButtonSkin;
 			import asmathema.collections.lists.List;
 			import asmathema.collections.sets.FiniteSetBuilder;
 
 	<s:DataGroup id="dataGroup"
 				 dataProvider="{declarations}"
-				 itemRenderer="{DeclarationRenderer.factory}"
+				 itemRenderer="{NameRenderer.factory}"
 				 mouseDown="dataGroup_mouseDownHandler(event)">
 		<s:layout>
 			

File src/org/namesonnodes/controls/files/graphML/GraphMLReader.as

 	import org.namesonnodes.math.Taxon;
 	import org.namesonnodes.math.TaxonomicUnit;
 	import org.namesonnodes.models.Context;
-	import org.namesonnodes.models.Declaration;
 	import org.namesonnodes.models.FileFormat;
-	import org.namesonnodes.models.Symbol;
+	import org.namesonnodes.models.NameEntry;
 	import org.namesonnodes.models.definitions.TaxonDefinition;
+	import org.namesonnodes.models.definitions.elements.NameElement;
 
 	[Event(name="progress", type="flash.events.ProgressEvent")]
 	public final class GraphMLReader extends AbstractOperation
 			{
 				var value:TaxonomicUnit = idTable.getNode(id) as TaxonomicUnit;
 				if (context.nodes.graphSolver.nodes.includes(value))
-					context.names.addDeclaration(new Declaration(new Symbol(new URI("#" + escape(id)),
-																								 <mi xmlns={MathML.NAMESPACE}>{id}</mi>),
-																								 new TaxonDefinition(idTable.getNode(id) as Taxon),
-																								 true));
+				{
+					var entry:NameEntry =
+						new NameEntry(new TaxonDefinition(value));
+					entry.addPresentation(<mi xmlns={MathML.NAMESPACE}>{id}</mi>);
+					context.names.addEntry(entry);
+				}
 			}
 		}
 

File src/org/namesonnodes/controls/files/mathML/MathMLReader.as

 	import asmathema.mathML.MathMLError;
 	import org.namesonnodes.controls.files.FileReader;
 	import org.namesonnodes.flow.AbstractAsyncManager;
+	import org.namesonnodes.flow.AsyncCommand;
 	import org.namesonnodes.flow.ProgressOperation;
 	import org.namesonnodes.flow.events.OperationEvent;
 	import org.namesonnodes.math.SymbolDefinitionURL;
 		{
 			super();
 		}
+		private var _progressOperations:Vector.<ProgressOperation> =
+			new Vector.<ProgressOperation>();
 		private var context:Context;
-		private var graphBuilder:GraphBuilder;
-		private var readEdges:ReadEdges;
-		private var readNames:ReadNames;
-		private var readNodes:ReadNodes;
 		private var xml:XML;
 
 		public function get format():String
 				xml = new XML(data.readUTFBytes(data.length));
 				if (xml.name() != MathML.MATH)
 					throw new MathMLError(xml, "Expected <math> element.");
-				const csymbols:XMLList =
+				const csymbolPG:XMLList =
 					xml.descendants(MathMLContent.CSYMBOL).(parent().name() == MathMLContent.DECLARE &&
 					childIndex() == 0 &&
 					attribute(MathMLAttributes.DEFINITION_URL) == SymbolDefinitionURL.PHYLOGENETIC_GRAPH);
-				if (csymbols.length() == 0)
+				if (csymbolPG.length() == 0)
 					throw new MathMLFileError(xml,
 											  "Cannot find phylogenetic graph declaration.");
-				if (csymbols.length() > 1)
-					throw new MathMLFileError(csymbols[1],
+				if (csymbolPG.length() > 1)
+					throw new MathMLFileError(csymbolPG[1],
 											  "The phylogenetic graph appears to be declared more than once.");
-				const declarePG:XML = csymbols[0].parent();
+				const declarePG:XML = csymbolPG[0].parent();
 				if (declarePG.parent() != xml)
 					throw new MathMLFileError(declarePG,
 											  "The phylogenetic graph is declared in an invalid position.");
 				if (declarePG.children().length() != 2)
 					throw new MathMLFileError(declarePG,
 											  "Invalid phylogenetic graph declaration");
-				const list:XML = declarePG.children()[1];
-				if (list.name() != MathMLContent.LIST)
-					throw new MathMLFileError(list, "Expected <list> element.");
-				if (list.children().length() != 2)
-					throw new MathMLFileError(list,
+				const listPG:XML = declarePG.children()[1];
+				if (listPG.name() != MathMLContent.LIST)
+					throw new MathMLFileError(listPG,
+											  "Expected <list> element.");
+				if (listPG.children().length() != 2)
+					throw new MathMLFileError(listPG,
 											  "Expected <list> element with two child elements.");
-				const nodeSet:XML = list.children()[0];
-				if (nodeSet.name() != MathMLContent.SET)
-					throw new MathMLFileError(nodeSet,
-											  "Expected <set> element.");
-				const edgeSet:XML = list.children()[1];
-				if (edgeSet.name() != MathMLContent.SET)
-					throw new MathMLFileError(edgeSet,
-											  "Expected <set> element.");
-				const nameList:XMLList = xml.children().copy();
-				delete nameList[declarePG.childIndex()];
 				context = new Context();
-				graphBuilder = new HashDAGBuilder(true);
-				readNodes =
-					new ReadNodes(nodeSet.children(), graphBuilder,
-								  context.names);
-				readEdges =
-					new ReadEdges(edgeSet.children(), graphBuilder,
-								  context.names);
-				readNames = new ReadNames(nameList, context);
-				executeAsyncCommand(readNodes, readNodes_completeHandler);
+				_progressOperations.push(new ReadTaxonDefinitions(xml, context));
+				_progressOperations.push(new ReadNodes(listPG, context));
+				_progressOperations.push(new ReadEdges(listPG, context));
+				_progressOperations.push(new ReadMathDefinitions(xml, context));
+				_progressOperations.push(new ReadURISynonyms(xml,
+															 context.names));
+				dispatchProgress();
+				executeAsyncCommand(_progressOperations[0] as AsyncCommand,
+									progressOperation_completeHandler);
 			}
 			catch (e:Error)
 			{
 
 		override protected function cleanUp():void
 		{
-			super.cleanUp();
 			xml = null;
 			context = null;
-			graphBuilder = null;
-			readEdges = null;
-			readNames = null;
-			readNodes = null;
+			_progressOperations = null;
+			super.cleanUp();
 		}
 
 		override protected function get progressOperations():Vector.<ProgressOperation>
 		{
-			const ops:Vector.<ProgressOperation> =
-				new Vector.<ProgressOperation>();
-			if (readEdges)
-				ops.push(readEdges);
-			if (readNames)
-				ops.push(readNames);
-			if (readNodes)
-				ops.push(readNodes);
-			return ops;
+			return _progressOperations;
 		}
 
-		private function readEdges_completeHandler(event:OperationEvent):void
+		private function progressOperation_completeHandler(event:OperationEvent):void
 		{
-			context.nodes.addGraph(graphBuilder.build());
-			graphBuilder = null;
-			dispatchProgress();
-			executeAsyncCommand(readNames, readNames_completeHandler);
-		}
-
-		private function readNames_completeHandler(event:OperationEvent):void
-		{
-			setResult(context);
-		}
-
-		private function readNodes_completeHandler(event:OperationEvent):void
-		{
-			dispatchProgress();
-			executeAsyncCommand(readEdges, readEdges_completeHandler);
+			const index:int =
+				_progressOperations.indexOf(event.target as ProgressOperation) + 1;
+			if (index >= _progressOperations.length)
+				setResult(context);
+			else
+				executeAsyncCommand(_progressOperations[index] as AsyncCommand,
+									progressOperation_completeHandler);
 		}
 	}
 }

File src/org/namesonnodes/controls/files/mathML/MathMLWriter.as

  */
 package org.namesonnodes.controls.files.mathML
 {
-	import flash.events.ProgressEvent;
-	import flash.utils.ByteArray;
-	import flash.utils.Dictionary;
 	import asmathema.collections.sets.FiniteSet;
 	import asmathema.collections.sets.Set;
 	import asmathema.mathML.MathML;
 	import asmathema.mathML.MathMLAttributes;
 	import asmathema.mathML.MathMLContent;
+	
+	import flash.events.ProgressEvent;
+	import flash.utils.ByteArray;
+	import flash.utils.Dictionary;
+	
 	import org.namesonnodes.controls.files.FileWriter;
 	import org.namesonnodes.flow.AbstractAsyncManager;
+	import org.namesonnodes.flow.AsyncCommand;
 	import org.namesonnodes.flow.ProgressOperation;
 	import org.namesonnodes.flow.events.OperationEvent;
 	import org.namesonnodes.math.SymbolDefinitionURL;
 		{
 			super();
 		}
+		private var _progressOperations:Vector.<ProgressOperation> =
+			new Vector.<ProgressOperation>();
 		private var context:Context;
-		private var nameNodes:NameNodes;
-		private var nameUnnamedNodes:NameUnnamedNodes;
-		private var nodeSymbols:Dictionary;
 		private var writeEdges:WriteEdges;
-		private var writeNames:WriteNames;
+		private var writeMathDefinitions:WriteMathDefinitions;
 		private var writeNodes:WriteNodes;
+		private var writeTaxonDefinitions:WriteTaxonDefinitions;
+		private var writeURISynonyms:WriteURISynonyms;
 
 		public function write(context:Context):void
 		{
 			try
 			{
 				this.context = context;
-				nodeSymbols = new Dictionary();
-				nameNodes =
-					new NameNodes(nodeSymbols,
-								  context.names.list.createCursor());
-				writeEdges =
-					new WriteEdges(context.nodes.graphSolver.edges.toVector(),
-								   nodeSymbols);
-				writeNodes =
-					new WriteNodes(context.nodes.graphSolver.nodes.toVector(),
-								   nodeSymbols);
-				writeNames = new WriteNames(context.names.list.createCursor());
-				executeAsyncCommand(nameNodes, nameNodes_completeHandler);
+				writeTaxonDefinitions = new WriteTaxonDefinitions(context);
+				writeNodes = new WriteNodes(context);
+				writeEdges = new WriteEdges(context);
+				writeMathDefinitions = new WriteMathDefinitions(context.names);
+				writeURISynonyms = new WriteURISynonyms(context.names);
+				_progressOperations =
+					Vector.<ProgressOperation>([writeTaxonDefinitions,
+												writeNodes, writeEdges,
+												writeMathDefinitions,
+												writeURISynonyms]);
+				executeAsyncCommand(writeTaxonDefinitions,
+									progressOperation_completeHandler);
 			}
 			catch (e:Error)
 			{
 		{
 			super.cleanUp();
 			context = null;
-			nameNodes = null;
-			nameUnnamedNodes = null;
-			nodeSymbols = null;
+			writeTaxonDefinitions = null;
 			writeEdges = null;
-			writeNames = null;
+			writeMathDefinitions = null;
 			writeNodes = null;
+			writeURISynonyms = null;
+			_progressOperations = null;
 		}
 
 		override protected function get progressOperations():Vector.<ProgressOperation>
 		{
-			const ops:Vector.<ProgressOperation> =
-				new Vector.<ProgressOperation>();
-			if (nameNodes)
-				ops.push(nameNodes);
-			if (nameUnnamedNodes)
-				ops.push(nameUnnamedNodes);
-			if (writeEdges)
-				ops.push(writeEdges);
-			if (writeNames)
-				ops.push(writeNames);
-			if (writeNodes)
-				ops.push(writeNodes);
-			return ops;
+			return _progressOperations;
 		}
 
-		private function nameNodes_completeHandler(event:OperationEvent):void
+		private function complete():void
 		{
-			const unnamedNodes:Set =
-				context.nodes.graphSolver.nodes.diff(nameNodes.declaredNodes);
-			if (!(unnamedNodes is FiniteSet))
-				throw new Error("Error finding unnamed nodes.");
-			nameUnnamedNodes =
-				new NameUnnamedNodes(nodeSymbols,
-									 FiniteSet(unnamedNodes).toVector(),
-									 context.names);
-			dispatchProgress();
-			executeAsyncCommand(nameUnnamedNodes,
-								nameUnnamedNodes_completeHandler);
-		}
-
-		private function nameUnnamedNodes_completeHandler(event:OperationEvent):void
-		{
-			executeAsyncCommand(writeNodes, writeNodes_completeHandler);
-		}
-
-		private function writeEdges_completeHandler(event:OperationEvent):void
-		{
-			executeAsyncCommand(writeNames, writeNames_completeHandler);
-		}
-
-		private function writeNames_completeHandler(event:OperationEvent):void
-		{
-			const csymbol:XML =
-				<csymbol xmlns={MathML.NAMESPACE} definitionURL={SymbolDefinitionURL.PHYLOGENETIC_GRAPH}/>;
+			var xml:XML;
+			const csymbol:XML = <csymbol xmlns={MathML.NAMESPACE}
+					definitionURL={SymbolDefinitionURL.PHYLOGENETIC_GRAPH}/>;
 			const list:XML = <list xmlns={MathML.NAMESPACE}/>;
 			list.appendChild(writeNodes.result as XML);
 			list.appendChild(writeEdges.result as XML);
 				<declare xmlns={MathML.NAMESPACE} type="list"/>
 			declarePhylogeny.appendChild(csymbol);
 			declarePhylogeny.appendChild(list);
-			const mathML:XML =
-				<math xmlns={MathML.NAMESPACE} xmlns:s="http://www.w3.org/2001/XMLSchema-instance" s:schemaLocation="http://www.w3.org/1998/Math/MathML http://www.w3.org/Math/XMLSchema/mathml2/mathml2.xsd"/>;
+			const mathML:XML = <math xmlns={MathML.NAMESPACE}
+					xmlns:s="http://www.w3.org/2001/XMLSchema-instance"
+					s:schemaLocation="http://www.w3.org/1998/Math/MathML http://www.w3.org/Math/XMLSchema/mathml2/mathml2.xsd"/>;
+			mathML.appendChild(<!-- MathML generated by Names on Nodes (alpha version) -->);
+			mathML.appendChild(<!-- http://namesonnodes.org/ -->);
+			mathML.appendChild(<!-- BEGIN  Taxonomic Unit Declarations -->);
+			for each (xml in writeTaxonDefinitions.result)
+				mathML.appendChild(xml);
+			mathML.appendChild(<!-- END    Taxonomic Unit Declarations -->);
+			mathML.appendChild(<!-- BEGIN  Phylogenetic Graph Declaration -->);
 			mathML.appendChild(declarePhylogeny);
-			for each (var name:XML in writeNames.result)
-				mathML.appendChild(name.copy());
+			mathML.appendChild(<!-- END    Phylogenetic Graph Declaration -->);
+			mathML.appendChild(<!-- BEGIN  Higher Taxon Declarations -->);
+			for each (xml in writeMathDefinitions.result)
+				mathML.appendChild(xml);
+			mathML.appendChild(<!-- END    Higher Taxon Declarations -->);
+			mathML.appendChild(<!-- BEGIN  URI Synonymies -->);
+			for each (xml in writeURISynonyms.result)
+				mathML.appendChild(xml);
+			mathML.appendChild(<!-- END    URI Synonymies -->);
 			const bytes:ByteArray = new ByteArray();
 			XML.prettyPrinting = true;
 			bytes.writeUTFBytes("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
 			setResult(bytes);
 		}
 
-		private function writeNodes_completeHandler(event:OperationEvent):void
+		private function progressOperation_completeHandler(event:OperationEvent):void
 		{
-			executeAsyncCommand(writeEdges, writeEdges_completeHandler);
+			const operation:ProgressOperation =
+				event.target as ProgressOperation;
+			const index:int = _progressOperations.indexOf(operation) + 1;
+			if (index >= _progressOperations.length)
+				complete();
+			else
+				executeAsyncCommand(_progressOperations[index] as AsyncCommand,
+									progressOperation_completeHandler);
 		}
 	}
 }

File src/org/namesonnodes/controls/files/mathML/NameNodes.as

-/*
-   Copyright (c) 2010 T. Michael Keesey <http://tmkeesey.net/>
-
-   Permission is hereby granted, free of charge, to any person obtaining a copy
-   of this software and associated documentation files (the "Software"), to deal
-   in the Software without restriction, including without limitation the rights
-   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-   copies of the Software, and to permit persons to whom the Software is
-   furnished to do so, subject to the following conditions:
-
-   The above copyright notice and this permission notice shall be included in
-   all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-   THE SOFTWARE.
- */
-package org.namesonnodes.controls.files.mathML
-{
-	import flash.utils.Dictionary;
-	import mx.collections.IViewCursor;
-	import asmathema.collections.sets.FiniteSet;
-	import asmathema.collections.sets.FiniteSetBuilder;
-	import asmathema.collections.sets.HashSetBuilder;
-	import org.namesonnodes.flow.AsyncTimerCommand;
-	import org.namesonnodes.math.TaxonomicUnit;
-	import org.namesonnodes.models.Declaration;
-
-	internal final class NameNodes extends AsyncTimerCommand
-	{
-		private static const CYCLE:uint = 75;
-		private static const NODES_NAMED_PER_CYCLE:uint = 2000;
-
-		public function NameNodes(nodeSymbols:Dictionary,
-								  declarationCursor:IViewCursor)
-		{
-			super(CYCLE,
-				  Math.max(1,
-						   Math.ceil(declarationCursor.view.length / NODES_NAMED_PER_CYCLE)));
-			this.nodeSymbols = nodeSymbols;
-			this.declarationCursor = declarationCursor;
-			declaredNodesBuilder = new HashSetBuilder();
-		}
-		private var _declaredNodes:FiniteSet;
-		private var declarationCursor:IViewCursor;
-		private var declaredNodesBuilder:FiniteSetBuilder;
-		private var nodeSymbols:Dictionary;
-
-		[Bindable(event="complete")]
-		public function get declaredNodes():FiniteSet
-		{
-			return _declaredNodes;
-		}
-
-		override protected function cleanUp():void
-		{
-			super.cleanUp();
-			declarationCursor = null;
-			nodeSymbols = null;
-			if (declaredNodesBuilder)
-				_declaredNodes = declaredNodesBuilder.build();
-			declaredNodesBuilder = null;
-		}
-
-		override protected function doCalculations():void
-		{
-			for (var i:uint = 0; i < NODES_NAMED_PER_CYCLE; ++i)
-			{
-				if (declarationCursor.afterLast)
-					break;
-				var declaration:Declaration =
-					declarationCursor.current as Declaration;
-				if (declaration.definition.apply() is TaxonomicUnit)
-				{
-					declaredNodesBuilder.addMember(declaration.definition.apply());
-					nodeSymbols[declaration.definition.apply()] =
-						declaration.symbol;
-				}
-				declarationCursor.moveNext();
-			}
-		}
-	}
-}

File src/org/namesonnodes/controls/files/mathML/NameUnnamedNodes.as

-/*
-   Copyright (c) 2010 T. Michael Keesey <http://tmkeesey.net/>
-
-   Permission is hereby granted, free of charge, to any person obtaining a copy
-   of this software and associated documentation files (the "Software"), to deal
-   in the Software without restriction, including without limitation the rights
-   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-   copies of the Software, and to permit persons to whom the Software is
-   furnished to do so, subject to the following conditions:
-
-   The above copyright notice and this permission notice shall be included in
-   all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-   THE SOFTWARE.
- */
-package org.namesonnodes.controls.files.mathML
-{
-	import com.adobe.net.URI;
-	import flash.utils.Dictionary;
-	import asmathema.mathML.MathML;
-	import org.namesonnodes.flow.AsyncTimerCommand;
-	import org.namesonnodes.math.TaxonomicUnit;
-	import org.namesonnodes.models.Declaration;
-	import org.namesonnodes.models.NameContext;
-	import org.namesonnodes.models.Symbol;
-	import org.namesonnodes.models.definitions.TaxonDefinition;
-
-	internal final class NameUnnamedNodes extends AsyncTimerCommand
-	{
-		private static const CYCLE:uint = 75;
-		private static const NODES_NAMED_PER_CYCLE:uint = 2000;
-
-		public function NameUnnamedNodes(nodeSymbols:Dictionary,
-										 unnamedNodes:Vector.<Object>,
-										 names:NameContext)
-		{
-			super(CYCLE,
-				  Math.max(1,
-						   Math.ceil(unnamedNodes.length / NODES_NAMED_PER_CYCLE)));
-			this.nodeSymbols = nodeSymbols;
-			this.unnamedNodes = unnamedNodes;
-			this.names = names;
-		}
-		private var names:NameContext;
-		private var nodeSymbols:Dictionary;
-		private var unnamedNodes:Vector.<Object>;
-
-		override protected function cleanUp():void
-		{
-			super.cleanUp();
-			names = null;
-			nodeSymbols = null;
-			unnamedNodes = null;
-		}
-
-		override protected function doCalculations():void
-		{
-			for (var i:uint = 0; i < NODES_NAMED_PER_CYCLE; ++i)
-			{
-				if (unnamedNodes.length == 0)
-					break;
-				var node:TaxonomicUnit = unnamedNodes.shift() as TaxonomicUnit;
-				do
-				{
-					var symbol:Symbol = Symbol.createPhantom();
-				} while (names.hasSymbol(symbol.uriString));
-				nodeSymbols[node] = symbol;
-				names.addDeclaration(new Declaration(symbol,
-													 new TaxonDefinition(node),
-													 true));
-			}
-		}
-	}
-}

File src/org/namesonnodes/controls/files/mathML/ReadEdges.as

 	import asmathema.collections.lists.OrderedPair;
 	import asmathema.mathML.MathML;
 	import asmathema.mathML.MathMLContent;
+	import asmathema.mathML.evaluators.MathMLEvaluator;
 	import org.namesonnodes.flow.AsyncTimerCommand;
+	import org.namesonnodes.math.Taxon;
 	import org.namesonnodes.math.TaxonomicUnit;
-	import org.namesonnodes.models.Declaration;
+	import org.namesonnodes.models.Context;
 	import org.namesonnodes.models.NameContext;
-	import org.namesonnodes.models.Symbol;
+	import org.namesonnodes.models.NameEntry;
 
 	internal final class ReadEdges extends AsyncTimerCommand
 	{
-		private static const CYCLE:uint = 75;
-		private static const EDGES_READ_PER_CYCLE:uint = 1000;
-
-		public function ReadEdges(list:XMLList, graphBuilder:GraphBuilder,
-								  names:NameContext)
+		public function ReadEdges(phylogeneticGraph:XML, context:Context)
 		{
-			super(CYCLE,
-				  Math.max(1, Math.ceil(list.length() / EDGES_READ_PER_CYCLE)));
-			this.list = list;
-			this.graphBuilder = graphBuilder;
-			this.names = names;
+			super(200, 150);
+			default xml namespace=MathML.NAMESPACE.uri;
+			this.context = context;
+			if (phylogeneticGraph.children().length() != 2)
+				throw new MathMLFileError(phylogeneticGraph,
+										  "Expected two child elements.");
+			const edgeSet:XML = phylogeneticGraph.children()[1];
+			if (edgeSet.name() != MathMLContent.SET)
+				throw new MathMLFileError(edgeSet, "Expected <set> element.");
+			list = edgeSet.list;
+			setProgress(0, list.length());
 		}
-		private var graphBuilder:GraphBuilder;
+		private var context:Context;
 		private var list:XMLList;
-		private var names:NameContext;
 		private var xmlIndex:uint;
 
 		override protected function cleanUp():void
 		{
 			super.cleanUp();
-			graphBuilder = null;
 			list = null;
-			names = null;
+			context = null;
 		}
 
-		override protected function doCalculations():void
+		protected function findNodeForCSymbol(csymbol:XML):Taxon
 		{
-			const n:int = list.length();
-			for (var i:uint = 0; i < EDGES_READ_PER_CYCLE; ++i)
-			{
-				if (xmlIndex >= n)
-					break;
-				var xml:XML = list[xmlIndex++];
-				if (xml.name() != MathMLContent.LIST)
-					throw new MathMLFileError(xml, "Expected <list> element.");
-				if (xml.children().length() != 2)
-					throw new MathMLFileError(xml,
-											  "Expected <list> element with two children.");
-				if (xml.children()[0].name() != MathMLContent.CSYMBOL)
-					throw new MathMLFileError(xml.children()[0],
-											  "Expected <csymbol> element.");
-				if (xml.children()[1].name() != MathMLContent.CSYMBOL)
-					throw new MathMLFileError(xml.children()[1],
-											  "Expected <csymbol> element.");
-				var source:TaxonomicUnit =
-					findNodeForCSymbol(xml.children()[0]);
-				var target:TaxonomicUnit =
-					findNodeForCSymbol(xml.children()[1]);
-				graphBuilder.addEdge(new OrderedPair(source, target));
-			}
+			default xml namespace=MathML.NAMESPACE.uri;
+			const entry:NameEntry =
+				context.names.getEntryForDefinitionURL(csymbol.@definitionURL);
+			if (entry == null)
+				throw new MathMLFileError(csymbol,
+										  "Cannot locate node: " + csymbol + ".");
+			const node:* = entry.definition.apply();
+			if (!(node is Taxon))
+				throw new MathMLFileError(csymbol,
+										  "Symbol does not identify a node (i.e., a taxonomic unit) directly.");
+			return node as Taxon;
 		}
 
-		protected function findNodeForCSymbol(csymbol:XML):TaxonomicUnit
+		override protected function performIteration():void
 		{
-			default xml namespace=MathML.NAMESPACE.uri;
-			var declaration:Declaration =
-				names.getDeclaration(csymbol.@definitionURL);
-			if (declaration == null)
-				throw new MathMLFileError(csymbol,
-										  "Cannot locate node: " + csymbol + ".");
-			var node:* = declaration.definition.apply();
-			if (!(node is TaxonomicUnit))
-				throw new MathMLFileError(csymbol,
-										  "Symbol does not identify a node (i.e., a taxonomic unit) directly.");
-			return node as TaxonomicUnit;
+			if (xmlIndex >= list.length())
+			{
+				setResult(true);
+				return;
+			}
+			const xml:XML = list[xmlIndex++];
+			if (xml.name() != MathMLContent.LIST)
+				throw new MathMLFileError(xml, "Expected <list> element.");
+			const n:int = xml.children().length();
+			if (n != 2 && n != 3)
+				throw new MathMLFileError(xml,
+										  "Expected <list> element with two or three children.");
+			if (xml.children()[0].name() != MathMLContent.CSYMBOL)
+				throw new MathMLFileError(xml.children()[0],
+										  "Expected <csymbol> element.");
+			if (xml.children()[1].name() != MathMLContent.CSYMBOL)
+				throw new MathMLFileError(xml.children()[1],
+										  "Expected <csymbol> element.");
+			const source:Taxon = findNodeForCSymbol(xml.children()[0]);
+			const target:Taxon = findNodeForCSymbol(xml.children()[1]);
+			var weight:Number = Number.NaN;
+			if (n == 3)
+				weight = new MathMLEvaluator().evaluate(xml.children()[2]);
+			context.nodes.addArc(source, target, weight);
+			setProgress(progress + 1, total);
 		}
 	}
 }

File src/org/namesonnodes/controls/files/mathML/ReadMathDefinitions.as

+package org.namesonnodes.controls.files.mathML
+{
+	import asmathema.collections.sets.Set;
+	import asmathema.mathML.MathML;
+	import org.namesonnodes.controls.definitions.MathElementTranslator;
+	import org.namesonnodes.flow.AsyncTimerCommand;
+	import org.namesonnodes.models.Context;
+	import org.namesonnodes.models.NameEntry;
+	import org.namesonnodes.models.definitions.Definition;
+	import org.namesonnodes.models.definitions.elements.ValueType;
+
+	internal final class ReadMathDefinitions extends AsyncTimerCommand
+	{
+		private static const valueType:ValueType = ValueType.fromClass(Set);
+
+		public function ReadMathDefinitions(content:XML, context:Context)
+		{
+			super(200, 150);
+			default xml namespace=MathML.NAMESPACE.uri;
+			this.context = context;
+			list = content.declare.(children().length() == 2);
+			setProgress(0, list.length());
+			this.context = context;
+		}
+		private var context:Context;
+		private var index:int = 0;
+		private var list:XMLList;
+		private var translator:MathElementTranslator;
+
+		override public function execute():*
+		{
+			try
+			{
+				if (list.length() == 0)
+				{
+					setResult(context);
+					return;
+				}
+				index = 0;
+				translator = new MathElementTranslator(context);
+				super.execute();
+			}
+			catch (e:Error)
+			{
+				setError(e);
+			}
+		}
+
+		override protected function cleanUp():void
+		{
+			context = null;
+			list = null;
+			translator = null;
+			super.cleanUp();
+		}
+
+		override protected function performIteration():void
+		{
+			default xml namespace=MathML.NAMESPACE.uri;
+			if (index >= list.length())
+			{
+				setResult(true);
+				return;
+			}
+			const declare:XML = list[index++];
+			const csymbol:XML = declare.csymbol;
+			const definition:Definition =
+				translator.translate(declare.children()[1], valueType);
+			const entry:NameEntry = new NameEntry(definition, csymbol.@id);
+			setProgress(progress + 1, total);
+		}
+	}
+}

File src/org/namesonnodes/controls/files/mathML/ReadNames.as

-/*
-   Copyright (c) 2010 T. Michael Keesey <http://tmkeesey.net/>
-
-   Permission is hereby granted, free of charge, to any person obtaining a copy
-   of this software and associated documentation files (the "Software"), to deal
-   in the Software without restriction, including without limitation the rights
-   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-   copies of the Software, and to permit persons to whom the Software is
-   furnished to do so, subject to the following conditions:
-
-   The above copyright notice and this permission notice shall be included in
-   all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-   THE SOFTWARE.
- */
-package org.namesonnodes.controls.files.mathML
-{
-	import asmathema.collections.sets.Set;
-	import asmathema.mathML.MathMLContent;
-	import org.namesonnodes.controls.definitions.MathElementTranslator;
-	import org.namesonnodes.flow.AsyncTimerCommand;
-	import org.namesonnodes.models.Context;
-	import org.namesonnodes.models.Declaration;
-	import org.namesonnodes.models.NameContext;
-	import org.namesonnodes.models.Symbol;
-	
-	import org.namesonnodes.models.definitions.elements.MathElement;
-	import org.namesonnodes.models.definitions.elements.ValueType;
-
-	internal final class ReadNames extends AsyncTimerCommand
-	{
-		private static const CYCLE:uint = 75;
-		private static const NAMES_READ_PER_CYCLE:uint = 2000;
-
-		public function ReadNames(list:XMLList, context:Context)
-		{
-			super(CYCLE,
-				  Math.max(1, Math.ceil(list.length() / NAMES_READ_PER_CYCLE)));
-			this.list = list;
-			this.context = context;
-		}
-		private var context:Context;
-		private var list:XMLList;
-		private var xmlIndex:uint;
-
-		override protected function cleanUp():void
-		{
-			super.cleanUp();
-			list = null;
-			context = null;
-		}
-
-		override protected function doCalculations():void
-		{
-			const n:int = list.length();
-			for (var i:uint = 0; i < NAMES_READ_PER_CYCLE; ++i)
-			{
-				if (xmlIndex >= n)
-					break;
-				var xml:XML = list[xmlIndex++];
-				if (xml.name() != MathMLContent.DECLARE)
-					continue;
-				if (xml.children().length() != 2)
-					throw new MathMLFileError(xml,
-											  "Expected <declare> element with two child elements.");
-				var csymbol:XML = xml.children()[0];
-				if (csymbol.name() != MathMLContent.CSYMBOL)
-					throw new MathMLFileError(csymbol,
-											  "Expected <csymbol> element.");
-				var definition:XML = xml.children()[1];
-				const element:MathElement =
-					new MathElementTranslator(context).translate(definition,
-																 ValueType.fromClass(Set));
-				context.names.addDeclaration(new Declaration(Symbol.fromContent(csymbol),
-																				element,
-																				false));
-			}
-		}
-	}
-}

File src/org/namesonnodes/controls/files/mathML/ReadNodes.as

 package org.namesonnodes.controls.files.mathML
 {
 	import asmathema.collections.graphs.GraphBuilder;
+	import asmathema.mathML.MathML;
 	import asmathema.mathML.MathMLContent;
+	import asmathema.mathML.MathMLError;
 	import org.namesonnodes.flow.AsyncTimerCommand;
+	import org.namesonnodes.math.Taxon;
 	import org.namesonnodes.math.TaxonomicUnit;
-	import org.namesonnodes.models.Declaration;
+	import org.namesonnodes.models.Context;
 	import org.namesonnodes.models.NameContext;
-	import org.namesonnodes.models.Symbol;
+	import org.namesonnodes.models.NameEntry;
 	import org.namesonnodes.models.definitions.TaxonDefinition;
 
 	internal final class ReadNodes extends AsyncTimerCommand
 	{
-		private static const CYCLE:uint = 75;
-		private static const NODES_READ_PER_CYCLE:uint = 1000;
+		public function ReadNodes(phylogeneticGraph:XML, context:Context)
+		{
+			super(200, 150);
+			default xml namespace=MathML.NAMESPACE.uri;
+			this.context = context;
+			if (phylogeneticGraph.children().length() != 2)
+				throw new MathMLFileError(phylogeneticGraph,
+										  "Expected two child elements.");
+			const nodeSet:XML = phylogeneticGraph.children()[0];
+			if (nodeSet.name() != MathMLContent.SET)
+				throw new MathMLFileError(nodeSet, "Expected <set> element.");
+			list = nodeSet.csymbol;
+			setProgress(0, list.length());
+		}
+		private var context:Context;
+		private var list:XMLList;
+		private var xmlIndex:uint;
 
-		public function ReadNodes(list:XMLList, graphBuilder:GraphBuilder,
-								  names:NameContext)
+		override public function execute():*
 		{
-			super(CYCLE,
-				  Math.max(1, Math.ceil(list.length() / NODES_READ_PER_CYCLE)));
-			this.list = list;
-			this.graphBuilder = graphBuilder;
-			this.names = names;
+			xmlIndex = 0;
+			super.execute();
 		}
-		private var graphBuilder:GraphBuilder;
-		private var list:XMLList;
-		private var names:NameContext;
-		private var xmlIndex:uint;
 
 		override protected function cleanUp():void
 		{
 			super.cleanUp();
-			graphBuilder = null;
 			list = null;
-			names = null;
+			context = null;
 		}
 
-		override protected function doCalculations():void
+		override protected function performIteration():void
 		{
-			const n:int = list.length();
-			for (var i:uint = 0; i < NODES_READ_PER_CYCLE; ++i)
+			default xml namespace=MathML.NAMESPACE.uri;
+			if (xmlIndex >= list.length())
 			{
-				if (xmlIndex >= n)
-					break;
-				var xml:XML = list[xmlIndex++];
-				if (xml.name() != MathMLContent.DECLARE)
-					throw new MathMLFileError(xml,
-											  "Expected <declare> element.");
-				if (xml.children().length() != 1)
-					throw new MathMLFileError(xml,
-											  "Expected <declare> element with one child.");
-				var csymbol:XML = xml.children()[0];
-				if (csymbol.name() != MathMLContent.CSYMBOL)
-					throw new MathMLFileError(xml,
-											  "Expected <declare> element with one <csymbol> element as a child.");
-				var node:TaxonomicUnit =
-					TaxonomicUnit.factory.newInstance() as TaxonomicUnit;
-				graphBuilder.addNode(node);
-				names.addDeclaration(new Declaration(Symbol.fromContent(csymbol),
-																		new TaxonDefinition(node),
-																		true));
+				setResult(true);
+				return;
 			}
+			var node:Taxon;
+			const xml:XML = list[xmlIndex++];
+			if (xml.@definitionURL.length() == 1)
+				node = context.names.getSymbolValue(xml.@definitionURL) as Taxon;
+			else if (xml.@id.length() == 1)
+			{
+				node = TaxonomicUnit.factory.newInstance() as Taxon;
+				context.names.addEntry(new NameEntry(new TaxonDefinition(node),
+																		 xml.@id));
+			}
+			else
+				throw new MathMLFileError(xml,
+										  "No ID or definition URL provided.");
+			if (node == null)
+				throw new MathMLFileError(xml,
+										  "Symbol \"" + String(xml.@definitionURL).substr(1) + "\" is not declared as a taxonomic unit.");
+			context.nodes.addNode(node);
+			setProgress(progress + 1, total);
 		}
 	}
 }

File src/org/namesonnodes/controls/files/mathML/ReadTaxonDefinitions.as

+/*
+   Copyright (c) 2010 T. Michael Keesey <http://tmkeesey.net/>
+
+   Permission is hereby granted, free of charge, to any person obtaining a copy
+   of this software and associated documentation files (the "Software"), to deal
+   in the Software without restriction, including without limitation the rights
+   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+   copies of the Software, and to permit persons to whom the Software is
+   furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+   THE SOFTWARE.
+ */
+package org.namesonnodes.controls.files.mathML
+{
+	import flash.events.TimerEvent;
+	import flash.system.System;
+	import flash.utils.Timer;
+	import flash.utils.getTimer;
+	import mx.collections.IViewCursor;
+	import asmathema.mathML.MathML;
+	import org.namesonnodes.flow.AbstractOperation;
+	import org.namesonnodes.flow.AbstractProgressOperation;
+	import org.namesonnodes.flow.AsyncCommand;
+	import org.namesonnodes.flow.AsyncTimerCommand;
+	import org.namesonnodes.flow.Operation;
+	import org.namesonnodes.math.Taxon;
+	import org.namesonnodes.math.TaxonomicUnit;
+	import org.namesonnodes.models.Context;
+	import org.namesonnodes.models.NameContext;
+	import org.namesonnodes.models.NameEntry;
+	import org.namesonnodes.models.definitions.TaxonDefinition;
+
+	internal final class ReadTaxonDefinitions extends AsyncTimerCommand
+	{
+		public function ReadTaxonDefinitions(content:XML, context:Context)
+		{
+			super(200, 150);
+			default xml namespace=MathML.NAMESPACE.uri;
+			this.context = context;
+			list = content.declare.(@type == "set" && children().length() == 1);
+			setProgress(0, list.length());
+			this.context = context;
+		}
+		private var context:Context;
+		private var index:int = 0;
+		private var list:XMLList;
+
+		override public function execute():*
+		{
+			try
+			{
+				if (list.length() == 0)
+				{
+					setResult(context);
+					return;
+				}
+				index = 0;
+				super.execute();
+			}
+			catch (e:Error)
+			{
+				setError(e);
+			}
+		}
+
+		override protected function cleanUp():void
+		{
+			super.cleanUp();
+			context = null;
+			list = null;
+		}
+
+		override protected function performIteration():void
+		{
+			default xml namespace=MathML.NAMESPACE.uri;
+			if (index >= list.length())
+			{
+				setResult(context);
+				return;
+			}
+			const declare:XML = list[index++];
+			const csymbol:XML = declare.csymbol;
+			const taxon:Taxon = TaxonomicUnit.factory.newInstance() as Taxon;
+			context.nodes.addNode(taxon);
+			const entry:NameEntry =
+				new NameEntry(new TaxonDefinition(taxon), csymbol.@id);
+			for each (var presentation:XML in csymbol.children())
+				entry.addPresentation(presentation);
+			context.names.addEntry(entry);
+			setProgress(progress + 1, total);
+		}
+	}
+}

File src/org/namesonnodes/controls/files/mathML/ReadURISynonyms.as

+package org.namesonnodes.controls.files.mathML
+{
+	import com.adobe.net.URI;
+	import asmathema.mathML.MathML;
+	import org.namesonnodes.flow.AsyncTimerCommand;
+	import org.namesonnodes.models.NameContext;
+	import org.namesonnodes.models.NameEntry;
+
+	internal final class ReadURISynonyms extends AsyncTimerCommand
+	{
+		public function ReadURISynonyms(content:XML, names:NameContext)
+		{
+			super(200, 150);
+			default xml namespace=MathML.NAMESPACE.uri;
+			this.names = names;
+			eqList = content.apply.eq;
+			setProgress(0, eqList.length());
+		}
+		private var eqList:XMLList;
+		private var index:int;
+		private var names:NameContext;
+
+		override public function execute():*
+		{
+			if (eqList.length() == 0)
+			{
+				setResult(true);
+				return;
+			}
+			index = 0;
+			super.execute();
+		}
+
+		override protected function cleanUp():void
+		{
+			names = null;
+			eqList = null;
+			super.cleanUp();
+		}
+
+		override protected function performIteration():void
+		{
+			default xml namespace=MathML.NAMESPACE.uri;
+			if (index >= eqList.length())
+			{
+				setResult(true);
+				return;
+			}
+			const eq:XML = eqList[index++];
+			const apply:XML = eq.parent();
+			const urls:Vector.<String> = new Vector.<String>();
+			var entry:NameEntry;
+			var url:String;
+			for each (var csymbol:XML in apply.csymbol)
+				if (csymbol.@definitionURL.length() == 1)
+				{
+					url = csymbol.@definitionURL;
+					if (url.charAt(0) == "#")
+						entry = names.getEntryForDefinitionURL(url);
+					else
+						urls.push(url);
+				}
+			if (entry)
+				for each (url in urls)
+					entry.addURI(new URI(url));
+			setProgress(progress + 1, total);
+		}
+	}
+}

File src/org/namesonnodes/controls/files/mathML/WriteEdges.as

 	import asmathema.collections.lists.FiniteList;
 	import asmathema.mathML.MathML;
 	import org.namesonnodes.flow.AsyncTimerCommand;
-	import org.namesonnodes.models.Symbol;
+	import org.namesonnodes.math.Taxon;
+	import org.namesonnodes.models.Context;
+	import org.namesonnodes.models.NameContext;
+	import org.namesonnodes.models.NameEntry;
 
 	internal final class WriteEdges extends AsyncTimerCommand
 	{
-		private static const CYCLE:uint = 200;
-		private static const EDGES_WRITTEN_PER_CYCLE:uint = 1000;
-
-		public function WriteEdges(edges:Vector.<Object>,
-								   nodeSymbols:Dictionary)
+		public function WriteEdges(context:Context)
 		{
-			super(CYCLE,
-				  Math.max(1,
-						   Math.ceil(edges.length / EDGES_WRITTEN_PER_CYCLE)));
-			this.nodeSymbols = nodeSymbols;
-			this.edges = edges;
+			super(300, 90);
+			names = context.names;
+			edges = context.nodes.graphSolver.edges.toVector();
 			edgeSet = <set xmlns={MathML.NAMESPACE}/>;
+			setProgress(0, edges.length);
 		}
 		private var edgeSet:XML;
 		private var edges:Vector.<Object>;
-		private var nodeSymbols:Dictionary
+		private var names:NameContext
 
 		override protected function cleanUp():void
 		{
 			super.cleanUp();
-			nodeSymbols = null;
+			names = null;
 			edges = null;
+			edgeSet = null;
 		}
 
-		override protected function doCalculations():void
+		override protected function performIteration():void
 		{
-			for (var i:uint = 0; i < EDGES_WRITTEN_PER_CYCLE; ++i)
+			if (edges.length == 0)
 			{
-				if (edges.length == 0)
-					break;
-				var arc:FiniteList = edges.shift() as FiniteList;
-				var list:XML = <list xmlns={MathML.NAMESPACE}/>;
-				list.appendChild(Symbol(nodeSymbols[arc.select(0)]).shortContent);
-				list.appendChild(Symbol(nodeSymbols[arc.select(1)]).shortContent);
-				edgeSet.appendChild(list);
+				setResult(edgeSet);
+				return;
 			}
-		}
-
-		override protected function get eventualResult():*
-		{
-			return edgeSet;
+			const arc:FiniteList = edges.pop() as FiniteList;
+			const head:Taxon = arc.select(0) as Taxon;
+			const tail:Taxon = arc.select(1) as Taxon;
+			const headEntry:NameEntry = names.getDirectEntryForTaxon(head);
+			const tailEntry:NameEntry = names.getDirectEntryForTaxon(tail);
+			const list:XML = <list xmlns={MathML.NAMESPACE}>
+					<csymbol definitionURL={'#' + headEntry.id}/>
+					<csymbol definitionURL={'#' + tailEntry.id}/>
+				</list>;
+			edgeSet.appendChild(list);
+			setProgress(progress + 1, total);
 		}
 	}
 }

File src/org/namesonnodes/controls/files/mathML/WriteMathDefinitions.as

+package org.namesonnodes.controls.files.mathML
+{
+	import asmathema.collections.sets.FiniteSetBuilder;
+	import asmathema.collections.sets.HashSetBuilder;
+	import asmathema.mathML.MathML;
+	import org.namesonnodes.flow.AsyncTimerCommand;
+	import org.namesonnodes.models.NameContext;
+	import org.namesonnodes.models.NameEntry;
+	import org.namesonnodes.models.definitions.elements.MathElement;
+
+	internal final class WriteMathDefinitions extends AsyncTimerCommand
+	{
+		public function WriteMathDefinitions(names:NameContext)
+		{
+			super(300, 90);
+			this.names = names;
+			exceptions = new HashSetBuilder();
+			var total:uint = 0;
+			for each (var entry:NameEntry in names.entries)
+				if (entry.definition is MathElement)
+					++total;
+				else
+					exceptions.addMember(entry);
+			setProgress(0, total);
+		}
+		private var container:XML;
+		private var exceptions:FiniteSetBuilder;
+		private var names:NameContext;
+
+		override public function execute():*
+		{
+			container = <math xmlns={MathML.NAMESPACE}/>;
+			super.execute();
+		}
+
+		override protected function cleanUp():void
+		{
+			super.cleanUp();
+			names = null;
+			container = null;
+			exceptions = null;
+		}
+
+		override protected function performIteration():void
+		{
+			const entry:NameEntry = names.findIndependent(exceptions.build());
+			if (!entry)
+			{
+				setResult(container.children());
+				return;
+			}
+			exceptions.addMember(entry);
+			const declare:XML = <declare xmlns={MathML.NAMESPACE} type="set"/>;
+			const csymbol:XML =
+				<csymbol xmlns={MathML.NAMESPACE} id={entry.id}/>;
+			for each (var presentation:XML in entry.presentationList)
+				csymbol.appendChild(presentation.copy());
+			declare.appendChild(csymbol);
+			declare.appendChild(MathElement(entry.definition).content);
+			container.appendChild(declare);
+			setProgress(progress + 1, total);
+		}
+	}
+}

File src/org/namesonnodes/controls/files/mathML/WriteNames.as

-/*
-   Copyright (c) 2010 T. Michael Keesey <http://tmkeesey.net/>
-
-   Permission is hereby granted, free of charge, to any person obtaining a copy
-   of this software and associated documentation files (the "Software"), to deal
-   in the Software without restriction, including without limitation the rights
-   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-   copies of the Software, and to permit persons to whom the Software is
-   furnished to do so, subject to the following conditions:
-
-   The above copyright notice and this permission notice shall be included in
-   all copies or substantial portions of the Software.
-
-   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-   THE SOFTWARE.
- */
-package org.namesonnodes.controls.files.mathML
-{
-	import flash.utils.Dictionary;
-	import mx.collections.IViewCursor;
-	import asmathema.mathML.MathML;
-	import org.namesonnodes.flow.AsyncTimerCommand;
-	import org.namesonnodes.math.SymbolPresentation;
-	import org.namesonnodes.math.TaxonomicUnit;
-	import org.namesonnodes.models.Declaration;
-	
-	import org.namesonnodes.models.definitions.TaxonDefinition;
-	import org.namesonnodes.models.definitions.elements.MathElement;
-
-	internal final class WriteNames extends AsyncTimerCommand
-	{
-		private static const CYCLE:uint = 200;
-		private static const NAMES_WRITTEN_PER_CYCLE:uint = 2000;
-
-		public function WriteNames(declarationCursor:IViewCursor)
-		{
-			super(CYCLE,
-				  Math.max(1,
-						   Math.ceil(declarationCursor.view.length / NAMES_WRITTEN_PER_CYCLE)));
-			this.declarationCursor = declarationCursor;
-			declareContainer = <math xmlns={MathML.NAMESPACE}/>;
-		}
-		private var declarationCursor:IViewCursor;
-		private var declareContainer:XML;
-
-		override protected function cleanUp():void
-		{
-			super.cleanUp();
-			declarationCursor = null;
-			declareContainer = null;
-		}
-
-		override protected function doCalculations():void
-		{
-			for (var i:uint = 0; i < NAMES_WRITTEN_PER_CYCLE; ++i)
-			{
-				if (declarationCursor.afterLast)
-					break;
-				var declaration:Declaration =
-					declarationCursor.current as Declaration;
-				declarationCursor.moveNext();
-				if (!(declaration.definition is MathElement))
-					continue;
-				var content:XML = declaration.symbol.longContent;
-				var declare:XML =
-					<declare xmlns={MathML.NAMESPACE} type="set"/>;
-				declare.appendChild(content);
-				var definition:XML =
-					MathElement(declaration.definition).content;
-				declare.appendChild(definition);
-				declareContainer.appendChild(declare);
-			}
-		}
-
-		override protected function get eventualResult():*
-		{
-			return declareContainer.children();
-		}
-	}
-}

File src/org/namesonnodes/controls/files/mathML/WriteNodes.as

 {
 	import flash.utils.Dictionary;
 	import asmathema.mathML.MathML;
-	import org.hamcrest.core.ShortcutCombinationMatcher;
 	import org.namesonnodes.flow.AsyncTimerCommand;
 	import org.namesonnodes.math.SymbolPresentation;
-	import org.namesonnodes.math.TaxonomicUnit;
-	import org.namesonnodes.models.Symbol;
+	import org.namesonnodes.math.Taxon;
+	import org.namesonnodes.models.Context;
+	import org.namesonnodes.models.NameContext;
+	import org.namesonnodes.models.NameEntry;
 
 	internal final class WriteNodes extends AsyncTimerCommand
 	{
-		private static const CYCLE:uint = 200;
-		private static const NODES_WRITTEN_PER_CYCLE:uint = 1000;
-
-		public function WriteNodes(nodes:Vector.<Object>,
-								   nodeSymbols:Dictionary)
+		public function WriteNodes(context:Context)
 		{
-			super(CYCLE,
-				  Math.max(1,
-						   Math.ceil(nodes.length / NODES_WRITTEN_PER_CYCLE)));
-			this.nodeSymbols = nodeSymbols;
-			this.nodes = nodes;
+			super(300, 90);
+			names = context.names;
+			nodes = context.nodes.graphSolver.nodes.toVector();
 			nodeSet = <set xmlns={MathML.NAMESPACE}/>;
+			setProgress(0, nodes.length);
 		}
+		private var names:NameContext;
 		private var nodeSet:XML;
-		private var nodeSymbols:Dictionary
 		private var nodes:Vector.<Object>;
 
 		override protected function cleanUp():void
 		{
 			super.cleanUp();
-			nodeSymbols = null;
+			names = null;
 			nodes = null;
+			nodeSet = null;
 		}
 
-		override protected function doCalculations():void
+		override protected function performIteration():void
 		{
-			for (var i:uint = 0; i < NODES_WRITTEN_PER_CYCLE; ++i)
+			if (nodes.length == 0)
 			{
-				if (nodes.length == 0)
-					break;
-				var node:TaxonomicUnit = nodes.shift() as TaxonomicUnit;
-				var content:XML = Symbol(nodeSymbols[node]).longContent;
-				var declareNode:XML =
-					<declare xmlns={MathML.NAMESPACE} type="set"/>;
-				declareNode.appendChild(content);
-				nodeSet.appendChild(declareNode);
+				setResult(nodeSet);
+				return;
 			}
-		}
-
-		override protected function get eventualResult():*
-		{
-			return nodeSet;
+			const node:Taxon = nodes.pop() as Taxon;
+			const entry:NameEntry = names.getDirectEntryForTaxon(node);
+			const csymbol:XML =
+				<csymbol xmlns={MathML.NAMESPACE} definitionURL={'#' + entry.id}/>;
+			nodeSet.appendChild(csymbol);
+			setProgress(progress + 1, total);
 		}
 	}
 }

File src/org/namesonnodes/controls/files/mathML/WriteTaxonDefinitions.as

+/*
+   Copyright (c) 2010 T. Michael Keesey <http://tmkeesey.net/>
+
+   Permission is hereby granted, free of charge, to any person obtaining a copy
+   of this software and associated documentation files (the "Software"), to deal
+   in the Software without restriction, including without limitation the rights
+   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+   copies of the Software, and to permit persons to whom the Software is
+   furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+   THE SOFTWARE.
+ */
+package org.namesonnodes.controls.files.mathML
+{
+	import flash.events.TimerEvent;
+	import flash.system.System;
+	import flash.utils.Timer;
+	import flash.utils.getTimer;
+	import mx.collections.ArrayCollection;
+	import mx.collections.IViewCursor;
+	import asmathema.mathML.MathML;
+	import org.namesonnodes.flow.AbstractOperation;
+	import org.namesonnodes.flow.AbstractProgressOperation;
+	import org.namesonnodes.flow.AsyncCommand;
+	import org.namesonnodes.flow.AsyncTimerCommand;
+	import org.namesonnodes.flow.Operation;
+	import org.namesonnodes.math.Taxon;
+	import org.namesonnodes.math.TaxonomicUnion;
+	import org.namesonnodes.models.Context;
+	import org.namesonnodes.models.NameContext;
+	import org.namesonnodes.models.NameEntry;
+	import org.namesonnodes.models.definitions.TaxonDefinition;
+
+	internal final class WriteTaxonDefinitions extends AsyncTimerCommand
+	{
+		public function WriteTaxonDefinitions(context:Context)
+		{
+			super(300, 90);
+			this.context = context;
+			setProgress(0, context.nodes.graphSolver.nodes.size);
+		}
+		private var contentHolder:XML;
+		private var context:Context;
+		private var nodes:Vector.<Object>;
+
+		override public function execute():*
+		{
+			try
+			{
+				const n:uint = context.nodes.graphSolver.nodes.size;
+				if (n == 0)
+				{
+					setResult(new XMLList());
+					return;
+				}
+				nodes = context.nodes.graphSolver.nodes.toVector();
+				contentHolder = <math xmlns={MathML.NAMESPACE}/>;
+				super.execute();
+			}
+			catch (e:Error)
+			{
+				setError(e);
+			}
+		}
+
+		override protected function cleanUp():void
+		{
+			super.cleanUp();