/* ================= MISC ==================== */
function stringReplace(aString, strOrg, strNew)
{
  if (strOrg.length > 0)
  {    
    var index = aString.indexOf(strOrg);    
    while(index>-1)
    {
      var begin = aString.substr(0, index);
      aString = aString.substr(index + strOrg.length, aString.length - index + strOrg.length);
      aString = begin + strNew + aString;    
      index = aString.indexOf(strOrg);
    }
  }
  return aString;
}
function trimRight(aString, c)
{
  if (!c)
    c=' ';
  var tmpString = aString;
  while (tmpString.lastIndexOf(c) == tmpString.length-1 && tmpString!='')
  {
    tmpString = tmpString.substr(0, tmpString.length-1)
  }
  return(tmpString);
}

function trimLeft(aString, c)
{
  if (!c)
    c=' ';
  var tmpString = aString;
  while (tmpString.indexOf(c) == 0)
  {
    tmpString = tmpString.substr(1, tmpString.length)
  }
  return(tmpString);
}

function trim(aString, c)
{
  if (!c)
    c=' ';
  if (aString)
  {
      var tmpString = trimLeft(aString,c);
      tmpString = trimRight(tmpString, c);
      return(tmpString);
  }
  else 
    return "";
}

function trimset(aString, aTrimmers)
{
  for (var i=0;i<aTrimmers.length;++i)
  {
    aString = trim(aString, aTrimmers[i]);
  }
  return aString;
}
function CompareSingleTerms(term_in_list, term_in_selection, b_add_star)
{
  term_in_list=trim(term_in_list).toLowerCase();
  term_in_selection=trim(term_in_selection).toLowerCase();
  if (term_in_list == term_in_selection)
  {
    return cSingleTerm;
  }
  else /* Sterzoeken?? */
  {
    if (IsSameTerm(term_in_selection, term_in_list, b_add_star))
    {
      return cTermInStarredTerm;
    }
    
    var _starindex=term_in_selection.indexOf("*");
    if ((_starindex == -1) && b_add_star && (term_in_selection.length<6))
    {
      term_in_selection += '*';
      _starindex = term_in_selection.length-1;
//    }
    
//    if (_starindex>-1)
//    {
      term_in_list      = term_in_list.substr(0, _starindex);
      term_in_selection = term_in_selection.substr(0, _starindex);
      if (term_in_list == term_in_selection)
      {
        return cTermInStarredTerm;
      }
    }
  }
  return 0;
}
function isRange(str)
{
  return str.indexOf("-") > 0;
}

function Level(_value)
{
  if (!_value)
    return -1;
  _value = _value.replace("..", "-");
  if (_value.indexOf('-') > -1)
  {
    _value = _value.replace(/\*/g, "");
    var _values=_value.split('-');
    return Math.max(_values[0].length, _values[1].length);
  }
  else
  {
    return _value.length;
  }
}
function Range(_lower, _upper)
{
  this.lower=_lower;
  this.upper=_upper;
}
function SplitRange(_value, _len)
{
  if (_value.indexOf('-')>-1)
  {
    lower=_value.split('-')[0];
    upper=_value.split('-')[1];
    if (_len)
    {
      lower = Complete(this.lower, _len, 0);
      upper = Complete(this.upper, _len, 1);
    }
    return new Range(lower, upper);
  }
  else
    return null;
}
function IsSameTerm(s0, s1, b_add_star)
{
  //if (s0.charAt(s0.length-1) == "*")
  //{
  //  if(s1.length>s0.length)
  //    s1=s1.substring(0, s0.length);
  //}
  s0 = s0.replace(/\./g, "\\.");
  s0 = s0.replace(/\*/g, ".*");
  s0 = s0.replace(/\?/g, ".");
  s0 = "\\b" + s0 + (!b_add_star?"\\b":"");
  var regexp=new RegExp(s0);
  regexp.ignoreCase = true;
  var oMatch=regexp.exec(s1);
  return (oMatch != null);
  
  //var s2=s1.replace(regexp, "");
  //return (s2.length==0);
}
var cTermInRange       = 1;
var cSingleTerm        = 2;
var cTermInStarredTerm = 3;

