Script.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using System.Reflection;
  7. using System.Xml.Linq;
  8. namespace BuildOurOwnBabylonJS
  9. {
  10. public class Script
  11. {
  12. public const string TAGNAME = "script";
  13. public const string ID_ATTRIBUTENAME = "id";
  14. public const string SRC_ATTRIBUTENAME = "src";
  15. public const string DEPENDSON_TAGNAME = "dependsOn";
  16. public const string SCRIPTREF_ATTRIBUTENAME = "scriptref";
  17. private string _id;
  18. public string Id { get { return _id; } }
  19. private string _src;
  20. public string Src { get { return _src; } }
  21. private List<Script> _dependencies = Enumerable.Empty<Script>().ToList();
  22. public IEnumerable<Script> Dependencies { get { return _dependencies; } }
  23. private static Dictionary<string, Script> _scripts = new Dictionary<string, Script>();
  24. public static IDictionary<string, Script> Scripts { get { return _scripts; } }
  25. private bool _written;
  26. // caution: it doesn't take into account xml namespaces
  27. public static Script Load(XElement scriptElement,
  28. IEnumerable<XElement> scriptElements)
  29. {
  30. if (scriptElement == null)
  31. throw new ArgumentNullException("script");
  32. if (scriptElements == null)
  33. throw new ArgumentNullException("root");
  34. if (scriptElement.Name != TAGNAME)
  35. throw new Exception("Wrong tag name");
  36. var srcAttribute = scriptElement.Attribute(SRC_ATTRIBUTENAME);
  37. if (srcAttribute == null)
  38. throw new Exception("Must have the " + SRC_ATTRIBUTENAME + " attribute");
  39. var src = srcAttribute.Value;
  40. var id = src;
  41. var idAttribute = scriptElement.Attribute(ID_ATTRIBUTENAME);
  42. if (idAttribute != null && !String.IsNullOrEmpty(idAttribute.Value))
  43. id = idAttribute.Value;
  44. Script _this;
  45. if (_scripts.TryGetValue(id, out _this))
  46. return _this;
  47. _this = new Script();
  48. _this._id = id;
  49. _this._src = src;
  50. _scripts.Add(_this.Id, _this);
  51. var dependsOnFiles = scriptElement.Elements(DEPENDSON_TAGNAME);
  52. foreach (var dependOnFile in dependsOnFiles)
  53. {
  54. var scriptrefAttribute = dependOnFile.Attribute(SCRIPTREF_ATTRIBUTENAME);
  55. if (scriptrefAttribute == null)
  56. throw new Exception(id + ": its dependency must have the " + SCRIPTREF_ATTRIBUTENAME + " attribute");
  57. var scriptref = scriptrefAttribute.Value;
  58. Script scriptRef;
  59. if (!_scripts.TryGetValue(scriptref, out scriptRef))
  60. {
  61. var newScriptElement = scriptElements
  62. .FirstOrDefault(script =>
  63. {
  64. var idAttr = script.Attribute(ID_ATTRIBUTENAME);
  65. if (idAttr == null)
  66. return false;
  67. return idAttr.Value == scriptref;
  68. });
  69. if (newScriptElement == null)
  70. throw new Exception(id +": couldn't find its dependency '" + scriptref + "'");
  71. scriptRef = Load(newScriptElement, scriptElements);
  72. }
  73. if (scriptRef == null)
  74. throw new Exception(id + ": couldn't find its dependency '" + scriptref + "'");
  75. _this._dependencies.Add(scriptRef);
  76. }
  77. return _this;
  78. }
  79. public void GetDependenciesList(ref List<string> result,
  80. List<string> dependenciesLoopStack = null)
  81. {
  82. dependenciesLoopStack = dependenciesLoopStack ?? new List<string>(_scripts.Count);
  83. if (dependenciesLoopStack.FirstOrDefault(src => src == _src) != null)
  84. throw new Exception(_id + ": there is a dependency loop");
  85. if (_written)
  86. {
  87. var dlsC = dependenciesLoopStack.Count;
  88. if (dlsC == 0)
  89. return;
  90. var lastId = dependenciesLoopStack[dlsC - 1];
  91. for(var i = 0; i < result.Count ; ++i)
  92. {
  93. var tmp = result[i];
  94. if (tmp != _src)
  95. continue;
  96. var firstToAdd = -1;
  97. for (var j = 0 ; j < dependenciesLoopStack.Count ; ++j)
  98. {
  99. var k = 0;
  100. var dls = dependenciesLoopStack[j];
  101. if (firstToAdd == -1)
  102. {
  103. for (; k < i; ++k)
  104. {
  105. if (dls == result[k])
  106. break;
  107. }
  108. if (k < i)
  109. continue;
  110. firstToAdd = j;
  111. }
  112. // i + j - firstToAdd should always be < result.Count - 1
  113. result[i + j - firstToAdd] = dls;
  114. }
  115. var moveTo = i + (dlsC - firstToAdd);
  116. // moveTo should always be < result.Count - 1
  117. if (result[moveTo] != lastId)
  118. {
  119. for (var k = result.Count - 1; k > moveTo; --k)
  120. {
  121. result[k] = result[k-1];
  122. }
  123. }
  124. result[moveTo] = tmp;
  125. break;
  126. }
  127. return;
  128. }
  129. _written = true;
  130. dependenciesLoopStack.Add(_src);
  131. result.Add(_src);
  132. foreach (var dependency in _dependencies)
  133. {
  134. dependency.GetDependenciesList(ref result, dependenciesLoopStack);
  135. }
  136. dependenciesLoopStack.RemoveAll(src => src == _src); // Remove(_src) should be enough
  137. }
  138. }
  139. }