PageRenderTime 32ms CodeModel.GetById 17ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/src/name/carter/mark/flex/project/mdoc/MDocument.as

http://transcriptstudio4isha.googlecode.com/
ActionScript | 190 lines | 167 code | 19 blank | 4 comment | 49 complexity | 00b86c3a6cb67907ad5127e75fa4f61f MD5 | raw file
  1package name.carter.mark.flex.project.mdoc
  2{
  3	import com.ericfeminella.collections.HashMap;
  4	import com.ericfeminella.collections.IMap;
  5	
  6	import name.carter.mark.flex.util.XMLUtils;
  7	import name.carter.mark.flex.util.collection.HashSet;
  8	import name.carter.mark.flex.util.collection.ISet;
  9	
 10	public class MDocument extends TaggableMNode
 11	{
 12		internal var idToNodeMap:IMap = new HashMap();
 13		private var prefixToLargestIdMap:IMap = new HashMap();
 14		internal var username:String;
 15
 16		public function MDocument(docElement:XML)
 17		{
 18			super(docElement, null);
 19			this.username = username;
 20			executeNodeFunc(function(node:MNode):Boolean {
 21				updateLargestIdMap(node.id); // might as well
 22				return true;
 23			});
 24			modified = false; // nothing changed yet
 25		}
 26		
 27		private function allNodes():Array {
 28			var result:Array = new Array();
 29			executeNodeFunc(function(node:MNode):Boolean {
 30				result.push(node);
 31				return true;
 32			});
 33			return result;
 34		}
 35		
 36		private function executeNodeFunc(nodeFunc:Function):void {
 37			for each (var element:XML in nodeElement..*.(localName() == MSuperSegment.TAG_NAME || localName() == MSegment.TAG_NAME || localName() == MSuperContent.TAG_NAME || localName() == MContent.TAG_NAME)) {
 38				var node:MNode = resolveElement(element);
 39				var moreToDo:Boolean = nodeFunc(node);
 40				if (!moreToDo) {
 41					break;
 42				}
 43			}			
 44		}
 45
 46		public function resolveId(id:String):MNode {
 47			return MUtils.getDescendantOrSelfNodeById(this, id);
 48		}
 49		
 50		public function resolveElement(element:XML):MNode {
 51			if (element == null) {
 52				return null;
 53			}
 54			if (element == nodeElement) {
 55				return this;
 56			}
 57			var nodeId:String = element.@id;
 58			var result:MNode = idToNodeMap.getValue(nodeId);
 59			if (result == null) {
 60				if (element.localName() == MSuperSegment.TAG_NAME) {
 61					result = new MSuperSegment(element, this);
 62				}
 63				else if (element.localName() == MSegment.TAG_NAME) {
 64					result = new MSegment(element, this);
 65				}
 66				else if (element.localName() == MSuperContent.TAG_NAME) {
 67					result = new MSuperContent(element, this);
 68				}
 69				else if (element.localName() == MContent.TAG_NAME) {
 70					result = new MContent(element, this);
 71				}
 72				else {
 73					return null;
 74				}
 75				registerNodeForId(nodeId, result);
 76			}
 77			else {
 78				// check the element has not changed
 79				if (result.nodeElement != element) {
 80				}
 81			}
 82			return result;
 83		}
 84		
 85		private function registerNodeForId(id:String, node:MNode):void {
 86			var existingNode:MNode = idToNodeMap.getValue(id) as MNode;
 87			if (existingNode != null) {
 88				if (existingNode != node) {
 89					throw new Error("Registering different node for id: " + id + ": " + node);					
 90				}
 91				else {
 92					// we have already registered this so nothing more to do
 93				}
 94			}
 95			else {
 96				idToNodeMap.put(id, node);
 97				node.modified = true; // its a new element so assume its modified
 98			}
 99		}
100		
101		public function createSuperSegment(segmentRange:MSegmentRange):MSuperSegment {
102			var ancestorSiblings:Array = MUtils.getCorrespondingAncestorSiblings(segmentRange.first, segmentRange.last);
103			var markupElement:XML = createElement(MSuperSegment.TAG_NAME, MSuperNode.ID_PREFIX);
104			XMLUtils.insertParentElement(markupElement, nodesToElements(ancestorSiblings));
105			return resolveElement(markupElement) as MSuperSegment;
106		}
107		
108		private static function nodesToElements(nodes:Array):XMLList {
109			var result:XMLList = new XMLList();
110			for each (var node:MNode in nodes) {
111				result += (node as MNode).nodeElement;
112			}
113			return result;
114		}
115		
116		public function createSuperContent(conceptRange:MContentRange):MSuperContent {
117			var ancestorSiblings:Array = MUtils.getCorrespondingAncestorSiblings(conceptRange.first, conceptRange.last);
118			var markupElement:XML = createElement(MSuperContent.TAG_NAME, MSuperNode.ID_PREFIX);
119			XMLUtils.insertParentElement(markupElement, nodesToElements(ancestorSiblings));
120			return resolveElement(markupElement) as MSuperContent;
121		}
122		
123		public function createSegmentElement(templateSegmentElement:XML = null):XML {
124			if (templateSegmentElement == null) {
125				return createElement(MSegment.TAG_NAME, MSegment.ID_PREFIX);
126			}
127			else {
128				// use the template - only for the attributes
129				var result:XML = templateSegmentElement.copy();
130				XMLUtils.removeAllElements(result.*);
131				result.@id = generateId(MSegment.ID_PREFIX);
132				return result;
133			}
134		}
135		
136		public function createContentElement(templateContentElement:XML = null):XML {
137			if (templateContentElement == null) {
138				return createElement(MContent.TAG_NAME, MContent.ID_PREFIX);
139			}
140			else {
141				// use the template - only for the attributes
142				var result:XML = templateContentElement.copy();
143				XMLUtils.removeAllElements(result.*);
144				result.@id = generateId(MContent.ID_PREFIX);
145				return result;
146			}
147		}
148		
149		internal function createElement(tagName:String, idPrefix:String):XML {
150			return <{tagName} id={generateId(idPrefix)}/>;
151		} 
152
153		internal function generateId(prefix:String):String {
154			var largestIdValue:int = prefixToLargestIdMap.getValue(prefix);
155			var newIdValue:int = largestIdValue + 1;
156			updateLargestIdValueMap(prefix, newIdValue);
157			return prefix + new String(newIdValue);
158		}
159		
160		private function updateLargestIdMap(id:String):void {
161			var prefix:String = id.replace(/\d/g, "");
162			var idValue:int = new int(id.replace(/\D/g, ""));
163			updateLargestIdValueMap(prefix, idValue);
164		}
165		
166		private function updateLargestIdValueMap(prefix:String, idValue:int):void {
167			var largestIdValue:int = prefixToLargestIdMap.getValue(prefix);
168			if (largestIdValue == 0 || largestIdValue < idValue) {
169				prefixToLargestIdMap.put(prefix, idValue);
170			}
171		}
172		
173		public function getAllPropertyValues(propName:String):ISet {
174			return getAllPropertyValuesInternal(this, propName);
175		}
176		
177		private static function getAllPropertyValuesInternal(node:MNode, propName:String):ISet {
178			var result:ISet = new HashSet();
179			var value:String = node.getPropertyValue(propName);
180			if (value != null) {
181				result.add(value);
182			}
183			for each (var child:MNode in node.childNodes) {
184				var childValues:ISet = getAllPropertyValuesInternal(child, propName);
185				result.addAll(childValues.toArray());
186			}
187			return result;
188		}
189	}
190}