/* ================= MISC ==================== */


/* ================= VARS/CONSTS ==================== */
var eParseStateeNone = 0;
var eParseStateeInQuotes = 1;
var m_quote = '"';
var m_NotOperator = "NIET";
var m_RangeOperator = "..";

var m_delimiters = new Array();
m_delimiters[0] = ' ';
m_delimiters[1] = ',';
m_delimiters[2] = m_quote;
m_delimiters[3] = '(';
m_delimiters[4] = ')';

/* =================== TOKEN CHECKERS ====================== */
function isBracketOpen(c)
{
  return (c == '(');
}
function isBracketClose(c)
{
  return (c == ')');
}
function isEscapeChar(c)
{
    return (c=='\\');
}
function isRangeOperator(str)
{
    return (trim(str) == m_RangeOperator);
}
function isNotOperator(str)
{

    if (str.indexOf(m_quote) == -1)
    {
        str = trimset(str, m_delimiters); // .Trim(m_delimiters); LET OP!!!
        return (str.toLowerCase() == m_NotOperator.toLowerCase()); // return str.Equals(m_NotOperator, StringComparison.CurrentCultureIgnoreCase);
    }
    else
        return false;// fixed term
}
function isDelimiter(c, b_use_space_as_separator)
{
    var result = false;
    if (c==' ' && !b_use_space_as_separator)
        return false;
    for (var i = 0; i < m_delimiters.length; ++i)
    {
        result = result || (m_delimiters[i] == c);
    }
    return result;
}

function Complete(_term, _length, upper_lower) // 1 = upper, 0 = lower
{
  _term = _term.replace("*", "");
  _term = _term.replace(/ /g, "");

  while (_term.length<_length)
    if (upper_lower == 1)
      _term += "z";
    else
      _term += "0";
  return _term;
}
function IsSublevelOf(_node2add, _existingnode)
{
  var oExisting=SplitRange(_existingnode, 6);
  if (oExisting != null) // is range
  {
    oNode2Add=SplitRange(_node2add, 6);
    if (oNode2Add != null)
      return ((oNode2Add.lower >= oExisting.lower) && (oNode2Add.upper <= oExisting.upper));
    else
      return ((Complete(_node2add, 6, 0) >= oExisting.lower) && (Complete(_node2add, 6, 1) <= oExisting.upper));
  }
  else
  {
    if (_node2add.length > _existingnode.length)
      return (_node2add.substring(0, _existingnode.length) == _existingnode);
  }
  return false;
}
/* =================== MSQUERY ====================== */

var cTokenTypeTerm         = 0;
var cTokenTypeBracketOpen  = 1;
var cTokenTypeBracketClose = 2;
var cTokenTypeOr           = 3;
var cTokenTypeNot          = 4;
var cTokenTypeRange        = 5;
var cTokenTypeEnd          = 6;

function Token(_type, _data)
{
  this.type = _type;
  this.data = _data; 
}
function MSQueryAddAndCreateToken(_type, _data)
{
  var oToken = new Token(_type, _data);
  this.tokens[this.tokens.length] = oToken;
}
function MSQueryGetTokens()
{
  for (var i=0;i<this.tokens.length;++i)
    document.write(this.tokens[i].type + ' ' + this.tokens[i].data + '<br>\n');
}
function MSQueryNormalizeTerm(term)
{
  if (this._type == 'zes') // postcode of branche
  {
    term = term.replace(/ /g, "");
    term = term.toUpperCase();
  }
  return trim(term);
}
function Value(_val, _pos)
{
  this.val = _val;
  this.pos = _pos;
}
/* MSQueryPutTokensInList
 * Verdeel tokens in this.tokens in een plus-array en min-array
 */
