123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- /// <reference path="../Relation.ts" />
- /// <reference path="../../../Functions.ts" />
- class RelationHandlerStrictOneToMany extends RelationHandler {
- public setRelation (relation : Relation, left : any, right : any, value? : any) : boolean {
- // a LEFT must not circle in on itself
- // Is right any of the left's parents?
- let parents = this.getAllLeft(left);
- if (parents.indexOf(right) != -1) {
- console.warn("[Relation] Attempt to create a circular relation:", this, left, right);
- return false; // Allowing this would create a circular relation
- }
- // from this point on we'll guarantee that the new relation can be made.
- // Changes will occur, so "return false" is no longer acceptable.
- // a RIGHT can only point to a single LEFT
- this.unsetRight(right);
- return true;
- }
- public unset (thing : any) {
- this.unsetLeft(thing);
- this.unsetRight(thing);
- }
- public unsetLeft (left: any) {
- this.relations.forEach(relation => {
- relation.unsetLeft(left);
- });
- }
- public unsetRight (right : any) {
- this.relations.forEach(relation => {
- relation.unsetRight(right);
- });
- }
- // A many can only have one one
- public getLeft (right : any) {
- let result;
- for (let i = 0; i < this.relations.length; i++) {
- result = this.relations[i].getLeft(right);
- if (result != undefined) {
- return result;
- }
- }
- }
- /**
- * This returns all ones that are relevant.
- * So in a relationship like A -> B -> C and asking for C, this will return
- * B because it's related to C and then A because that's related to B.
- * @param right
- * @returns {Array}
- */
- public getAllLeft (right : any) {
- let newParent = this.getLeft(right);
- let parents = [];
- while (newParent != undefined ) {
- parents.push(newParent);
- newParent = this.getLeft(newParent);
- }
- return parents;
- }
- public getAllLeftType (right : any, type : any) {
- return this.getAllLeft(right).filter(left => {
- return left instanceof type;
- });
- }
- /**
- * Returns the highest One that can be found.
- * for A -> B -> C and asking for C, this would return A
- * as that's the one "originating" the other relations.
- * @param right
- * @returns {any}
- */
- public getLastLeft (right : any) {
- let parent = this.getLeft(right);
- let newParent = this.getLeft(parent);
- while (newParent != undefined) {
- parent = newParent;
- newParent = this.getLeft(parent);
- }
- return parent;
- }
- public getAllRight (left : any) {
- let rights = [];
- this.relations.forEach(relation => {
- rights.push(...relation.getRight(left));
- });
- arrayUnique(rights);
- return rights;
- }
- public getAllRightTypes (left : any, rightType : any) {
- return this.getAllRight(left).filter(right => {
- return right instanceof rightType;
- });
- }
- }
- class RelationOneToMany extends Relation {
- private valuesHash : {[idid : string] : any} = {};
- private oneMap = new Map<any, Array<any>>();
- private manyMap = new Map<any, any>();
- public getValue (left : any, right : any) {
- return this.valuesHash[Relation.createString(left, right)];
- }
- /**
- * Only relationships between Objets can have values
- * @param left
- * @param right
- * @param value
- */
- public setValue (left : any, right : any, value : any) {
- if (this.manyMap.get(right) == left) {
- let string = Relation.createString(left, right);
- if (string != undefined) {
- this.valuesHash[string] = value;
- }
- }
- }
- public setRelation (left : any, right : any, value? : any) {
- let proceed;
- if (this.handler != undefined) {
- proceed = this.handler.setRelation(this, left, right, value);
- }
- if (proceed) {
- // something on the left can't be on the right
- this.unsetRight(left);
- // something on the right can't be on the left
- this.unsetLeft(right);
- // something on the right can only have one left
- this.unsetRight(right);
- let string = Relation.createString(left, right);
- if (string != undefined) {
- this.valuesHash[string] = value;
- }
- this.manyMap.set(right, left);
- if (this.oneMap.get(left) == undefined) {
- this.oneMap.set(left, [right]);
- } else {
- this.oneMap.get(left).push(right);
- }
- }
- }
- public getLeft (right : any) {
- return this.manyMap.get(right);
- }
- public getAnyLeft () {
- let left = [];
- this.oneMap.forEach((value, key) => {
- left.push(key);
- });
- arrayUnique(left);
- return left;
- }
- public getAnyRight () {
- let rights = [];
- this.oneMap.forEach((value) => {
- rights.push(...value);
- });
- arrayUnique(rights);
- return rights;
- }
- public getAnyRightType (type : any) {
- return this.getAnyRight().filter(value => {
- return value instanceof type;
- });
- }
- public isRight (left : any, needle : any) {
- let right = this.oneMap.get(left);
- if (right != undefined) {
- return right.indexOf(needle) != -1;
- }
- return false;
- }
- public getRight (left : any) {
- let right = this.oneMap.get(left);
- if (right != undefined) {
- return [].concat(...right);
- }
- return [];
- }
- public getRightType (left : any, type : any) {
- return this.getRight(left).filter(right => {
- return right instanceof type;
- });
- }
- public getRightTypeOne (left : any, type : any) {
- let rights = this.getRightType(left, type);
- if (rights.length > 0) {
- return rights[0];
- }
- }
- public getRelationValue (left : any, right : any) {
- return this.valuesHash[Relation.createString(left, right)];
- }
- public unsetRight (right : any) {
- let left = this.manyMap.get(right);
- if (left != undefined) {
- let allRight = this.oneMap.get(left);
- allRight.splice(allRight.indexOf(right), 1);
- this.manyMap.delete(right);
- if (allRight.length == 0) {
- this.oneMap.delete(left);
- }
- let string = Relation.createString(left, right);
- if (string != undefined) {
- delete(this.valuesHash[string]);
- }
- }
- }
- public unsetLeft (left : any) {
- let allRight = this.oneMap.get(left);
- if (allRight != undefined) {
- allRight.forEach((right : any) => {
- this.manyMap.delete(right);
- let string = Relation.createString(left, right);
- if (string != undefined) {
- delete(this.valuesHash[string]);
- }
- });
- this.oneMap.delete(left);
- }
- }
- }
|