RelationOneToMany.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /// <reference path="../Relation.ts" />
  2. /// <reference path="../../../Functions.ts" />
  3. class RelationHandlerStrictOneToMany extends RelationHandler {
  4. public setRelation (relation : Relation, left : any, right : any, value? : any) : boolean {
  5. // a LEFT must not circle in on itself
  6. // Is right any of the left's parents?
  7. let parents = this.getAllLeft(left);
  8. if (parents.indexOf(right) != -1) {
  9. console.warn("[Relation] Attempt to create a circular relation:", this, left, right);
  10. return false; // Allowing this would create a circular relation
  11. }
  12. // from this point on we'll guarantee that the new relation can be made.
  13. // Changes will occur, so "return false" is no longer acceptable.
  14. // a RIGHT can only point to a single LEFT
  15. this.unsetRight(right);
  16. return true;
  17. }
  18. public unset (thing : any) {
  19. this.unsetLeft(thing);
  20. this.unsetRight(thing);
  21. }
  22. public unsetLeft (left: any) {
  23. this.relations.forEach(relation => {
  24. relation.unsetLeft(left);
  25. });
  26. }
  27. public unsetRight (right : any) {
  28. this.relations.forEach(relation => {
  29. relation.unsetRight(right);
  30. });
  31. }
  32. // A many can only have one one
  33. public getLeft (right : any) {
  34. let result;
  35. for (let i = 0; i < this.relations.length; i++) {
  36. result = this.relations[i].getLeft(right);
  37. if (result != undefined) {
  38. return result;
  39. }
  40. }
  41. }
  42. /**
  43. * This returns all ones that are relevant.
  44. * So in a relationship like A -> B -> C and asking for C, this will return
  45. * B because it's related to C and then A because that's related to B.
  46. * @param right
  47. * @returns {Array}
  48. */
  49. public getAllLeft (right : any) {
  50. let newParent = this.getLeft(right);
  51. let parents = [];
  52. while (newParent != undefined ) {
  53. parents.push(newParent);
  54. newParent = this.getLeft(newParent);
  55. }
  56. return parents;
  57. }
  58. public getAllLeftType (right : any, type : any) {
  59. return this.getAllLeft(right).filter(left => {
  60. return left instanceof type;
  61. });
  62. }
  63. /**
  64. * Returns the highest One that can be found.
  65. * for A -> B -> C and asking for C, this would return A
  66. * as that's the one "originating" the other relations.
  67. * @param right
  68. * @returns {any}
  69. */
  70. public getLastLeft (right : any) {
  71. let parent = this.getLeft(right);
  72. let newParent = this.getLeft(parent);
  73. while (newParent != undefined) {
  74. parent = newParent;
  75. newParent = this.getLeft(parent);
  76. }
  77. return parent;
  78. }
  79. public getAllRight (left : any) {
  80. let rights = [];
  81. this.relations.forEach(relation => {
  82. rights.push(...relation.getRight(left));
  83. });
  84. arrayUnique(rights);
  85. return rights;
  86. }
  87. public getAllRightTypes (left : any, rightType : any) {
  88. return this.getAllRight(left).filter(right => {
  89. return right instanceof rightType;
  90. });
  91. }
  92. }
  93. class RelationOneToMany extends Relation {
  94. private valuesHash : {[idid : string] : any} = {};
  95. private oneMap = new Map<any, Array<any>>();
  96. private manyMap = new Map<any, any>();
  97. public getValue (left : any, right : any) {
  98. return this.valuesHash[Relation.createString(left, right)];
  99. }
  100. /**
  101. * Only relationships between Objets can have values
  102. * @param left
  103. * @param right
  104. * @param value
  105. */
  106. public setValue (left : any, right : any, value : any) {
  107. if (this.manyMap.get(right) == left) {
  108. let string = Relation.createString(left, right);
  109. if (string != undefined) {
  110. this.valuesHash[string] = value;
  111. }
  112. }
  113. }
  114. public setRelation (left : any, right : any, value? : any) {
  115. let proceed;
  116. if (this.handler != undefined) {
  117. proceed = this.handler.setRelation(this, left, right, value);
  118. }
  119. if (proceed) {
  120. // something on the left can't be on the right
  121. this.unsetRight(left);
  122. // something on the right can't be on the left
  123. this.unsetLeft(right);
  124. // something on the right can only have one left
  125. this.unsetRight(right);
  126. let string = Relation.createString(left, right);
  127. if (string != undefined) {
  128. this.valuesHash[string] = value;
  129. }
  130. this.manyMap.set(right, left);
  131. if (this.oneMap.get(left) == undefined) {
  132. this.oneMap.set(left, [right]);
  133. } else {
  134. this.oneMap.get(left).push(right);
  135. }
  136. }
  137. }
  138. public getLeft (right : any) {
  139. return this.manyMap.get(right);
  140. }
  141. public getAnyLeft () {
  142. let left = [];
  143. this.oneMap.forEach((value, key) => {
  144. left.push(key);
  145. });
  146. arrayUnique(left);
  147. return left;
  148. }
  149. public getAnyRight () {
  150. let rights = [];
  151. this.oneMap.forEach((value) => {
  152. rights.push(...value);
  153. });
  154. arrayUnique(rights);
  155. return rights;
  156. }
  157. public getAnyRightType (type : any) {
  158. return this.getAnyRight().filter(value => {
  159. return value instanceof type;
  160. });
  161. }
  162. public isRight (left : any, needle : any) {
  163. let right = this.oneMap.get(left);
  164. if (right != undefined) {
  165. return right.indexOf(needle) != -1;
  166. }
  167. return false;
  168. }
  169. public getRight (left : any) {
  170. let right = this.oneMap.get(left);
  171. if (right != undefined) {
  172. return [].concat(...right);
  173. }
  174. return [];
  175. }
  176. public getRightType (left : any, type : any) {
  177. return this.getRight(left).filter(right => {
  178. return right instanceof type;
  179. });
  180. }
  181. public getRightTypeOne (left : any, type : any) {
  182. let rights = this.getRightType(left, type);
  183. if (rights.length > 0) {
  184. return rights[0];
  185. }
  186. }
  187. public getRelationValue (left : any, right : any) {
  188. return this.valuesHash[Relation.createString(left, right)];
  189. }
  190. public unsetRight (right : any) {
  191. let left = this.manyMap.get(right);
  192. if (left != undefined) {
  193. let allRight = this.oneMap.get(left);
  194. allRight.splice(allRight.indexOf(right), 1);
  195. this.manyMap.delete(right);
  196. if (allRight.length == 0) {
  197. this.oneMap.delete(left);
  198. }
  199. let string = Relation.createString(left, right);
  200. if (string != undefined) {
  201. delete(this.valuesHash[string]);
  202. }
  203. }
  204. }
  205. public unsetLeft (left : any) {
  206. let allRight = this.oneMap.get(left);
  207. if (allRight != undefined) {
  208. allRight.forEach((right : any) => {
  209. this.manyMap.delete(right);
  210. let string = Relation.createString(left, right);
  211. if (string != undefined) {
  212. delete(this.valuesHash[string]);
  213. }
  214. });
  215. this.oneMap.delete(left);
  216. }
  217. }
  218. }