function MSQueryPutTokensInList()
{
  this.plus = new Array();
  this.min  = new Array();
  var bPreviousTokenIsRangeOperator = false;
  var curtokendata="";
  var current_group='plus';
  var iBracketsOpen = 0;
  var _pos = 0;
  this.tokens[this.tokens.length] = new Token(cTokenTypeEnd, "");
  for (var i=0;i<this.tokens.length;++i)
  {
    if (this.tokens[i].type == cTokenTypeBracketOpen)
    {
      if (current_group == 'min')
        iBracketsOpen++;
    }
    else if (this.tokens[i].type == cTokenTypeBracketClose)
    {
      if (current_group == 'min')
        iBracketsOpen--;
    }
    else if (this.tokens[i].type == cTokenTypeTerm)
    {
       curtokendata = this.tokens[i].data;
       if (current_group=='plus')
       {
         if (bPreviousTokenIsRangeOperator)
           this.plus[this.plus.length-1].val += "-"+this.normalizeTerm(curtokendata);
         else
         {
           this.plus[this.plus.length] = new Value(this.normalizeTerm(curtokendata), _pos++);
         }
       }
       else
       {
         if (bPreviousTokenIsRangeOperator  )
           this.min[this.min.length-1].val += "-"+ this.normalizeTerm(curtokendata);
         else
           this.min[this.min.length] = new Value(this.normalizeTerm(curtokendata), _pos++);
       }
      if (iBracketsOpen == 0) // Geen haakjes meer, reset naar groep plus
        current_group = 'plus';         
    }
    
    if (this.tokens[i].type == cTokenTypeNot) // switch naar groep min
      current_group = 'min';
    else if (iBracketsOpen == 0) // Geen haakjes meer, reset naar groep plus
      current_group = 'plus';     
          
    bPreviousTokenIsRangeOperator  = (this.tokens[i].type == cTokenTypeRange);
  }
}
function MSQueryAddToken(s_data)
{   
    if (s_data == '(')
      this.addAndCreateToken(cTokenTypeBracketOpen, "");
    else if (s_data == ')')
      this.addAndCreateToken(cTokenTypeBracketClose, "");
    else if (isNotOperator(trim(s_data)))
      this.addAndCreateToken(cTokenTypeNot, "");
    else if (isRangeOperator(s_data))
    {
        if (this.m_supportranges)
          this.addAndCreateToken(cTokenTypeRange, "");
        else
          this.addAndCreateToken(cTokenTypeTerm, "\"..\"");
    }
    else
    {
        if (s_data.indexOf(m_quote) == -1) // trim delimiters
            s_data = trimset(s_data, m_delimiters);
        else if (s_data.length > 2)
        { // quotes in s_data
            s_data = trim(s_data);
            if ((s_data.charAt(0) == m_quote) && (s_data.charAt(s_data.length-1) == m_quote))
                s_data = s_data.substr(1, s_data.length - 2); // voeg s_data toe zonder quotes
        }
        if (trim(s_data).length > 0) // voeg s_data toe als term
          this.addAndCreateToken(cTokenTypeTerm, trim(s_data));
    }
}
/* MSQueryTermInItem 
 * Valt term in range set_item, of  term == set_item (eventueel met wildcard *)
 * Returnt: 0, cSingleTerm, cTermInRange, cStarredTerm
 */
