export interface Condition { [ name ] : any ; } export enum Connector { AND , OR } export class Q { children : ( Q | Condition ) [ ] = [ ] ; connector : Connector = Connector . AND ; negated : boolean = false ; convertCondition ( cond ) { var result = [ ] ; if ( typeof cond == "object" && cond . hasOwnProperty ( 'length' ) ) { result . push ( ... ( cond as Q [ ] ) ) ; } else { result . push ( cond ) ; } return result ; } constructor ( children = null , connector = Connector . AND , negated = false ) { if ( children ) { if ( typeof children == "object" && children . hasOwnProperty ( 'length' ) ) { this . children . push ( ... children as Q [ ] ) ; } else { this . children . push ( children ) ; } } this . connector = connector ; this . negated = negated ; } _combine ( other , conn ) { var obj = new Q ( ) ; obj . connector = conn ; obj . add ( this , conn ) ; obj . add ( other , conn ) ; return obj ; } _new_instance ( children , connector = Connector . AND , negated = false ) { var obj = new Q ( ) ; obj . children = children . slice ( ) ; obj . connector = connector ; obj . negated = negated ; return obj ; } clone ( ) { var obj = new Q ( ) ; obj . children = this . children . slice ( ) ; obj . connector = this . connector ; obj . negated = this . negated ; return obj ; } swapNegate ( ) { var clone = this . clone ( ) ; clone . negated = ! clone . negated ; return clone ; } add ( q , conn ) { if ( this . connector == conn ) { if ( q instanceof Q && ! q . negated && ( q . connector == conn || q . children . length == 1 ) ) { this . children . push ( ... q . children ) ; return this ; } else { this . children . push ( q ) ; return q ; } } else { var obj = this . _new_instance ( this . children , this . connector , this . negated ) ; this . connector = conn ; this . children = [ obj , q ] ; return q ; } } _normaliseCondition ( cond , negated = false ) { if ( cond instanceof Q ) { if ( cond . negated == false && negated == true ) { return this . _new_instance ( cond . children , cond . connector , negated ) ; } else if ( cond . negated == true && negated == true ) { return this . _new_instance ( cond . children , cond . connector ) ; } return cond ; } else { return new Q ( cond , undefined , negated ) ; } } AND ( cond ) { return this . _combine ( this . _normaliseCondition ( cond ) , Connector . AND ) ; } OR ( cond ) { return this . _combine ( this . _normaliseCondition ( cond ) , Connector . OR ) ; } AND_NOT ( cond ) { return this . _combine ( this . _normaliseCondition ( cond , true ) , Connector . AND ) ; } OR_NOT ( cond ) { return this . _combine ( this . _normaliseCondition ( cond , true ) , Connector . OR ) ; } }