/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

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