function MSQueryTermInItem(term, set_item)
{
  try
  {
    term=this.normalizeTerm(term);
    
    if (this._type=='werknemers')
    {
      if (this.m_supportranges && (set_item.indexOf('-') > -1)) // range
      {
        var abounds = SplitRange(set_item, 2);
        var lower=abounds.lower; // 1 wordt 10
        var upper=abounds.upper; // 1 wordt 1z
        /*var abounds=set_item.split('-'); var lower=CompleteWeknemersKlasse(abounds[0], 0); var upper=CompleteWeknemersKlasse(abounds[1], 1);*/
        if ((term >= lower) && (term <= upper))
        {
          return cTermInRange;
        }
      }
      else
      {
        return (CompareSingleTerms(term, set_item));
      }
    }
    else if (this._type=='zes') // branches en postcodes
    {
      if (this.m_supportranges && (set_item.indexOf('-') > -1)) // range
      {
        var abounds=SplitRange(set_item, 6);
        var lower=abounds.lower; // 4611 wordt 461100
        var upper=abounds.upper; // 4611 wordt 4611zz
        if ((term >= lower) && (term <= upper))
          return cTermInRange;
      }
      else
      {
        return (CompareSingleTerms(term, set_item, true));
      }
    }
    else if (this._type=='jaar')
    {
      if (this.m_supportranges && (set_item.indexOf('-') > -1)) // range
      {
        var abounds=SplitRange(set_item, 4);
        var lower=abounds.lower; //19 wordt 1900
        var upper=abounds.upper; //19 wordt 1999
        if ((term >= lower) && (term <= upper))
          return cTermInRange;
      }
      else
      {
        return (CompareSingleTerms(term, set_item));
      }
    }  
    else
    {
        return (CompareSingleTerms(term, set_item));
    }
  }
  catch(exc)
  {
    return 0;
  }
  return 0;
}

function MSQueryAddTerm(_term)
{
  _term = this.normalizeTerm(_term);
  if (this._type == 'branchetree')
  {
      this.termInSelection(_term, 'add');
  }
  else // andere lijsten
  {
      var test = this.termInSelection(_term);
      while(!test)  // term niet aanwezig
      {
        if (this._indexOfLastNegativeSearch > -1) // _term is gevonden als singleterm in min-array, verwijder _term uit dit array
          this.min.splice(this._indexOfLastNegativeSearch , 1);
        else // _term valt in een range in min-array, voeg _term toe aan plus-array    
          this.plus[this.plus.length] = new Value(_term, this.min.length+this.plus.length); 
          // this.plus[this.plus.length] = _term;  
        test = this.termInSelection(_term);      
      }
  }  
}
function MSQueryRemoveTerm(_term)
{
  _term = this.normalizeTerm(_term);
  if (this._type == 'branchetree')
  {
      this.termInSelection(_term, 'del');
  }
  else // andere lijsten
  {
    _term = this.normalizeTerm(_term);
    for (var i=0;i<this.plus.length;++i)
    {
      if (!this.m_supportranges || this.plus[i].val.indexOf('-')<0)
      { // als _term voorkomt als single-term in plus-array, verwijder _term uit plus-array
        if (trim(_term).toLowerCase() == trim(this.plus[i].val).toLowerCase()) 
          this.plus.splice(i,1);
      }
    }
    var test = this.termInSelection(_term);
    while (test)
    { // als _term valt onder range of wildcard waarde in plus-array -> voeg _term toe aan min-array
      if (test==cTermInRange || test==cTermInStarredTerm)
        this.min[this.min.length] = new Value(_term, this.min.length+this.plus.length); 
      test = this.termInSelection(_term);
    }
  }
}

function MSQueryTermInSelection(_term, _action)
{
  _term = this.normalizeTerm(_term);
  if (this._type == 'branchetree')
  {
      if (_action) // return boom gewijzigd a.d.h.v. _action
      {
        this.root = this.root.inTree(_term, _action);
        this.root.isRoot = true;
      }
      else
      {
        return this.root.inTree(_term);
      }
  }
  else
  {
      var _inSelection  = 0;
      var _asSingleTerm = false;
      this._indexOfLastPositiveSearch = -1;
      this._indexOfLastNegativeSearch = -1;
      _term = this.normalizeTerm(_term);
      // komt _term voor als single term in plus array?
      for (var i=0;i<this.plus.length;++i)
      {
        var test = this.termInItem(_term, this.plus[i].val);
        if (test == cSingleTerm)
        {
          this._indexOfLastPositiveSearch = i; // onthoudt deze positie, zodat dit item later eventueel uit het plus-array verwijderd kan worden
          _inSelection  = test;
          _asSingleTerm = true;
        }
      }
      // valt _term onder range/wildcard-waarde in plus array?
      for (var i=0;i<this.plus.length;++i)
      {
        var test = this.termInItem(_term, this.plus[i].val);
        if (test == cTermInRange || test == cTermInStarredTerm)
        {
          if (_asSingleTerm)
            return cSingleTerm; //komt voor in Range en als single term -> maakt niet uit of _term in min-array zit
          else
          {
            this._indexOfLastPositiveSearch = i; // onthoudt deze positie, zodat dit item later eventueel uit het plus-array verwijderd kan worden
            _inSelection = test;
          }
          break;
        }
      }
      if (_inSelection) // gevonden in plus-array, controleer nu voorkomen in min-array
      {
        for (var i=0;i<this.min.length;++i)
        {
          var test=this.termInItem(_term, this.min[i].val);
          if (test)
          {
            if (test == cSingleTerm)
              this._indexOfLastNegativeSearch = i; // onthoudt deze positie, zodat dit item later eventueel uit het min-array verwijderd kan worden
            _inSelection = 0;
            break;
          }
        }
      }
      return _inSelection;  
  }
}


function MSQueryQueryString()
{
    var s="";
    
    if (this._type == 'branchetree') 
    {
      s = this.root.info();
    } 
    else 
    {
        if (this.plus.length>0)
        {
          var pos=0;
          while (pos<=(this.plus.length+this.min.length))
          {
            for (var i=0;i<this.plus.length;++i)
            {  
               if (this.plus[i].pos == pos)
               {
                   if (this.m_supportranges && isRange(this.plus[i].val))
                     s += ", "+this.plus[i].val;
                   else
                     s += ", \""+this.plus[i].val+"\"";
               }
            }
            for (var i=0;i<this.min.length;++i)
            {
               if (this.min[i].pos == pos)
               {
                   if (this.m_supportranges && isRange(this.min[i].val))
                     s += " NIET "+this.min[i].val;
                   else
                     s += " NIET \""+this.min[i].val+"\"";
               }
            }
            
            pos++;
          }
        }
        if (false && this.plus.length>0)
        {
            for (var i=0;i<this.plus.length;++i)
            {  
               if (this.m_supportranges && isRange(this.plus[i].val))
                 s += ", "+this.plus[i].val;
               else
                 s += ", \""+this.plus[i].val+"\"";
            }
            for (var i=0;i<this.min.length;++i)
            {
               if (this.m_supportranges && isRange(this.min[i].val))
                 s += " NIET "+this.min[i].val;
               else
                 s += " NIET \""+this.min[i].val+"\"";
            }
        }
        else
        {
          this.min.length = 0;
        }
    }
    if (s.length>1)
    {
      if (s.charAt(0) == ",")
        s=s.substr(2);
    }        
    
    return s;
}

/* MSQueryBuildTree
 * Voeg eerst nodes toe van level 1 (bijv. 1) , dan van level 2 (bijv. 21-22), ... , level 6 (bijv. 432211)
 */
function MSQueryBuildTree()
{
  this.root = new MSNode();
  this.root.isRoot = true;

  var level=1;
  
  while (level<=6)
  {
      for (var i=0;i<this.plus.length;++i)
      {
        if (Level(this.plus[i].val) == level)
          this.root = this.root.inTree(this.plus[i].val, 'add');
      }
      for (var i=0;i<this.min.length;++i)
      {
        if (Level(this.min[i].val) == level)
          this.root = this.root.inTree(this.min[i].val, 'del');
      }
      ++level;
  }
  this.root.isRoot = true;
  var qry = this.root.info();
  if ((qry.length>1) && (qry.charAt(0) == ","))
    qry = qry.substr(2);
}
var g_dbg=false;
function DBG(msg, cond)
{
  if (g_dbg && cond)
    alert('===DBG===\n' + msg);
}

function MSQuery(s_querystring, b_ranges, b_space_is_separator, b_AllowStrangeCharacters, _type)
{
    this._indexOfLastPositiveSearch = -1;
    this._indexOfLastNegativeSearch = i;
    if (_type)
      this._type              = _type;
    else
      this._type              = '';
    this.m_supportranges      = b_ranges;
    this.addToken             = MSQueryAddToken;
    this.tokens               = new Array();
    this.addAndCreateToken    = MSQueryAddAndCreateToken;
    this.getTokens            = MSQueryGetTokens;
    this.putTokensInList      = MSQueryPutTokensInList;
    this.termInItem           = MSQueryTermInItem;
    this.termInSelection      = MSQueryTermInSelection;
    this.addTerm              = MSQueryAddTerm;
    this.removeTerm           = MSQueryRemoveTerm;
    this.queryString          = MSQueryQueryString;
    this.normalizeTerm        = MSQueryNormalizeTerm;
    
    this.buildTree            = MSQueryBuildTree;

    /* Vervang 5341 DC door 5341DC (En alle andere postcodes met spatie erin natuurlijk */
    if (this._type == 'postcode')
    {                
      re = /(\d{4})\s+(\w{1,2})([^\w])/g;
      s_querystring += " ";
      s_querystring = s_querystring.replace(re, "$1$2$3");
      this._type = 'zes';
    }
    /* Vervang NIET 10-20 door NIET (10-20) */
    if (this.m_supportranges)
    {
      s_querystring += " ";
      re = /(\w+)\s*-\s*(\w+)/g;
      s_querystring = s_querystring.replace(re, "($1-$2)");
    }

    if (!b_AllowStrangeCharacters && ((s_querystring.indexOf("!") > -1) || (s_querystring.indexOf("&") >-1)))
    {
        alert("De karakters & en ! hebben geen syntactische betekenis. Verwijderd u deze a.u.b. uit uw zoekopdracht.");            
        this.errorOccured = true;
        return;
        // throw("De karakters & en ! hebben geen syntactische betekenis. Verwijderd u deze a.u.b. uit uw zoekopdracht.");            return;
    }   
    var curterm             = "";
    var i                   = 0;
    var eState              = eParseStateeNone;
    var bLastWasEscapeChar  = false;
    if (this.m_supportranges) // VN.2006.10.11
        s_querystring = stringReplace(s_querystring, "-", "..");

    while (i < s_querystring.length || curterm != "")
    {
        if (i == s_querystring.length)
        {
            if (eState == eParseStateeInQuotes)
            {
              curterm += m_quote;
            }        
            this.addToken(curterm);
            curterm = "";
        }
        else
        {
            if (eState == eParseStateeInQuotes)
            {
                curterm += s_querystring.charAt(i);
                if (!bLastWasEscapeChar && s_querystring.charAt(i) == m_quote)
                {
                    this.addToken(curterm);
                    curterm = "";
                    eState = eParseStateeNone;
                }
            }
            else
            {
                if  (((i + 1) < s_querystring.length)  && (s_querystring.substr(i, 2) == m_RangeOperator) )
                {
                    this.addToken(curterm); // voeg eventuele eerdere term al toe, bijv. 4600aa..
                    curterm = "";
                    this.addToken(m_RangeOperator); // voeg .. toe
                    ++i;
                }
                else
                {
                    if (isBracketOpen(s_querystring.charAt(i)))
                    {
                        this.addToken(s_querystring.charAt(i));
                    }
                    else
                    {
                      if (!bLastWasEscapeChar && isDelimiter(s_querystring.charAt(i), b_space_is_separator))
                      {
                          this.addToken(curterm);
                          curterm = "";
                      }
                      curterm += s_querystring.charAt(i);
                      if (!bLastWasEscapeChar && s_querystring.charAt(i) == m_quote)
                      {
                          eState = eParseStateeInQuotes;
                      }
                      if (isBracketClose(s_querystring.charAt(i)))
                      {
                          this.addToken(s_querystring.charAt(i));
                          curterm = "";
                      }
                   }
                }
            }

            bLastWasEscapeChar = (isEscapeChar(s_querystring.charAt(i)));
            ++i;
        }
    }

    if (this.tokens.length>1)
    {
        if ((this.tokens[this.tokens.length-1].type == cTokenTypeOr) ||
            (this.tokens[this.tokens.length-1].type == cTokenTypeNot) || 
            (this.tokens[this.tokens.length-1].type == cTokenTypeRange))
        {
            this.tokens.splice(this.tokens.length-1, 1);
            // throw("Het gebruik van de range-operator (..) in uw zoekopdracht is niet correct.");
        }
     }
    this.putTokensInList();
    if (this._type == 'branchetree')
      this.buildTree();
}

/* ================ MSNODE ====================== */
function MSNode()
{
  this.value    = null;
  this.sign     = null;
  this.nodes    = null;
  this.add      = MSNodeAdd;
  this.info     = MSNodeInfo;
  this.inTree   = MSNodeInTree
}
function MSNode(_value, _sign, _nodes)
{
   this.value  = _value;
   this.sign   = _sign;
   this.nodes  = _nodes;
   this.add    = MSNodeAdd;
   this.info   = MSNodeInfo;
   this.inTree = MSNodeInTree
}
/* MSNodeInfo
 * Construct query
 */
function MSNodeInfo()
{
    var s="";
    if (this.value) // voeg value toe aan query
    {
        if (isRange(this.value)) // bijv. 10-20
          var _val = this.value;
        else
          var _val = "\"" + this.value + "\"";
        if (this.sign == '+')
          s+= ", " + _val;
        else
          s+= " NIET " + _val;
    }
    if (this.nodes) // voeg subnodes toe aan quey
    {
        for (var i=0;i<this.nodes.length;++i)
        {
          var _info=this.nodes[i].info();
          s+= _info;
        }
    }
    return s;
}
/* MSNodeInTree
 * als _action == null: return (_term in verzameling van waarden van gehele boom)
 * als _action == 'add': 
 *     als _term voorkomt in boom-node met negatieve range (bijv NIET 10-20)-> Voeg subnode toe aan deze node met waarde _term en sign== '+'
 *     als _term voorkomt als negatieve boom-node (bijv NIET 234563)        -> verwijder deze node
 * als _action == 'del': 
 *     als _term voorkomt in boom-node met range (bijv 10-20)-> Voeg subnode toe aan deze node met waarde _term en sign== '-'
 *     als _term voorkomt als boom-node                      -> verwijder deze node
 */
function MSNodeInTree(_term, _action)
{
      if (_action == 'add')
      {
        /* Als rootnode -> controleer of _term 'valt onder' een van de subnodes
         * zoniet: Voeg _term toe als subnode */
        if (this.isRoot)
        {
          var found=false;          
          if (this.nodes)
          {
             for (var i=0;i<this.nodes.length;++i)
             {
                  if (IsSublevelOf(_term, this.nodes[i].value))
                        found=true;  
             }
           }
           if (!found)
           {
             this.add(new MSNode(_term, '+', null));
             return this;
           }
        }
      }
      var b_result       = false; // wordt gebruikt als _action == null
      var node_result    = null;
      var _subnodesIndex = -1;
      /* Controleer eerst of _term valt onder een van de subnodes */
      if (this.nodes) 
      {
          for (var i=0;i<this.nodes.length;++i)
          { 
                if (CompareSingleTerms(_term, this.nodes[i].value, true) || IsSublevelOf(_term, this.nodes[i].value))
                {
                  _subnodesIndex=i;
                  break;
                }
          }
      }
      if (_subnodesIndex>-1)
      { 
        if (_action) /* _term valt onder subnode _subnodesIndex, roep functie recursief aan op deze subnode */
        {
          var oNode = this.nodes[_subnodesIndex].inTree(_term, _action);
          this.nodes[_subnodesIndex] = oNode;
        }
        else /* _term valt onder subnode _subnodesIndex, roep functie recursief aan op deze subnode */
          b_result = this.nodes[_subnodesIndex].inTree(_term);
      }
      else /* _term valt niet onder een van de subnodes */
      {
          if (this.value)
          {
              var cmp=0;
              var set_item = this.value;
              if (set_item.indexOf('-') > -1) // range
              {
                var abounds=set_item.split('-');
                var lower=Complete(abounds[0], 6, 0); /* Maak van bijv 234 -> 234000 */
                var upper=Complete(abounds[1], 6, 1); /* Maak van bijv 234 -> 234ZZZ */
                if ((Complete(_term, 6, 0) >= lower) && (Complete(_term, 6, 1) <= upper))
                {
                  cmp      =  cTermInRange;
                  b_result = (this.sign=='+');
                }
              }
              else
              {
                cmp=CompareSingleTerms(_term, set_item, true);
              }
              if (cmp) // cmp == cSingleTerm of cTermInRange of cStarredTerm
              {
                if (_action == 'del')
                {
                  if (cmp == cSingleTerm)
                  {
                    if (this.sign == '+') /* Verwijder node */
                    {
                      this.value = null;
                      this.nodes = null;
                      this.sign  = null;
                    }
                  }
                  else
                  {
                    if (this.sign=='+') /* cTermInRange of cStarredTerm, voeg _term toe met '-' sign */
                      this.add(new MSNode(_term, '-', null));
                  }
                } 
                else if (_action == 'add')
                {
                  if (cmp == cSingleTerm)
                  {
                    if (this.sign=='-') /* Verwijder negatieve node */
                    {
                      this.value = null;
                      this.nodes = null;
                      this.sign  = null;
                    }
                  }
                  else
                  {
                    if (this.sign=='-') /* cTermInRange of cStarredTerm */
                      this.add(new MSNode(_term, '+', null));/* _term valt onder negatieve range, voeg _term toe met '+' sign */ 
                  }
                } 
                else /* Geen _action, als sign=='+' -> _term zit erin */
                  b_result=(this.sign=='+');
              }
          }
      }
      if (_action)
        return this;
      else
        return b_result;
}

function MSNodeAdd(_node)
{
  if (!this.nodes || (this.nodes.length == 0)) // geen subnodes, voeg nieuwe node toe
  {
    this.nodes = new Array();
    this.nodes.push(_node);
  }
  else 
  {
    var added=false;
    for (var i=0;i<this.nodes.length;++i) 
    {
        if (IsSublevelOf(_node.value, this.nodes[i].value))
        {
          added=true; 
          this.nodes[i].add(_node); // node is sublevel van deze node, dus voeg hieraan toe
          break;
        }    
    }
    if (!added) // geen sublevel gevonden, voeg toe aan subnodes
      this.nodes.push(_node);
  }
}


/* ================ NOT USED =========== */
function _MSQueryAddTreeNode(node)
{
  if (!this._nodes)
    this._nodes = new Array();
    
  this._nodes[this._node.length] = node;
}

function _CompletePostcode(str, upper_lower) // 1 = upper, 0 = lower
{
  str = str.replace("*", "");
  str = str.replace(/ /g, "");
  
  while(str.length<6)
  {
    if (upper_lower == 1)
      str += "z";
    else
      str += "0";
  }
  return str;
}
function _CompleteJaartal(str, upper_lower) // 1 = upper, 0 = lower
{
  str = str.replace("*", "");
  str = str.replace(/ /g, "");
  
  while(str.length<4)
  {
    if (upper_lower == 1)
      str += "9";
    else
      str += "0";
  }
  return str;
}
function _CompleteWeknemersKlasse(str, upper_lower) // 1 = upper, 0 = lower
{
  str = str.replace("*", "");
  str = str.replace(/ /g, "");
  
  while(str.length<2)
  {
    if (upper_lower == 1)
      str += "9";
    else
      str += "0";
  }
  return str;
}


