/*
 * Copyright (C) 2005-2012 Diego Perini
 * All rights reserved.
 *
 * nwevents.js - Javascript Event Manager
 *
 * Author: Diego Perini <diego.perini at gmail com>
 * Version: 1.2.4
 * Created: 20051016
 * Release: 20120101
 *
 * License:
 *  http://javascript.nwbox.com/NWEvents/MIT-LICENSE
 * Download:
 *  http://javascript.nwbox.com/NWEvents/nwevents.js
 */

(function(global) {

  var version = 'nwevents-1.2.4',

  Event = typeof exports === 'object' ? exports : (
    (global.NW || (global.NW = { })) &&
    (global.NW.Event || (global.NW.Event = { }))),

  // default to DOM2
  USE_DOM2 = true,

  // event phases constants
  CUSTOM = 0, CAPTURING_PHASE = 1, AT_TARGET = 2, BUBBLING_PHASE = 3,

  // event collections and predefined DOM0 register
  DOMEvents = { }, Delegates = { }, Listeners = { }, Predefined = { },

  // initial script load context
  viewport = global,
  context = global.document || { },
  root = context.documentElement || { },

  Keyboard_Events = {
    // keypress deprecated in favor of textInput
    keypress: 1, keydown: 1, keyup: 1
  },

  Mouse_Events = {
    // contextmenu is a non standard event
    contextmenu: 1,
    // dblclick is a non standard event
    click: 1, dblclick: 1,
    mouseout: 1, mouseover: 1,
    mouseenter: 1, mouseleave: 1,
    mousemove: 1, mousedown: 1, mouseup: 1
  },

  Touch_Events = {
    touchup: 1, touchdown: 1,
    // touch devices like iPhone/iPod
    touchend: 1, touchmove: 1, touchstart: 1, touchcancel: 1,
    gestureend: 1, gesturemove: 1, gesturestart: 1, gesturecancel: 1
  },

  Text_Events = {
    // input/textarea elements
    textInput: 1, keydown: 1, keyup: 1
  },

  UI_Events = {
    // keyboard focus and activation events
    blur: 1, focus: 1, focusin: 1, focusout: 1,
    DOMActivate: 1, DOMFocusIn: 1, DOMFocusOut: 1
  },

  Events = {
    // host objects and binary content related
    abort: 1, error: 1,
    load: 1, unload: 1, resize: 1, scroll: 1,
    // forms and control elements related
    change: 1, input: 1, select: 1, reset: 1, submit: 1
  },

  EventCollection =
    function() {
      return {
        items: [],
        calls: [],
        parms: [],
        wraps: []
      };
    },

  /* ============================ FEATURE TESTING =========================== */

  implementation = context.implementation ||
    { hasFeature: function() { return false; } },

  // detect activation capabilities,
  // Firefox 3+, Safari 3+, Opera 9+, IE
  hasActive = 'activeElement' in context ?
    (function() {
      try {
        return (context.activeElement = null) || true;
      } catch(e) {
        return false;
      }
    }) : true,

  hasFeature =
    function(t, v) {
      return implementation.hasFeature(t, v || '');
    },

  hasInterface = hasFeature('Events', '') ?
    function(t) {
      try {
        return typeof context.createEvent(t)['init' + t] === 'function';
      } catch (e) {
        return false;
      }
    } :
    function(t) {
      return false;
    },

  // detect native methods
  isNative = (function() {
    var s = (global.open + '').replace(/open/g, '');
    return function(object, method) {
      var m = object ? object[method] : false, r = new RegExp(method, 'g');
      return !!(m && typeof m !== 'string' && s === (m + '').replace(r, ''));
    };
  })(),

  // detect event model in use
  W3C_MODEL =
    isNative(root, 'dispatchEvent') &&
    isNative(root, 'addEventListener') &&
    isNative(root, 'removeEventListener') &&
    isNative(context, 'createEvent'),

  MSIE_MODEL = !W3C_MODEL &&
    isNative(root, 'fireEvent') &&
    isNative(root, 'attachEvent') &&
    isNative(root, 'detachEvent') &&
    isNative(context, 'createEventObject'),

  SUPPORT_EVENTS = hasInterface('Event'),

  SUPPORT_UI_EVENTS = hasInterface('UIEvent'),

  SUPPORT_TEXT_EVENTS = hasInterface('TextEvent'),

  SUPPORT_TOUCH_EVENTS = hasInterface('TouchEvent'),

  SUPPORT_MOUSE_EVENTS = hasInterface('MouseEvent'),

  SUPPORT_KEYBOARD_EVENTS = hasInterface('KeyboardEvent'),

  // non standard Firefox KeyEvent
  SUPPORT_KEY_EVENTS = 'KeyEvent' in global &&
    typeof KeyEvent.prototype.initEvent === 'function',

  KEYBOARD_FIX = SUPPORT_KEYBOARD_EVENTS ? '' : 's',

  KEYBOARD_EVENT = SUPPORT_KEY_EVENTS ? 'KeyEvent' :
    SUPPORT_KEYBOARD_EVENTS ? 'KeyboardEvent' :
    SUPPORT_UI_EVENTS ? 'UIEvent' : 'Event',
  // end non standard...

  testTarget = context.createDocumentFragment &&
    context.createDocumentFragment().
      appendChild(context.createElement('div')),

  special = /^onload|onunload|onbeforeunload|oninput$/,

  supported = { },

  isSupported =
    function(type, element) {
      var handler;
      type = 'on' + type;
      if (typeof supported[type] !== 'undefined') {
        return supported[type];
      } else {
        supported[type] = false;
      }
      element || (element = testTarget);
      if (type in element) {
        supported[type] = true;
      } else if (special.test(type)) {
        if (type in global) {
          supported[type] = true;
        } else {
          handler = global[type];
          context.createElement('body').setAttribute(type, 'return');
          if (typeof global[type] === 'function') {
            supported[type] = true;
          }
          global[type] = handler;
        }
      } else {
        element.setAttribute(type, 'return');
        if (typeof element[type] === 'function') {
          supported[type] = true;
        }
      }
      return supported[type];
    },

  /* ============================ UTILITY METHODS =========================== */

  // get document from element
  getDocument =
    function(e) {
      return e.ownerDocument || e.document || e;
    },

  // get window from document
  getWindow = 'parentWindow' in context ?
    function(d) {
      return d.parentWindow || window;
    } : 'defaultView' in context && global === context.defaultView ?
    function(d) {
      return d.defaultView || window;
    } : global.frames ?
    function(d) {
      // fix for older Safari 2.0.x returning
      // [object AbstractView] instead of [window]
      if (global.frames.length === 0 && context === d) {
        return global;
      } else {
        for (var i in global.frames) {
          if (global.frames[i].document === d) {
            return global.frames[i];
          }
        }
      }
      return global;
    } :
    function() { return global; },

  // fix IE event properties to comply with w3c standards
  fixEvent =
    function(element, event, capture) {
      // needed for DOM0 events
      event || (event = getWindow(getDocument(element)).event);
      // bound element (listening the event)
      event.currentTarget = element;
      // fired element (triggering the event)
      event.target = event.srcElement || element;
      // add preventDefault and stopPropagation methods
      event.preventDefault = preventDefault;
      event.stopPropagation = stopPropagation;
      // bound and fired element are the same AT_TARGET
      event.eventPhase = capture ? CAPTURING_PHASE : BUBBLING_PHASE;
      // related element (routing of the event)
      event.relatedTarget =
        event[(event.target === event.fromElement ? 'to' : 'from') + 'Element'];
      // set time event was fixed
      event.timeStamp = +new Date;
      return event;
    },

  // prevent default action
  preventDefault =
    function() {
      this.returnValue = false;
    },

  // stop event propagation
  stopPropagation =
    function() {
      this.cancelBubble = true;
    },

  // block any further event processing
  stop =
    function(event) {
      if (event.preventDefault) {
        event.preventDefault();
      } else {
        event.returnValue = false;
      }
      if (event.stopPropagation) {
        event.stopPropagation();
      } else {
        event.cancelBubble = true;
      }
      return false;
    },

  // check collection for registered event,
  // match element, handler and capture
  isRegistered =
    function(registry, element, type, handler, capture) {
      var i, l, found = false;
      if (registry[type] && registry[type].items) {
        for (i = 0, l = registry[type].items.length; l > i; ++i) {
          if (
            registry[type].items[i] === element &&
            registry[type].calls[i] === handler &&
            registry[type].parms[i] === capture) {
            found = i;
            break;
          }
        }
      }
      return found;
    },

  // list event handlers bound to
  // a given object for each type
  getRegistered =
    function(registry, element, type, capture) {
      var i, j, l, results = [ ];
      type || (type = '*');
      element || (element = '*');
      registry || (registry = Listeners);
      for (i in registry) {
        if (type.indexOf(i) > -1 || type === '*') {
          for (j = 0, l = registry[i].items.length; j < l; j++) {
            if (element === '*' || (element === registry[i].items[j] &&
              (capture === '*' || capture === registry[i].parms[j]))) {
              results.push(registry[i].calls[j]);
            }
          }
        }
      }
      return results;
    },

  // process listeners chain for event type
  processListeners =
    function(event) {
      var i, l, items, calls, parms, phase, valid,
      done = false, result = true, type = event.type;

      if (Listeners[type] && Listeners[type].items) {

        // cache eventPhase access
        phase = event.eventPhase;

        if (!event.propagated && FormActivationEvents[type]) {
          return true;
        }

        // only AT_TARGET event.target === event.currentTarget
        if (phase !== AT_TARGET && event.target === this) {
          if (event.propagated && phase === CAPTURING_PHASE) return true;
          phase = event.eventPhase = AT_TARGET;
        }

        // make a copy of the Listeners[type] array
        // since it can be modified run time by the
        // events deleting themselves or adding new
        items = Listeners[type].items.slice();
        calls = Listeners[type].calls.slice();
        parms = Listeners[type].parms.slice();

        // process chain in fifo order
        for (i = 0, l = items.length; l > i; ++i) {
          valid = false;
          if (items[i] === this) {
            switch (phase) {
              case CAPTURING_PHASE:
                if (!!parms[i]) {
                  valid = true;
                }
                break;
              case BUBBLING_PHASE:
                if (!parms[i]) {
                  valid = true;
                }
                break;
              case AT_TARGET:
                if (!done && (done = true)) {
                  valid = true;
                }
                break;
              // Safari 4.x load events
              // may have eventPhase === 0
              default:
                valid = true;
                break;
            }
          }

          if (valid && (result = calls[i].call(this, event)) === false) break;
        }

        if (result === false) stop(event);

      }

      return result;
    },

  // process delegates chain for event type
  processDelegates =
    function(event) {
      var i, l,
        items, calls, parms, target,
        result = true, type = event.type;

      if (Delegates[type] && Delegates[type].items) {

        // make a copy of the Delegates[type] array
        // since it can be modified run time by the
        // events deleting themselves or adding new
        items = Delegates[type].items.slice();
        calls = Delegates[type].calls.slice();
        parms = Delegates[type].parms.slice();

        // process chain in fifo order
        bubblingLoop:
        for (i = 0, l = items.length; l > i; ++i) {
          // skip processing unregistered elements
          if (items[i] !== this) continue;
          // check element's ancestors up
          // to the currentTarget ('this')
          target = event.target;
          // bubble events up to parent nodes
          while (target && target.nodeType === 1) {
            if (NW.Dom.match(target, parms[i])) {
              // execute registered function in element scope
              if (calls[i].call(target, event) === false) {
                result = false;
                break bubblingLoop;
              }
            }
            if (target === this) break;
            target = target.parentNode;
          }
        }

      }

      return result;
    },

  // register an event instance and its parameters
  register =
    function(registry, element, type, handler, capture) {
      registry[type] || (registry[type] = new EventCollection);
      // append instance parameters to the registry
      registry[type].items.push(element);
      registry[type].calls.push(handler);
      registry[type].parms.push(capture);
    },

  // unregister an event instance and its parameters
  unregister =
    function(registry, element, type, handler, capture, key) {
      // remove instance parameters from the registry
      registry[type].items.splice(key, 1);
      registry[type].calls.splice(key, 1);
      registry[type].parms.splice(key, 1);
      registry[type].items.length === 0 && delete registry[type];
    },

  // lazy definition for addEventListener / attachEvent
  append = W3C_MODEL && USE_DOM2 ?
    function(element, type, handler, capture) {
      // use DOM2 event registration
      element.addEventListener(type, handler, !!capture);
    } : MSIE_MODEL && USE_DOM2 ?
    function(element, type, handler, capture) {
      // use MSIE event registration
      var key = DOMEvents[type].wraps.push(function(event) {
        return handler.call(element, fixEvent(element, event, !!capture));
      });
      element.attachEvent('on' + type, DOMEvents[type].wraps[key - 1]);
    } :
    function(element, type, handler, capture) {
      var callback = Predefined['on' + type] = element['on' + type] || new Function();
      // use DOM0 event registration
      element['on' + type] = function(event) {
        var result;
        event || (event = fixEvent(this, event, !!capture));
        result = handler.call(this, event);
        callback.call(this, event);
        return result;
      };
    },

  // lazy definition for removeEventListener / detachEvent
  remove = W3C_MODEL && USE_DOM2 ?
    function(element, type, handler, capture) {
      // use DOM2 event registration
      element.removeEventListener(type, handler, !!capture);
    } : MSIE_MODEL && USE_DOM2 ?
    function(element, type, handler, capture, key) {
      // use MSIE event registration
      element.detachEvent('on' + type, DOMEvents[type].wraps[key]);
      DOMEvents[type].wraps.splice(key, 1);
    } :
    function(element, type, handler, capture) {
      // use DOM0 event registration
      element['on' + type] = Predefined['on' + type];
      delete Predefined['on' + type];
    },

  // append an event handler
  set =
    function(element, type, handler, capture) {
      var i, k, l, types;
      if (typeof type === 'string') {
        types = type.split(' ');
        for (i = 0, l = types.length; l > i; ++i) {
          k = isRegistered(DOMEvents, element, types[i], handler, !!capture);
          if (k === false) {
            register(DOMEvents, element, types[i], handler, !!capture);
            append(element, types[i], handler, capture);
          }
        }
      } else {
        // a hash of "rules" containing type-handler pairs
        for (i in type) {
          set(element, i, type[i], capture);
        }
      }
      return this;
    },

  // remove an event handler
  unset =
    function(element, type, handler, capture) {
      var i, k, l, types;
      if (typeof type === 'string') {
        types = type.split(' ');
        for (i = 0, l = types.length; l > i; ++i) {
          k = isRegistered(DOMEvents, element, types[i], handler, !!capture);
          if (k !== false) {
            remove(element, types[i], handler, capture, k);
            unregister(DOMEvents, element, types[i], handler, !!capture, k);
          }
        }
      } else {
        // a hash of "rules" containing type-handler pairs
        for (i in type) {
          unset(element, i, type[i], capture);
        }
      }
      return this;
    },

  // append an event listener
  listen =
    function(element, type, handler, capture) {
      var i, k, l, types;
      if (typeof type === 'string') {
        types = type.split(' ');
        for (i = 0, l = types.length; l > i; ++i) {
          k = isRegistered(Listeners, element, types[i], handler, !!capture);
          if (k === false) {
            register(Listeners, element, types[i], handler, !!capture);
            if (getRegistered(Listeners, element, types[i], !!capture).length === 1) {
              set(element, types[i], processListeners, capture);
            }
          }
        }
      } else {
        // a hash of "rules" containing type-handler pairs
        for (i in type) {
          listen(element, i, type[i], capture);
        }
      }
      return this;
    },

  // remove an event listener
  unlisten =
    function(element, type, handler, capture) {
      var i, k, l, types;
      if (typeof type === 'string') {
        types = type.split(' ');
        for (i = 0, l = types.length; l > i; ++i) {
          k = isRegistered(Listeners, element, types[i], handler, !!capture);
          if (k !== false) {
            if (getRegistered(Listeners, element, types[i], !!capture).length === 1) {
              unset(element, types[i], processListeners, capture);
            }
            unregister(Listeners, element, types[i], handler, !!capture, k);
          }
        }
      } else {
        // a hash of "rules" containing type-handler pairs
        for (i in type) {
          unlisten(element, i, type[i], capture);
        }
      }
      return this;
    },

  // append an event delegate
  delegate =
    // delegated element defaults to document
    // it is a required parameter with iframes
    function(selector, type, handler, element) {
      var i, j, k, l, types;
      if (typeof selector === 'string') {
        types = type.split(' ');
        element = element || context;
        for (i = 0, l = types.length; l > i; ++i) {
          k = isRegistered(Delegates, element, types[i], handler, selector);
          if (k === false) {
            register(Delegates, element, types[i], handler, selector);
            if (getRegistered(Delegates, element, types[i], '*').length === 1) {
              listen(element, types[i], processDelegates, selector);
            }
          }
        }
      } else {
        // hash of "rules" containing selector-event-handler
        for (i in selector) {
          if (typeof i === 'string') {
            for (j in selector[i]) {
              delegate(i, j, selector[i][j], element);
            }
          }
        }
      }
      return this;
    },

  // remove an event delegate
  undelegate =
    // delegated element defaults to document
    // it is a required parameter with iframes
    function(selector, type, handler, element) {
      var i, j, k, l, types;
      if (typeof type === 'string') {
        types = type.split(' ');
        element = element || context;
        for (i = 0, l = types.length; l > i; ++i) {
          k = isRegistered(Delegates, element, types[i], handler, selector);
          if (k !== false) {
            if (getRegistered(Delegates, element, types[i], '*').length === 1) {
              unlisten(element, types[i], processDelegates, selector);
            }
            unregister(Delegates, element, types[i], handler, selector, k);
          }
        }
      } else {
        // hash of "rules" containing selector-event-handler
        for (i in selector) {
          if (typeof i === 'string') {
            for (j in selector[i]) {
              undelegate(i, j, selector[i][j], element);
            }
          }
        }
      }
      return this;
    },

  // dispatch native or custom events to registered listeners
  // this is performed using native DOM Event API if possible
  // so the event propagates to other DOM listening instances
  dispatch = W3C_MODEL ?
    // W3C event model
    function(element, type, capture, options) {

      var event, d = getDocument(element), view = d.defaultView;

      options || (options = { });

      if (SUPPORT_MOUSE_EVENTS && Mouse_Events[type]) {

        event = d.createEvent('MouseEvent');
        event.initMouseEvent(type,
          options.bubbles || true, options.cancelable || true, view,
          options.detail || 0, options.screenX || 0, options.screenY || 0, options.clientX || 0, options.clientY || 0,
          options.ctrlKey || false, options.altKey || false, options.shiftKey || false, options.metaKey || false,
          options.button || 0, options.relatedTarget || null);

      } else if ((SUPPORT_KEYBOARD_EVENTS || SUPPORT_KEY_EVENTS) && Keyboard_Events[type]) {

        event = d.createEvent(KEYBOARD_EVENT + KEYBOARD_FIX);
        event['init' + KEYBOARD_EVENT](type,
          options.bubbles || true, options.cancelable || true, view,
          /* DOM3 KeyboardEvent: option.keyIndentifier || '', option.keyLocation || 0, option.modifierList || '' */
          options.ctrlKey || false, options.altKey || false, options.shiftKey || false, options.metaKey || false,
          options.keyCode || 0, options.charCode || 0);

      } else if (SUPPORT_TOUCH_EVENTS && Touch_Events[type]) {

        event = d.createEvent('TouchEvent');
        event.initTouchEvent(type,
          options.bubbles || true, options.cancelable || true, view,
          options.detail || 0, options.screenX || 0, options.screenY || 0, options.clientX || 0, options.clientY || 0,
          options.ctrlKey || false, options.altKey || false, options.shiftKey || false, options.metaKey || false,
          options.touches || [ ], options.targetTouches || [ ], options.changedTouches || [ ],
          options.scale || 1.0, options.rotation || 0.0);

      } else if (SUPPORT_UI_EVENTS && UI_Events[type]) {

        event = d.createEvent('UIEvent');
        event.initUIEvent(type, options.bubbles || true, options.cancelable || true, view, options.detail);

      } else if (SUPPORT_EVENTS) {

        event = d.createEvent('Event');
        event.initEvent(type, options.bubbles || true, options.cancelable || true);

      }

      if (FormActivationEvents[type]) event.propagated = true;

      return element.dispatchEvent(event);
    } : MSIE_MODEL ?
    // IE event model
    function(element, type, capture, options) {

      if (isSupported(type)) {
        var event = getDocument(element).createEventObject();
        event.type = type;
        event.target = element;
        event.eventPhase = CUSTOM;
        event.returnValue = true;
        event.cancelBubble = !!capture;
        event.currentTarget = element;
        event.preventDefault = preventDefault;
        event.stopPropagation = stopPropagation;
        for (var i in options) event[i] = options[i];
        if (FormActivationEvents[type]) event.propagated = true;

        return element.fireEvent('on' + type, fixEvent(element, event, capture));
      }

      return notify(element, type, capture, options || { });
    } :
    // try manual dispatch
    function(element, type, capture, options) {
      return notify(element, type, capture, options || { });
    },

  // notify registered listeners an event occurred
  notify =
    function(element, type, capture, options) {
      if (typeof capture !== 'undefined') {
        return propagatePhase(element, type, !!capture);
      }
      return (propagatePhase(element, type, true) &&
        propagatePhase(element, type, false));
    },

  /* =========================== EVENT PROPAGATION ========================== */

  //
  // known available activation events:
  //
  // Internet Explorer:
  //   focusin, focusout, activate, deactivate,
  //   beforeactivate, beforedeactivate
  //
  // FF/Opera/Safari/K:
  //   DOMActivate, DOMFocusIn, DOMFocusOut
  //
  // DOM0/1 and inline:
  //   focus, blur
  //
  // we use just a few of them to emulate the capturing
  // and bubbling phases of the focus and blur events
  // where not available or named/used differently
  //
  ActivationMap = {
    'blur': 'blur',
    'focus': 'focus',
/*
    'focusin': 'focus',
    'focusout': 'blur',
    'activate': 'focus',
    'deactivate': 'blur',
    'DOMFocusIn': 'focus',
    'DOMFocusOut': 'blur',
*/
    'beforeactivate': 'focus',
    'beforedeactivate': 'blur'
  },

  FormActivationEvents = {
    blur: 1,
    focus: 1,
    reset: 1,
    submit: 1,
    change: 1
  },

  FormAction = 'keydown mousedown',
  Activation = context.addEventListener ?
    'focus blur' : 'beforeactivate beforedeactivate',

  FormButton = RegExp('^(reset|submit)$'),
  FormTextbox = RegExp('^(file|text|password)$'),
  FormControl = RegExp('^(select-(one|multi)|checkbox|radio|textarea|file|text|password)$'),

  // create a synthetic event
  synthesize =
    function(element, type, capture, options) {
      var event = {
        type: type,
        target: element,
        bubbles: true,
        cancelable: true,
        propagated: true,
        relatedTarget: null,
        currentTarget: element,
        preventDefault: preventDefault,
        stopPropagation: stopPropagation,
        eventPhase: capture ? CAPTURING_PHASE : BUBBLING_PHASE,
        timeStamp: +new Date
      };
      for (var i in options) event[i] = options[i];
      return event;
    },

  // propagate events traversing the
  // ancestors path in both directions
  propagate =
    function(event) {
      var result = true, target = event.target, type = event.type;
      // execute the capturing phase
      result && (result = propagatePhase(target, type, true));
      // execute the bubbling phase
      result && (result = propagatePhase(target, type, false));
      // remove the trampoline event
      unset(target, type, propagate, false);
      // submit/reset events relayed to parent forms
      if (target.form && (/submit|reset/).test(type)) {
        target = target.form;
      }
      if (Listeners[type] && Listeners[type].items.length) {
        // execute existing native methods if not overwritten
        result && isNative(target, type) && target[type]();
      }
      result || stop(event);
      return result;
    },

  // propagate event capturing or bubbling phase
  propagatePhase =
    function(element, type, capture) {
      var i, l,
        result = true,
        node = element, ancestors = [],
        event = synthesize(element, type, capture);
      // collect ancestors
      while (node) {
        ancestors.push(node);
        node = node.parentNode;
      }
      // capturing, reverse ancestors collection
      if (capture) ancestors.reverse();
      // execute registered handlers in fifo order
      for (i = 0, l = ancestors.length; l > i; ++i) {
        // set currentTarget to current ancestor
        event.currentTarget = ancestors[i];
        // set eventPhase to the requested phase
        event.eventPhase = capture ? CAPTURING_PHASE : BUBBLING_PHASE;
        // execute listeners bound to this ancestor and set return value
        if (processListeners.call(ancestors[i], event) === false || event.returnValue === false) {
          result = false;
          break;
        }
      }
      return result;
    },

  // propagate activation events
  // captured/emulated activations
  // only applied to form elements
  propagateActivation =
    function(event) {
      var result = true, target = event.target;
      // exit if the event was not fired on forms or on controls
      if (!(/^form$/i).test(target.nodeName) && !(target.type && 'form' in target)) return true;
      result && (result = propagatePhase(target, ActivationMap[event.type], true));
      result && (result = propagatePhase(target, ActivationMap[event.type], false));
      result || (event.preventDefault ? event.preventDefault() : (event.returnValue = false));
      return result;
    },

  // propagate form action events
  // mousedown and keydown events
  // only applied to form elements
  propagateFormAction =
    function(event) {
      var target = event.target, type = target.type,
        active = target.ownerDocument.activeElement;
      // handle activeElement on context document
      if (target !== active) {
        if (!hasActive && target.nodeType === 1) {
          target.ownerDocument.activeElement = target;
        }
      }
      // html form elements only
      if (type) {
        // keydown or mousedown on form elements
        if (FormTextbox.test(type) && event.keyCode === 13 && target.form) {
          target = target.form;
          type = 'submit';
        } else if (FormButton.test(type) && target.form) {
          target = target.form;
        } else if (FormControl.test(type)) {
          type = 'change';
        } else {
          return;
        }
        set(target, type, propagate, false);
      }
    },

  // enable event propagation
  enablePropagation =
    function(context) {
      if (!context.forcedPropagation) {
        context.forcedPropagation = true;
        // deregistration on page unload
        set(getWindow(context), 'unload',
          function(event) {
            disablePropagation(context);
            // we are removing ourself here, so do it as last
            unset(this, 'unload', arguments.callee, false);
          }, false);
        // register capturing keydown and mousedown event handlers
        set(context, FormAction, propagateFormAction, true);
        // register emulated capturing focus and blur event handlers
        set(context, Activation, propagateActivation, true);
      }
    },

  // disable event propagation
  disablePropagation =
    function(context) {
      if (context.forcedPropagation) {
        context.forcedPropagation = false;
        // deregister capturing keydown and mousedown event handlers
        unset(context, FormAction, propagateFormAction, true);
        // deregister emulated capturing focus and blur event handlers
        unset(context, Activation, propagateActivation, true);
      }
    },

  /* ========================== DOM CONTENT LOADED ========================== */

  /*!
   * contentloaded.js
   *
   * Author: Diego Perini (diego.perini at gmail.com)
   * Summary: cross-browser wrapper for DOMContentLoaded
   * Updated: 20101020
   * License: MIT
   * Version: 1.2
   *
   * URL:
   * http://javascript.nwbox.com/ContentLoaded/
   * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
   *
   */

  // @win window reference
  // @fn function reference
  contentLoaded = function(win, fn) {

    var done = false, top = true,

    doc = win.document, root = doc.documentElement,

    add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
    rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
    pre = doc.addEventListener ? '' : 'on',

    init = function(e) {
      if (e.type === 'readystatechange' && doc.readyState !== 'complete') return;
      (e.type === 'load' ? win : doc)[rem](pre + e.type, init, false);
      if (!done && (done = true)) fn.call(win, e.type || e);
    },

    poll = function() {
      try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
      init('poll');
    };

    if (doc.readyState === 'complete') fn.call(win, 'lazy');
    else {
      if (doc.createEventObject && root.doScroll) {
        try { top = !win.frameElement; } catch(e) { }
        if (top) poll();
      }
      doc[add](pre + 'DOMContentLoaded', init, false);
      doc[add](pre + 'readystatechange', init, false);
      win[add](pre + 'load', init, false);
    }

  },

  isReady = false,

  readyHandlers = new EventCollection,

  ready =
    function(host, callback) {
      if (isReady) {
        callback.call('ready');
      } else {
        var k = isRegistered(readyHandlers, host, 'ready', callback, null);
        if (k === false) {
          register(readyHandlers, host, 'ready', callback, null);
        } else {
          throw new Error('NWEvents: duplicate ready handler for host: ' + host);
        }
      }
    },

  complete =
    function(event) {
      isReady = true;
      if (readyHandlers['ready'] && readyHandlers['ready'].items) {
        var i, length = readyHandlers['ready'].items.length;
        for (i = 0; length > i; ++i) {
          readyHandlers['ready'].calls[i](event);
        }
      }
    };

  // inititalize the activeElement
  // to a known cross-browser state
  if (!hasActive) {
    context.activeElement = root;
  }

  // initialize context propagation
  if (!context.forcedPropagation) {
    enablePropagation(context);
  }

  // initialize global ready event
  contentLoaded(global, complete);

  // detected event model, ms or w3c
  Event.W3C_MODEL = W3C_MODEL;
  Event.MSIE_MODEL = MSIE_MODEL;

  // controls the type of registration
  // for event listeners (DOM0 / DOM2)
  Event.USE_DOM2 = USE_DOM2;

  // exposed event collections
  Event.Delegates = Delegates;
  Event.Listeners = Listeners;
  Event.DOMEvents = DOMEvents;

  // exposed event methods
  Event.stop = stop;
  Event.ready = ready;

  Event.set = set;
  Event.unset = unset;

  Event.append = append;
  Event.remove = remove;

  Event.register = register;
  Event.unregister = unregister;

  Event.listen = listen;
  Event.unlisten = unlisten;

  Event.delegate = delegate;
  Event.undelegate = undelegate;

  Event.notify = notify;
  Event.dispatch = dispatch;

  Event.synthesize = synthesize;

  Event.isRegistered = isRegistered;
  Event.getRegistered = getRegistered;

  Event.contentLoaded = contentLoaded;

  // back compat aliases
  Event.appendHandler = set;
  Event.removeHandler = unset;

  Event.appendListener = listen;
  Event.removeListener = unlisten;

  Event.appendDelegate = delegate;
  Event.removeDelegate = undelegate;

  // helpers and debugging functions
  Event.isSupported = isSupported;

  Event.enablePropagation = enablePropagation;
  Event.disablePropagation = disablePropagation;

})(this);

// embedded NW.Dom.match() so basic event delegation works,
// accepts mixed id, tag, class simple selectors div#foo.bar
// accepts objects having properties that must match element
// overwritten when loading the nwmatcher.js selector engine
(function(global) {

  // NW.Dom already defined, leave now
  if (global.NW && global.NW.Dom) return;

  var version = 'match-1.0',

  Dom = typeof exports === 'object' ? exports : (
    (global.NW || (global.NW = { })) &&
    (global.NW.Dom || (global.NW.Dom = { }))),

  doc = global.document,
  root = document.documentElement,

  Patterns = {
    'id': /#([^\.]+)/,
    'tagName': /^([^#\.]+)/,
    'className': /\.([^#]+)/,
    'all': /^[\.\-\#\w]+$/
  },

  References = {
    'parentNode': 1,
    'lastChild': 1,
    'firstChild': 1,
    'nextSibling': 1,
    'previousSibling': 1,
    'lastElementChild': 1,
    'firstElementChild': 1,
    'nextElementSibling': 1,
    'previousElementSibling': 1
  },

  // select Matches Selector API to use if available
  NATIVE_MATCHES_SELECTOR =
    'matchesSelector' in root ? 'matchesSelector' :
    'oMatchesSelector' in root ? 'oMatchesSelector' :
    'msMatchesSelector' in root ? 'msMatchesSelector' :
    'mozMatchesSelector' in root ? 'mozMatchesSelector' :
    'webkitMatchesSelector' in root ? 'webkitMatchesSelector' : null,

  RE_SIMPLE_SELECTOR = RegExp('^(?:\\*|[.#]?-?[_a-zA-Z]{1}(?:[-\\w]|[^\\x00-\\xa0]|\\\\.)*)$');

  // use a simple selector match or a full
  // CSS3 selector engine if it is available
  Dom.match = function(element, selector) {

    var d, j, length,
    id, tagName, className,
    match, matched = false, results = [ ];

    d = element.ownerDocument || element;

    if (typeof selector === 'string') {
      if (RE_SIMPLE_SELECTOR.test(selector)) {
        // use a simple selector match (id, tag, class)
        if (selector.match(Patterns.all)) {
          match = selector.match(Patterns.tagName);
          tagName = match ? match[1] : '*';
          match = selector.match(Patterns.id);
          id = match ? match[1] : null;
          match = selector.match(Patterns.className);
          className = match ? match[1] : null;
          if ((!id || id === element.id) &&
            (!tagName || tagName === '*' || (new RegExp(tagName, 'i')).test(element.nodeName)) &&
            (!className || (' ' + element.className.replace(/\s+/g, ' ') + ' ').indexOf(' ' + className + ' ') > -1)) {
            matched = true;
          }
        }
      } else if (NATIVE_MATCHES_SELECTOR) {
        // use native matchesSelector where available
        return element[NATIVE_MATCHES_SELECTOR](selector);
      }
      return matched;
    } else {
      // a selector matcher object
      if (typeof selector === 'object') {
        // match on property/values
        for (j in selector) {
          matched = false;
          if (j === 'className') {
            // handle special className matching
            if ((' ' + element.className.replace(/\s+/g, ' ') + ' ').indexOf(' ' + selector[j] + ' ') > -1) {
              matched = true;
            }
          } else if (j === 'nodeName' || j === 'tagName') {
            // handle upper/lower case tag names
            if (element[j].toLowerCase() === selector[j].toLowerCase()) {
              matched = true;
            }
          } else if (References[j]) {
            // handle matching nested objects references
            matched = Dom.match(element[j], selector[j]);
          } else {
            // handle matching other properties
            if (element[j] === selector[j]) {
              matched = true;
            }
          }
          results.push(matched);
        }
      }
    }

    // boolean true/false
    return results.join('|').indexOf('false') < 0;
  };

})(this);


/**
 * Copyright (c) 2011-2015 committers of YAKINDU and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     committers of YAKINDU - initial API and implementation
 */
package org.yakindu.sct.generator.csharp.features;

import static org.yakindu.sct.generator.csharp.features.ICSharpFeatureConstants.*;

import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EObject;
import org.yakindu.sct.generator.core.library.AbstractDefaultFeatureValueProvider;
import org.yakindu.sct.model.sgen.FeatureParameterValue;
import org.yakindu.sct.model.sgen.FeatureType;
import org.yakindu.sct.model.sgen.FeatureTypeLibrary;

/**
 *
 * @author andreas muelder - Initial contribution and API
 * @author terfloth - extensions
 *
 */
public class CSharpFeatureValueProvider extends
		AbstractDefaultFeatureValueProvider {

	private static final String SUFFIX_REGEX = "[a-zA-Z0-9_]*";

	@Override
	protected void setDefaultValue(FeatureType featureType, FeatureParameterValue parameterValue,
			EObject contextElement) {
		if (parameterValue.getParameter().getName().equals(NAMESPACE_NAME)) {
			parameterValue.setValue("Yakindu.SCT");
		} else if (parameterValue.getParameter().getName()
				.equals(IMPLEMENTATION_SUFFIX)) {
			parameterValue.setValue("impl");
		} else if (parameterValue.getParameter().getName().equals(NAME_PREFIX)) {
			parameterValue.setValue("Runnable");
		} else if (parameterValue.getParameter().getName().equals(NAME_SUFFIX)) {
			parameterValue.setValue("");
		}

	}

	public boolean isProviderFor(FeatureTypeLibrary library) {
		return library.getName().equals(LIBRARY_NAME);
	}

	public IStatus validateParameterValue(FeatureParameterValue value) {
		String name = value.getParameter().getName();
		if (NAMESPACE_NAME.equals(name)) {
			// Filter out C# keywords
			for (String keyword : Arrays.asList(CSHARP_KEYWORDS)) {
				Pattern pattern = Pattern.compile("(?:^|\\.)" + keyword
						+ "(?:$|\\.)");
				Matcher matcher = pattern.matcher(value.getStringValue());
				while (matcher.find()) {
					return error("C# keyword '" + matcher.group()
							+ "' is not allowed in package names.");
				}
			}
		}
		if (IMPLEMENTATION_SUFFIX.equals(name)) {
			if (!value.getStringValue().matches(SUFFIX_REGEX)) {
				return error("Invalid value");
			}
			for (String keyword : Arrays.asList(CSHARP_KEYWORDS)) {
				Pattern pattern = Pattern.compile("^" + keyword + "$");
				Matcher matcher = pattern.matcher(value.getStringValue());
				while (matcher.find()) {
					return error("C# keyword '" + matcher.group()
							+ "' is not allowed as suffix.");
				}
			}

		}
		return Status.OK_STATUS;
	}
}


'use strict';

var _ = require('lodash/dist/lodash.underscore'),
    Q = require('q'),
    QFS = require('q-io/fs'),
    FS = require('fs'),
    PATH = require('../path'),
    CP = require('child_process'),
    VM = require('vm'),
    LOGGER = require('../logger'),
    BEM = require('../coa').api,
    createLevel = require('../level').createLevel,
    Context = require('../context').Context,
    U = require('../util'),
    registry = require('../nodesregistry'),

    FileNode = require('./file'),
    GeneratedFileNode = require('./file').GeneratedFileNodeName,

    BemBuildNodeName = exports.BemBuildNodeName = 'BemBuildNode';

/* jshint -W106 */
exports.__defineGetter__(BemBuildNodeName, function() {
    return registry.getNodeClass(BemBuildNodeName);
});
/* jshint +W106 */

registry.decl(BemBuildNodeName, GeneratedFileNode, {

    nodeType: 7,

    __constructor: function(o) {

        this.bundlesLevel = o.bundlesLevel;
        this.levelsPaths = o.levels.map(function(level) {
            return level.path || level;
        });
        this.levels = o.levels.map(function(l) {
            return createLevel(l, {
                projectRoot: o.root
            });
        });
        this.declPath = o.declPath;
        this.techName = o.techName;
        this.output = o.output;
        this.forked = typeof o.forked === 'undefined'? false : !!o.forked;

        // NOTE: Every time we need new tech object so we use createTech().
        // If we use getTech(), we'll overwrite context of the same tech
        // object that is prone to collisions
        this.tech = this.bundlesLevel.getTech(o.techName, o.techPath);
        this.techPath = this.tech.getTechPath();
        this.tech.setContext(new Context(this.bundlesLevel, { level: this.levels }));

        this.__base(U.extend({ path: this.__self.createId(o) }, o));

    },

    isValid: function() {

        if (this.tech.API_VER === 2) return false;

        var _this = this;

        return Q.when(this.__base(), function(valid){
            if (!valid) return false;

            var meta = _this.getMetaNode();
            if (!_this.ctx.arch.hasNode(meta)) return false;

            return Q.all([
                    _this.readMeta(),
                    _this.lastModified(),
                    meta.lastModified()
                ])
                .spread(function(meta, nodeLastModified, metaLastModified) {

                    // expired if <tech>.meta.js is invalid
                    if (meta === null) return false;

                    // expired if .<tech>.meta.js is newer than .<tech>
                    if (metaLastModified > nodeLastModified) return false;

                    // Possible values: promised, callback, sync
                    var strategy = process.env.BEM_IO_STRATEGY_BUILD_IS_VALID || process.env.BEM_IO_STRATEGY;

                    ['promised', 'callback', 'sync'].indexOf(strategy) !== -1 || (strategy = 'callback');
                    LOGGER.fverbose('Using %s strategy in BemBuildNode.isValid()', strategy);

                    if (strategy === 'promised') {

                        // Promised build result validity check
                        return (function() {

                            var valid = true;
                            return Q.all(meta.map(function(m) {

                                return QFS.lastModified(PATH.resolve(_this.root, m))
                                    .then(function(d) {
                                        if (d > nodeLastModified) valid = false;
                                    })
                                    .fail(function() {
                                        valid = false;
                                    });

                            }))
                            .then(function() {
                                return valid;
                            });

                        })();

                    }

                    else if (strategy === 'callback') {

                        // Async build result validity check
                        return (function() {

                            var d = Q.defer(),
                                total = meta.length,
                                count = 0;

                            if (total === 0) d.resolve(true);

                            meta.forEach(function(path) {

                                FS.stat(PATH.resolve(_this.root, path), function(err, stat) {

                                    count++;

                                    if (err || stat.mtime.getTime() > nodeLastModified) d.resolve(false);
                                    if (count < total) return;
                                    d.resolve(true);

                                });

                            });

                            return d.promise;

                        })();

                    }

                    // Sync build result validity check
                    // See https://github.com/bem/bem-tools/issues/157
                    for (var i = 0, l = meta.length; i < l; i++) {
                        if (FS.statSync(PATH.resolve(_this.root, meta[i])).mtime.getTime() > nodeLastModified) return false;
                    }

                    return true;

                });
        });
    },

    make: function() {
        var opts = {
            outputLevel: this.bundlesLevel.dir,
            level: this.levelsPaths,
            declaration: PATH.resolve(this.root, this.declPath),
            tech: this.techPath,
            outputName: PATH.resolve(this.root, this.output),
            force: this.ctx.force,
            root: this.root
        };

        this.log('bem.build(forked=%j, %s)', this.forked, JSON.stringify(opts, null, 4));

        if (!this.forked) {
            opts.level = this.levels;
            return BEM.build(opts);
        }

        opts.forceCache = true;
        // TODO: generalize forking of bem commands
        var _this = this,
            d = Q.defer(),
            worker = CP.fork(PATH.join(__dirname, 'workers', 'bembuild.js'), [], { env: process.env }),
            handler = function(m) {
                (m.code !== 0)? d.reject(m.msg) : d.resolve();
            };

        /* jshint -W109 */
        worker.on('exit', function(code) {
            LOGGER.fdebug("Exit of bembuild worker for node '%s' with code %s", _this.output, code);
            handler({ code: code });
        });

        worker.on('message', function(m) {
            LOGGER.fdebug("Message from bembuild worker for node '%s': %j", _this.output, m);
            handler(m);
        });
        /* jshint +W109 */

        worker.send(opts);

        return d.promise;
    },

    readMeta: function() {
        return this._readMeta(this.getMetaNode().getPath());
    },

    _readMeta: function(path) {

        path = PATH.resolve(this.root, path);
        var _this = this,
            relativize = getPathRelativizer(this.root);

        return U.readFile(path)
            .then(function(c) {

                return VM.runInThisContext(c).map(function(f) {
                    return relativize(PATH.resolve(PATH.dirname(path), f));
                }, _this);

            })
            .fail(function() {
                return null;
            });

    },

    getMetaNode: function() {

        var node = this.metaNode || (this.metaNode = new exports.BemBuildMetaNode({
            root: this.root,
            bundlesLevel: this.bundlesLevel,
            levels: this.levelsPaths,
            declPath: this.declPath,
            techPath: this.techPath,
            techName: this.techName,
            output: this.output,
            forked: this.forked
        }));

        node.buildNode = this;

        return node;

    },

    /**
     * Get files minimum mtime in milliseconds or -1 in case of any file doesn't exist.
     *
     * @return {Promise * Number}
     */
    lastModified: function() {

        return Q.all(this.tech
            .getPaths(PATH.resolve(this.root, this.output), this.tech.getBuildSuffixes())
            .map(function(path) {

                return QFS.lastModified(path)
                    .fail(function() {
                        return -1;
                    });

            }))
            .spread(Math.min);

    },

    /**
     * clean() implementation.
     * @return {Promise * Undefined}
     */
    clean: function() {

        var _this = this;
        return Q.all(this.tech
            .getPaths(PATH.resolve(this.root, this.output), this.tech.getBuildSuffixes())
            .map(function(path) {

                return QFS.remove(path)
                    .then(function() {
                        LOGGER.fverbose('[-] Removed %j', path);
                    })
                    .fail(function() {});

            }))
            .then(function() {

                return U.removePath(_this.getPath())
                    .then(function() {
                        LOGGER.fverbose('[-] Removed %j', _this.getId());
                    })
                    .fail(function() {});

            });

    },

    getFiles: function() {
        return this.tech.getPaths(this.output, this.tech.getBuildSuffixes());
    },

    getDependencies: function() {

        var deps = this.tech.getDependencies().map(function(d) {
            return this.bundlesLevel.getPath(this.output, d);
        }, this);

        deps.push(this.declPath);
        return deps;

    }

}, {

    createId: function(o) {

        return o.bundlesLevel
            .getTech(o.techName, o.techPath)
            .getPath(o.output);

    }

});

var BemBuildMetaNodeName = exports.BemBuildMetaNodeName = 'BemBuildMetaNode';

/* jshint -W106 */
exports.__defineGetter__(BemBuildMetaNodeName, function() {
    return registry.getNodeClass(BemBuildMetaNodeName);
});
/* jshint +W106 */

registry.decl(BemBuildMetaNodeName, BemBuildNodeName, {

    /**
     * Overriden.
     *
     * Constructs new BemBuildMetaNode instance and changes the path property with `.bem/cache` prefix.
     *
     * @param {Object} o
     */
    __constructor: function(o) {
        this.__base(o);
        this.path = PATH.join('.bem', 'cache', this.path);
    },

    isValid: function() {

        var ctx = this.ctx;

        // expired in case of clean or other methods
        if (ctx.method && ctx.method !== 'make') return false;

        var decl = U.readDecl(PATH.resolve(this.root, this.declPath)),
            tech = this.tech,
            techv2 = !!this.tech.getBuildPaths,
            relativize = getPathRelativizer(this.root),
            prefixes = !techv2? tech.getBuildPrefixes(tech.transformBuildDecl(decl), this.levels): Q.resolve([]),
            filteredPaths = tech.filterPrefixes(prefixes, tech.getSuffixes()).invoke('map', relativize),
            savedPaths = this.readMeta();

        ctx.prefixes = prefixes;
        ctx.filteredPaths = filteredPaths;
        ctx.savedPaths = savedPaths;

        // expired if build is forced; must return after filling the ctx with promises
        if (ctx.force) return false;

        var _this = this;
        return Q.all([filteredPaths, savedPaths])
            .spread(function(filteredPaths, savedPaths) {
                if (savedPaths === null) return false;
                filteredPaths = filteredPaths || [];

                var diff = [].concat(_.difference(savedPaths, filteredPaths),
                    _.difference(filteredPaths, savedPaths));

                LOGGER.fdebug('*** isValid(%j)=%j', _this.getId(), !diff.length);
                LOGGER.fdebug('*** diff=%j', diff);
                LOGGER.fdebug('*** savedPaths=%j', savedPaths);
                LOGGER.fdebug('*** filteredPaths=%j', filteredPaths);

                return !diff.length;
            });
    },

    make: function() {
        var _this = this,
            ctx = this.ctx,
            arch = ctx.arch;

        return Q.all([ctx.filteredPaths, ctx.savedPaths])
            .spread(function(filteredPaths, savedPaths) {

                return arch.withLock(_this.alterArch(filteredPaths, savedPaths), _this)
                    .then(function() {

                        // write file list to .meta.js
                        var relativize = getPathRelativizer(PATH.dirname(_this.path)),
                            paths = filteredPaths.map(function(f) {
                                return relativize(f);
                            });

                        U.mkdirs(PATH.dirname(_this.getPath()));
                        return QFS.write(_this.getPath(), '(' + JSON.stringify(paths, null, 4) + ')');

                    });

            });
    },

    alterArch: function(filteredPaths, savedPaths) {

        return function() {

            var ctx = this.ctx,
                arch = ctx.arch,
                buildNodeId = this.buildNode.getId();

            savedPaths = savedPaths || [];
            filteredPaths = filteredPaths || [];

            // find difference with array read from file and filteredPaths
            var obsolete = _.difference(savedPaths, filteredPaths);

            // clean obsolete dependencies from arch
            obsolete.forEach(function(p) {
                if (!arch.hasNode(p)) return;

                // remove link with p
                arch.unlink(p, buildNodeId);

                // when p has no other dependent nodes, remove it from arch
                if (!arch.getParents(p).length) arch.removeNode(p);
            });

            // create nodes for all existent paths to blocks files: FileNode(path)
            filteredPaths.forEach(function(p) {
                arch.hasNode(p) || arch.addNode(new FileNode.FileNode({
                    root: this.root,
                    path: p
                }));
                // link created nodes to BemBuildNode corresponding to this node
                ctx.plan.link(p, buildNodeId);
            }, this);

            return Q.when(this.takeSnapshot('after alterArch BemBuildMetaNode ' + this.getId()));
        };

    },

    readMeta: function() {
        return this._readMeta(this.getPath());
    },

    /**
     * Get file mtime in milliseconds or -1 in case of file doesn't exist.
     *
     * @return {Promise * Number}
     */
    lastModified: function() {

        // TODO: should really use link to GeneratedFileNode.prototype.lastModified() here
        return QFS.lastModified(this.getPath())
            .fail(function() {
                return -1;
            });

    },

    /**
     * clean() implementation.
     * @return {Promise * Undefined}
     */
    clean: function() {

        // TODO: should really use link to GeneratedFileNode.prototype.clean() here
        var _this = this;
        return QFS.remove(this.getPath())
            .then(function() {
                LOGGER.fverbose('[-] Removed %j', _this.getId());
            })
            .fail(function() {});

    },

    getDependencies: function() {
        return [this.declPath];
    }

}, {

    createId: function(o) {
        return this.__base(o) + '.meta.js';
    }

});

function getPathRelativizer(from) {
    return function(p) {
        return PATH.relative(from, p);
    };
}


$icon-font-path: "/bower_components/bootstrap-sass-official/vendor/assets/fonts/bootstrap/";

// http://colorschemedesigner.com/#00428sOsOFfFf

$brand-primary: #007DA1;
$brand-success: #0A95BB;
$brand-danger: #AA3C2F;
$brand-warning: #C66025;
$brand-info: #666;
$brand-neutral: #666;

$brand-primary: #167D2E;
$brand-success: #17A139;
$brand-danger: #D4402A;
$brand-warning: #D98915;
$brand-info: #666;
$brand-neutral: #666;

$contrast: 10%;

$brand-primary-dark: darken($brand-primary, $contrast); //#0165BD;
$brand-danger-dark: darken($brand-danger, $contrast);
$brand-success-dark: darken($brand-success, $contrast);
$brand-warning-dark: darken($brand-warning, $contrast);
$brand-info-dark: darken($brand-info, $contrast);
$brand-neutral-dark: #222;

$brand-neutral-vdark: #111;

$brand-neutral-bright: #888;

$body-bg: #000;
$text-color: #eee;
$headings-color: $brand-primary;
$text-color-dark: #444;
$text-muted: $brand-neutral;

$font-family-sans-serif: 'Roboto Condensed', Helvetica, Arial, sans-serif;

$headings-font-family: $font-family-sans-serif;
$headings-font-weight: 700;

$padding-base-vertical: 10px;
$padding-base-horizontal: 15px;
$padding-large-vertical: 15px;
$padding-large-horizontal: 30px;

$border-color: $brand-neutral-dark;
$border-width: 4px;
$border-radius-base: 0px;
$border-radius-large: 0px;
$border-radius-small: 0px;

// states
$state-danger-bg: $brand-danger;
$state-danger-text: $text-color;
$state-danger-border: $brand-danger-dark;
$state-warning-bg: $brand-warning;
$state-warning-text: $text-color;
$state-warning-border: $brand-warning-dark;
$state-info-bg: $brand-info;
$state-info-text: $text-color;
$state-info-border: $brand-info-dark;
$state-success-bg: $brand-success;
$state-success-text: $text-color;
$state-success-border: $brand-success-dark;

// wells
$well-bg: rgba(0,0,0,0.2);

// buttons
$btn-default-color: $text-color;
$btn-default-bg: $body-bg;
$btn-default-border: lighten($body-bg, 22%);

// popovers
$popover-bg: $body-bg;
$popover-arrow-color: $body-bg;
$popover-arrow-width: 6px;
$popover-max-width: 400px;

// modals
$modal-content-bg: $body-bg;
$modal-header-border-color: lighten($body-bg, 10%);

// panels
$panel-bg: $body-bg;
$panel-header-bg: $brand-primary;
$panel-header-border: darken($panel-header-bg, $contrast);
$panel-header-color: $text-color;
$panel-footer-bg: $brand-neutral-dark;
$panel-footer-border: $brand-neutral-vdark;
$panel-footer-color: $text-color;
$panel-default-text: $text-color;

// code
$code-color: inherit;
$code-bg: fade-out($text-color, 0.8);

// thumbnails
$thumbnail-border: $border-color;
$thumbnail-bg: $body-bg;
$thumbnail-matte: $brand-neutral-dark;
$thumbnail-padding: 1px;

@import "_bootstrap.scss";
@import "_icomoon.scss";

$navbar-height: 40px;
$navbar-bg: $body-bg;

$leftpane-width: 375px;
$leftpane-bg: $brand-neutral-vdark;

$about-bg: transparent; //$brand-primary-dark;

$gallery-width: 70px;
$gallery-bg: darken($leftpane-bg, 15%);

$draw-sm-size: 640px;
$draw-lg-size: 980px;
$draw-pane-width: 320px;
$draw-pane-height: 50px;

$facebook-color: desaturate(darken(#3B5998, $contrast), $contrast);
$google-color:   desaturate(darken(#D74635, $contrast), $contrast);
$twitter-color:  desaturate(darken(#00C3F8, $contrast), $contrast);

$media-tiny: "(max-width: #{$screen-xs-max})";
$media-small: "(min-width: #{$screen-sm-min}) and (max-width: #{$screen-sm-max})";
$media-medium: "(min-width: #{$screen-md-min}) and (max-width: #{$screen-md-max})";
$media-large: "(min-width: #{$screen-lg-min})";

$media-phone: $media-tiny;
$media-tablet: $media-small;
$media-mobile: "(max-width: #{$screen-xs-max})";
$media-desktop: "(min-width: #{$screen-desktop})";

$media-full: "(min-width: #{$screen-lg-min})";

@import "_mixins.scss";
@import "_common.scss";
@import "_animations.scss";
@import "_elements.scss";
@import "_rwd.scss";
@import "_poor.scss";


# This file is part of NIT ( http://www.nitlanguage.org ).
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import opts

import benitlux_model
import benitlux_db
import correct

# Sort beers by their availability
class BeerComparator
	super Comparator

	# 1st sorting priority
	var map1: HashMap[COMPARED, Comparable]

	# 2nd sorting priority
	var map2: HashMap[COMPARED, Comparable]

	# Key compare
	redef fun compare(a, b) do return if map1[a] == map1[b] then
	                                      map2[a] <=> map2[b]
	                                  else map1[a] <=> map1[b]
end

redef class Text

	# Get the background for the date `self` of format `yyyy-mm-dd`
	private fun date_to_back: String
	do
		assert length == 10

		var m = substring(5, 2)
		var month = m.to_i
		if [4..9].has(month) then return " "
		return "-"
	end
end

var opts = new OptionContext
var opt_columns = new OptionInt("Number of columns for the graph", 70, "-c")
opts.add_option(opt_columns)

opts.parse(args)
var rest = opts.rest

# Use the local DB
var db_path = "benitlux_sherbrooke.db"
if rest.not_empty then db_path = rest.first
var db = new BenitluxDB.open(db_path)

# All known beers
var beers = db.beers
assert beers != null
print "{beers.length} known beers"

# All days
var all_days = db.days
assert all_days != null
print "{all_days.length} days, from {all_days.first} to {all_days.last}"

# Beers availability by days
var beer2days = new HashMap[Beer, Array[String]]
for beer in beers do
	var days = db.days(beer)
	assert days != null
	default_comparator.sort days
	beer2days[beer] = days
end

# Sort beers by their availability and first date of appearance
var availability = new HashMap[Beer, Int]
var appearances = new HashMap[Beer, String]
for beer in beers do
	var days = beer2days[beer]
	if days.not_empty then
		appearances[beer] = days.first
		availability[beer] = -days.length # Opposite for inverse sort
	else
		appearances[beer] = "err"
		availability[beer] = 1
	end
end

# Sort by availability then appearance
var sorter: Comparator = new BeerComparator(availability, appearances)
sorter.sort beers

# List all beers
print "\nBeers:"
for beer in beers do
	var days = beer2days[beer]

	# Skip never-available beers, usually name errors
	if days.is_empty then continue

	var from = days.first
	if from == all_days.first then from = "      ... "

	var to = days.last
	if to == all_days.last then to = " ...      "

	print "- {days.length}\t{from} {to}\t{beer.name}: {beer.desc}"
end

# Sort by appearance then availability
sorter = new BeerComparator(appearances, availability)
sorter.sort beers

# Display the batch graph
print "\nAvailability graph:"

# Compute `column_width` days from all the known days
var column_width = opt_columns.value
var days_sample = [for i in [1..column_width[ do all_days[i*all_days.length/column_width]]
var weeks_sample = new Array[Array[String]]

# Gather columns headers for each month
var headers = new Array[nullable String]
var iter = all_days.iterator
iter.start
var pre = ""
for day in days_sample do
	# Prepare headers
	var new_pre = day.substring(0, 7)

	if not day.has_prefix(pre) then
		headers.add new_pre
	else headers.add null

	pre = new_pre

	# Fill weeks
	var week = new Array[String]
	weeks_sample.add week
	while iter.is_ok do
		var item = iter.item
		if item == day then break
		week.add item
		iter.next
	end
end

# Draw the headers from top to bottom so they look like:
#
# ~~~
# 2
# 0
# 1
# 5
# -
# 0
# 1
# ~~~
for l in 7.times do
	for header in headers do
		if header != null then
			printn header[l]
		else printn " "
	end
	print ""
end

for beer in beers do
	var days = beer2days[beer]

	# Skip never-available beers, usually name errors
	if days.is_empty then continue

	# Print a line looking like: "  ############ ######    -----########- Beer"
	var last = null
	#var iter = days.iterator
	for week in weeks_sample do
		printn if days.has_all(week) then
		           "#"
		       else if days.has_any(week) then
		           ":"
		       else week.first.date_to_back
	end
	print " {beer.name}"
end

db.close


/*****************************************************************************/
// BeUtils.cpp
//
// Version: 1.0.0d1
//
// Several utilities for writing applications for the BeOS. It are small
// very specific functions, but generally useful (could be here because of a
// lack in the APIs, or just sheer lazyness :))
//
// Author
//   Ithamar R. Adema
//   Michael Pfeiffer
//
// This application and all source files used in its construction, except
// where noted, are licensed under the MIT License, and have been written
// and are:
//
// Copyright (c) 2001, 2002 OpenBeOS Project
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
/*****************************************************************************/

#include <Application.h>
#include <Bitmap.h>
#include <Messenger.h>
#include <Resources.h>
#include <Roster.h>
#include <String.h>

#include "BeUtils.h"

// ---------------------------------------------------------------
// TestForAddonExistence
//
// [Method Description]
//
// Parameters:
//
// Returns:
// ---------------------------------------------------------------
status_t TestForAddonExistence(const char* name, directory_which which, const char* section, BPath& outPath)
{
	status_t err = B_OK;

	if ((err=find_directory(which, &outPath)) == B_OK &&
		(err=outPath.Append(section)) == B_OK &&
		(err=outPath.Append(name)) == B_OK)
	{
		struct stat buf;
		err = stat(outPath.Path(), &buf);
	}

	return err;
}

// Implementation of AutoReply

AutoReply::AutoReply(BMessage* sender, uint32 what)
	: fSender(sender)
	, fReply(what)
{
}

AutoReply::~AutoReply() {
	fSender->SendReply(&fReply);
	delete fSender;
}

bool MimeTypeForSender(BMessage* sender, BString& mime) {
	BMessenger msgr = sender->ReturnAddress();
	team_id team = msgr.Team();
	app_info info;
	if (be_roster->GetRunningAppInfo(team, &info) == B_OK) {
		mime = info.signature;
		return true;
	}
	return false;
}


Resources:
  HtmlFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: s3://sam-demo-bucket/member_portal.zip
      Handler: index.gethtml
      Runtime: nodejs12.x
      Events:
        GetHtml:
          Type: Api
          Properties:
            RestApiId: HtmlApi
            Path: /{prameter}/resources
            Method: get

  HtmlApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      DefinitionUri: s3://sam-demo-bucket/webpage_swagger.json


package command

import (
	"flag"
	"fmt"
	"strings"

	"github.com/hashicorp/serf/cmd/serf/command/agent"
	"github.com/mitchellh/cli"
)

// TagsCommand is an interface to dynamically add or otherwise modify a
// running serf agent's tags.
type TagsCommand struct {
	Ui cli.Ui
}

var _ cli.Command = &TagsCommand{}

func (c *TagsCommand) Help() string {
	helpText := `
Usage: serf tags [options] ...

  Modifies tags on a running Serf agent.

Options:

  -rpc-addr=127.0.0.1:7373  RPC Address of the Serf agent.
  -rpc-auth=""              RPC auth token of the Serf agent.
  -set key=value            Creates or modifies the value of a tag
  -delete key               Removes a tag, if present
`
	return strings.TrimSpace(helpText)
}

func (c *TagsCommand) Run(args []string) int {
	var tagPairs []string
	var delTags []string
	cmdFlags := flag.NewFlagSet("tags", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
	cmdFlags.Var((*agent.AppendSliceValue)(&tagPairs), "set",
		"tag pairs, specified as key=value")
	cmdFlags.Var((*agent.AppendSliceValue)(&delTags), "delete",
		"tag keys to unset")
	rpcAddr := RPCAddrFlag(cmdFlags)
	rpcAuth := RPCAuthFlag(cmdFlags)
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	if len(tagPairs) == 0 && len(delTags) == 0 {
		c.Ui.Output(c.Help())
		return 1
	}

	client, err := RPCClient(*rpcAddr, *rpcAuth)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error connecting to Serf agent: %s", err))
		return 1
	}
	defer client.Close()

	tags, err := agent.UnmarshalTags(tagPairs)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error: %s", err))
		return 1
	}

	if err := client.UpdateTags(tags, delTags); err != nil {
		c.Ui.Error(fmt.Sprintf("Error setting tags: %s", err))
		return 1
	}

	c.Ui.Output("Successfully updated agent tags")
	return 0
}

func (c *TagsCommand) Synopsis() string {
	return "Modify tags of a running Serf agent"
}


#ifdef BLOG_CURRENT_CHANNEL
#undef BLOG_CURRENT_CHANNEL
#endif
#define BLOG_CURRENT_CHANNEL BLOG_CHANNEL_BLockReactor


from apps.common.coininfo import COINS

def by_shortcut(shortcut):
    for c in COINS:
        if c.coin_shortcut == shortcut:
            return c
    raise ValueError('Unknown coin shortcut "%s"' % shortcut)

def by_name(name):
    for c in COINS:
        if c.coin_name == name:
            return c
    raise ValueError('Unknown coin name "%s"' % name)

def by_slip44(slip44):
    for c in COINS:
        if c.slip44 == slip44:
            return c
    raise ValueError("Unknown coin slip44 index %d" % slip44)


/*
 * Copyright (c) 2019 - now, Eggroll Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.webank.eggroll.core.retry.impl.stop;

import com.google.common.base.Preconditions;
import com.webank.eggroll.core.retry.AttemptContext;
import com.webank.eggroll.core.retry.StopStrategy;
import javax.annotation.concurrent.Immutable;

@Immutable
public final class StopAfterMaxDelayStrategy implements StopStrategy {

  private final long maxDelay;

  public StopAfterMaxDelayStrategy(long maxDelay) {
    Preconditions.checkArgument(maxDelay >= 0, "maxDelay must >= 0");
    this.maxDelay = maxDelay;
  }

  @Override
  public boolean shouldStop(AttemptContext<?> failedAttemptContext) {
    return failedAttemptContext.getElapsedTimeSinceFirstAttempt() >= maxDelay;
  }
}


import BaseExpression from './base';
import Property from './basic/property';
import { castDate } from '../../../utils/util';
import ClusterTime from './aggregation/cluster/ClusterTime';
import { linear, globalMin, globalMax, number } from '../expressions';
import { checkType, checkFeatureIndependent, clamp, checkMaxArguments, implicitCast } from './utils';
import { Fade } from './Fade';

let waitingForLayer = new Set();
let waitingForOthers = new Set();

export default class AnimationGeneral extends BaseExpression {
    constructor (input, duration = 10, fade = new Fade()) {
        checkMaxArguments(arguments, 3, 'animation');
        duration = implicitCast(duration);
        input = implicitCast(input);
        super({ input, duration, fade });
        this._init();
    }
    _init () {
        const input = this.input;
        const originalInput = input;

        if (input.isA(Property) || (input.isA(ClusterTime) && input.type === 'timerange')) {
            this._input = linear(input, globalMin(input), globalMax(input), 'start');
        } else {
            this._input = this.input;
        }
        this.childrenNames = this.childrenNames.filter(x => x === '_input');
        this.childrenNames.push('_input');
        this.childrenNames.push('fade');
        this.childrenNames.push('duration');

        this.type = 'number';
        this._originalInput = originalInput;
        this._paused = false;
        this.progress = number(0);
        this.childrenNames.push('progress');

        this.expressionName = 'animation';

        this.preface = `
        #ifndef ANIMATION
        #define ANIMATION

        float animation(float _input, float progress, float duration, float fadeIn, float fadeOut){
            float x = 0.;

            // Check for NaN
            if (_input <= 0.0 || 0.0 <= _input){
                x = 1. - clamp(abs(_input - progress) * duration / (_input > progress ? fadeIn: fadeOut), 0., 1.);
            }

            return x;
        }

        #endif
    `;

        this.inlineMaker = inline => `animation(${inline._input}, ${inline.progress}, ${inline.duration}, ${inline.fade.in}, ${inline.fade.out})`;

        waitingForLayer.add(this);
        if (!this._paused) {
            this._paused = 'default';
        }
    }

    toString () {
        return `${this.expressionName}(${this._input.toString()}, ${this.duration.toString()}, ${this.fade.toString()})`;
    }

    _bindMetadata (metadata) {
        this._input._bindMetadata(metadata);
        this.progress._bindMetadata(metadata);
        this.fade._bindMetadata(metadata);
        this.duration._bindMetadata(metadata);

        checkType('animation', 'input', 0, ['number', 'date', 'timerange'], this._originalInput);
        checkType('animation', 'duration', 1, 'number', this.duration);

        checkType('animation', 'fade', 2, 'fade', this.fade);
        checkFeatureIndependent('animation', 'duration', 1, this.duration);
    }

    isAnimated () {
        return true;
    }

    _dataReady () {
        if (waitingForLayer.has(this)) {
            waitingForLayer.delete(this);
            waitingForOthers.add(this);
        }
        // setTimeout is needed to avoid the possibility of a de-synchronization of 1 frame
        // if the last layer to be loaded is not the first one on the painting loop
        setTimeout(() => {
            if (waitingForOthers.has(this)) {
                waitingForLayer = new Set([...waitingForLayer].filter(expr => {
                    while (expr.parent) {
                        expr = expr.parent;
                    }
                    if (expr._getRootExpressions) {
                        // The animation hasn't been removed from the viz
                        return true;
                    }
                    return false;
                }));
                if (waitingForLayer.size > 0) {
                    return;
                }
                [...waitingForOthers.values()].map(anim => {
                    if (anim._paused === 'default') {
                        anim.play();
                    }
                });
                waitingForOthers.clear();
            }
        }, 0);
    }

    _postShaderCompile (program, gl) {
        super._postShaderCompile(program, gl);
    }

    _setTimestamp (timestamp) {
        super._setTimestamp(timestamp);

        if (this._paused && this._lastTime === undefined) {
            return;
        }

        let deltaTime = 0;
        const speed = 1 / this.duration.value;

        if (this._lastTime !== undefined) {
            deltaTime = timestamp - this._lastTime;
        }

        this._lastTime = timestamp;

        if (this._paused) {
            return;
        }

        this.progress.value = (this.progress.value + speed * deltaTime) % 1;
    }

    eval (feature) {
        const input = this._input.eval(feature);

        if (input === null) {
            return 0;
        }

        const progress = this.progress.value;
        const duration = this.duration.value;
        const fadeIn = this.fade.fadeIn.eval(feature);
        const fadeOut = this.fade.fadeOut.eval(feature);

        const output = 1 - clamp(Math.abs(input - progress) * duration / (input > progress ? fadeIn : fadeOut), 0, 1);

        return output;
    }

    /**
     * Get the current time stamp of the animation
     *
     * @returns {Number|Date} Current time stamp of the animation. If the animation is based on a numeric expression this will output a number, if it is based on a date expression it will output a date
     *
     * @example <caption>Using the `getProgressValue` method to get the animation current value.</caption>
     * const s = carto.expressions;
     * let animationExpr = s.animation(s.linear(s.prop('saledate'), 1991, 2017), 20, s.fade(0.7, 0.4));
     * const animationStyle = {
     *   color: s.ramp(s.linear(s.prop('priceperunit'), 2000, 1010000), [s.rgb(0, 255, 0), s.rgb(255, 0, 0)]),
     *   width: s.mul(s.sqrt(s.prop('priceperunit')), 0.05),
     *   filter: animationExpr
     * };
     * layer.on('updated', () => {
     *   let currTime = Math.floor(animationExpr.getProgressValue());
     *   document.getElementById('timestamp').innerHTML = currTime;
     * });
     *
     * @memberof expressions.Animation
     * @name getProgressValue
     * @instance
     * @api
     */
    getProgressValue () {
        const progress = this.progress.value;
        return this._input.converse(progress);
    }

    /**
     * Set the time stamp of the animation
     * @api
     * @memberof expressions.Animation
     * @instance
     * @name setCurrent
     * @param {Date|number} value - A JavaScript Date object with the new animation time
     */
    setTimestamp (timestamp) {
        const date = castDate(timestamp);
        const [tmin, tmax] = this._input.limits();

        if (date.getTime() < tmin) {
            throw new RangeError('animation.setTimestamp requires the date parameter to be higher than the lower limit');
        }
        if (date.getTime() > tmax) {
            throw new RangeError('animation.setTimestamp requires the date parameter to be lower than the higher limit');
        }

        this.progress.value = (date.getTime() - tmin) / (tmax - tmin);
    }

    /**
     * Get the animation progress.
     *
     * @returns {Number} A number representing the progress. 0 when the animation just started and 1 at the end of the cycle.
     * @api
     * @instance
     * @memberof expressions.Animation
     * @name getProgressPct
     */
    getProgressPct () {
        return this.progress.value;
    }

    /**
     * Set the animation progress from 0 to 1.
     * @param {number} progress - A number in the [0-1] range setting the animation progress.
     * @api
     * @instance
     * @memberof expressions.Animation
     * @name setProgressPct
     */
    setProgressPct (progress) {
        progress = Number.parseFloat(progress);

        if (progress < 0 || progress > 1) {
            throw new TypeError(`animation.setProgressPct requires a number between 0 and 1 as parameter but got: ${progress}`);
        }

        this.progress.value = progress;
    }

    /**
     * Returns whether the animation is playing or not
     *
     * @api
     * @memberof expressions.Animation
     * @instance
     * @name isPlaying
     */
    isPlaying () {
        return this._paused === false;
    }

    /**
     * Pause the animation
     *
     * @api
     * @memberof expressions.Animation
     * @instance
     * @name pause
     */
    pause () {
        this._paused = true;
    }

    /**
     * Play/resume the animation
     *
     * @api
     * @memberof expressions.Animation
     * @instance
     * @name play
     */
    play () {
        this._paused = false;
        this.notify();
    }

    /**
     * Stops the animation
     *
     * @api
     * @memberof expressions.Animation
     * @instance
     * @name stop
     */
    stop () {
        this.progress.value = 0;
        this._paused = true;
    }
}


// Package watch provides a filesystem watcher that is used to rebuild affected targets.
package watch

import (
	"context"
	"fmt"
	"path"
	"time"

	"github.com/fsnotify/fsnotify"
	"github.com/streamrail/concurrent-map"
	"gopkg.in/op/go-logging.v1"

	"github.com/thought-machine/please/src/cli"
	"github.com/thought-machine/please/src/core"
	"github.com/thought-machine/please/src/fs"
	"github.com/thought-machine/please/src/run"
)

var log = logging.MustGetLogger("watch")

const debounceInterval = 100 * time.Millisecond

// A CallbackFunc is supplied to Watch in order to trigger a build.
type CallbackFunc func(*core.BuildState, []core.BuildLabel)

// Watch starts watching the sources of the given labels for changes and triggers
// rebuilds whenever they change.
// It never returns successfully, it will either watch forever or die.
func Watch(state *core.BuildState, labels core.BuildLabels, callback CallbackFunc) {
	// This hasn't been set before, do it now.
	state.NeedTests = anyTests(state, labels)
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatalf("Error setting up watcher: %s", err)
	}
	// This sets up the actual watches. It must be done in a separate goroutine.
	files := cmap.New()
	go startWatching(watcher, state, labels, files)

	parentCtx, cancelParent := context.WithCancel(context.Background())
	cli.AtExit(func() {
		cancelParent()
		time.Sleep(5 * time.Millisecond) // Brief pause to give the cancel() call time to progress before the process dies
	})

	ctx, cancel := context.WithCancel(parentCtx)

	// The initial setup only builds targets, it doesn't test or run things.
	// Do one of those now if requested.
	if state.NeedTests || state.NeedRun {
		build(ctx, state, labels, callback)
	}

	for {
		select {
		case event := <-watcher.Events:
			log.Info("Event: %s", event)
			if !files.Has(event.Name) {
				log.Notice("Skipping notification for %s", event.Name)
				continue
			}
			// Kill any previous process.
			cancel()
			ctx, cancel = context.WithCancel(parentCtx)

			// Quick debounce; poll and discard all events for the next brief period.
		outer:
			for {
				select {
				case <-watcher.Events:
				case <-time.After(debounceInterval):
					break outer
				}
			}
			build(ctx, state, labels, callback)
		case err := <-watcher.Errors:
			log.Error("Error watching files:", err)
		}
	}
}

func startWatching(watcher *fsnotify.Watcher, state *core.BuildState, labels []core.BuildLabel, files cmap.ConcurrentMap) {
	// Deduplicate seen targets & sources.
	targets := map[*core.BuildTarget]struct{}{}
	dirs := map[string]struct{}{}

	var startWatch func(*core.BuildTarget)
	startWatch = func(target *core.BuildTarget) {
		if _, present := targets[target]; present {
			return
		}
		targets[target] = struct{}{}
		for _, source := range target.AllSources() {
			addSource(watcher, state, source, dirs, files)
		}
		for _, datum := range target.AllData() {
			addSource(watcher, state, datum, dirs, files)
		}
		for _, dep := range target.Dependencies() {
			startWatch(dep)
		}
		pkg := state.Graph.PackageOrDie(target.Label)
		if !files.Has(pkg.Filename) {
			log.Notice("Adding watch on %s", pkg.Filename)
			files.Set(pkg.Filename, struct{}{})
		}
		for _, subinclude := range pkg.Subincludes {
			startWatch(state.Graph.TargetOrDie(subinclude))
		}
	}

	for _, label := range labels {
		startWatch(state.Graph.TargetOrDie(label))
	}
	// Drop a message here so they know when it's actually ready to go.
	fmt.Println("And now my watch begins...")
}

func addSource(watcher *fsnotify.Watcher, state *core.BuildState, source core.BuildInput, dirs map[string]struct{}, files cmap.ConcurrentMap) {
	if source.Label() == nil {
		for _, src := range source.Paths(state.Graph) {
			if err := fs.Walk(src, func(src string, isDir bool) error {
				files.Set(src, struct{}{})
				if !path.IsAbs(src) {
					files.Set("./"+src, struct{}{})
				}
				dir := src
				if !isDir {
					dir = path.Dir(src)
				}
				if _, present := dirs[dir]; !present {
					log.Notice("Adding watch on %s", dir)
					dirs[dir] = struct{}{}
					if err := watcher.Add(dir); err != nil {
						log.Error("Failed to add watch on %s: %s", src, err)
					}
				}
				return nil
			}); err != nil {
				log.Error("Failed to add watch on %s: %s", src, err)
			}
		}
	}
}

// anyTests returns true if any of the given labels refer to tests.
func anyTests(state *core.BuildState, labels []core.BuildLabel) bool {
	for _, l := range labels {
		if state.Graph.TargetOrDie(l).IsTest {
			return true
		}
	}
	return false
}

// build invokes a single build while watching.
func build(ctx context.Context, state *core.BuildState, labels []core.BuildLabel, callback CallbackFunc) {
	// Set up a new state & copy relevant parts off the existing one.
	ns := core.NewBuildState(state.Config)
	ns.Cache = state.Cache
	ns.VerifyHashes = state.VerifyHashes
	ns.NumTestRuns = state.NumTestRuns
	ns.NeedTests = state.NeedTests
	ns.NeedRun = state.NeedRun
	ns.Watch = true
	ns.CleanWorkdirs = state.CleanWorkdirs
	ns.DebugTests = state.DebugTests
	ns.ShowAllOutput = state.ShowAllOutput
	ns.StartTime = time.Now()
	callback(ns, labels)
	if state.NeedRun {
		// Don't wait for this, its lifetime will be controlled by the context.
		go run.Parallel(ctx, state, labels, nil, state.Config.Please.NumThreads, false, false, false, false, "")
	}
}


From df1cf48777fe4cd81ad7fb09ecbe5b31432b7c1c Mon Sep 17 00:00:00 2001
From: Yvan Roux <yvan.roux@linaro.org>
Date: Fri, 15 Apr 2016 13:29:26 +0200
Subject: [PATCH] Suppress GCC 6 warning about ambiguous 'else' with
 -Wparentheses

---
 nis/nis_call.c  |   20 +++++++++++---------
 stdlib/setenv.c |   24 +++++++++++++-----------
 2 files changed, 24 insertions(+), 20 deletions(-)

--- a/nis/nis_call.c
+++ b/nis/nis_call.c
@@ -680,16 +680,18 @@
   /* Choose which entry should be evicted from the cache.  */
   loc = &nis_server_cache[0];
   if (*loc != NULL)
-    for (i = 1; i < 16; ++i)
-      if (nis_server_cache[i] == NULL)
-	{
+    {
+      for (i = 1; i < 16; ++i)
+	if (nis_server_cache[i] == NULL)
+	  {
+	    loc = &nis_server_cache[i];
+	    break;
+	  }
+	else if ((*loc)->uses > nis_server_cache[i]->uses
+		 || ((*loc)->uses == nis_server_cache[i]->uses
+		     && (*loc)->expires > nis_server_cache[i]->expires))
 	  loc = &nis_server_cache[i];
-	  break;
-	}
-      else if ((*loc)->uses > nis_server_cache[i]->uses
-	       || ((*loc)->uses == nis_server_cache[i]->uses
-		   && (*loc)->expires > nis_server_cache[i]->expires))
-	loc = &nis_server_cache[i];
+    }
   old = *loc;
   *loc = new;

--- a/stdlib/setenv.c
+++ b/stdlib/setenv.c
@@ -289,18 +289,20 @@
   ep = __environ;
   if (ep != NULL)
     while (*ep != NULL)
-      if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
-	{
-	  /* Found it.  Remove this pointer by moving later ones back.  */
-	  char **dp = ep;
+      {
+	if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
+	  {
+	    /* Found it.  Remove this pointer by moving later ones back.  */
+	    char **dp = ep;

-	  do
-	    dp[0] = dp[1];
-	  while (*dp++);
-	  /* Continue the loop in case NAME appears again.  */
-	}
-      else
-	++ep;
+	    do
+		dp[0] = dp[1];
+	    while (*dp++);
+	    /* Continue the loop in case NAME appears again.  */
+	  }
+	else
+	  ++ep;
+      }

   UNLOCK;


<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="isometric" width="10" height="10" tilewidth="100" tileheight="50">
 <tileset firstgid="1" name="wetlands-ipad" tilewidth="100" tileheight="100" spacing="1" margin="1">
  <tileoffset x="0" y="15"/>
  <image source="tile_iso_offset.png" width="256" height="256"/>
     <tile id="0">
         <properties>
             <property name="altitude" value="0"/>
             <property name="isWater" value="0"/>
         </properties>
     </tile>
     <tile id="1">
         <properties>
             <property name="altitude" value="0"/>
             <property name="isWater" value="0"/>
         </properties>
     </tile>
     <tile id="2">
         <properties>
             <property name="altitude" value="2.5"/>
             <property name="isWater" value="0"/>
         </properties>
     </tile>
     <tile id="3">
         <properties>
             <property name="altitude" value="-1"/>
             <property name="isWater" value="1"/>
         </properties>
     </tile>
 </tileset>
 <layer name="baseLayer" width="10" height="10">
  <data encoding="base64" compression="zlib">
   eJxtkEEOwDAIwyDh/2/eDpsUWTlYSK0bCpoZBftygQr74fBc7lvmhktH0ZP5i+wr79Izzg+9jMp//hmcS8jNvXj6ng4OSfcBuQwA6g==
  </data>
 </layer>
</map>


神崎映美里最新番号
【CS-687】集団痴漢現場 3</a>2003-06-07アリーナエンターテインメント$$$Are50分钟


# frozen_string_literal: true

require 'spec_helper'

RSpec.describe 'ActiveRecord locking' do
  let(:issue) { create(:issue) }

  shared_examples 'locked model' do
    before do
      issue.update_column(:lock_version, start_lock_version)
    end

    it 'can be updated' do
      issue.update(title: "New title")

      expect(issue.reload.lock_version).to eq(new_lock_version)
    end

    it 'can be deleted' do
      expect { issue.destroy }.to change { Issue.count }.by(-1)
    end
  end

  context 'when lock_version is NULL' do
    let(:start_lock_version) { nil }
    let(:new_lock_version) { 1 }

    it_behaves_like 'locked model'
  end

  context 'when lock_version is 0' do
    let(:start_lock_version) { 0 }
    let(:new_lock_version) { 1 }

    it_behaves_like 'locked model'
  end

  context 'when lock_version is 1' do
    let(:start_lock_version) { 1 }
    let(:new_lock_version) { 2 }

    it_behaves_like 'locked model'
  end
end


'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", {
  "DATETIME_FORMATS": {
    "AMPMS": [
      "\u0bae\u0bc1\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd",
      "\u0baa\u0bbf\u0bb1\u0bcd\u0baa\u0b95\u0bb2\u0bcd"
    ],
    "DAY": [
      "\u0b9e\u0bbe\u0baf\u0bbf\u0bb1\u0bc1",
      "\u0ba4\u0bbf\u0b99\u0bcd\u0b95\u0bb3\u0bcd",
      "\u0b9a\u0bc6\u0bb5\u0bcd\u0bb5\u0bbe\u0baf\u0bcd",
      "\u0baa\u0bc1\u0ba4\u0ba9\u0bcd",
      "\u0bb5\u0bbf\u0baf\u0bbe\u0bb4\u0ba9\u0bcd",
      "\u0bb5\u0bc6\u0bb3\u0bcd\u0bb3\u0bbf",
      "\u0b9a\u0ba9\u0bbf"
    ],
    "ERANAMES": [
      "\u0b95\u0bbf\u0bb1\u0bbf\u0bb8\u0bcd\u0ba4\u0bc1\u0bb5\u0bc1\u0b95\u0bcd\u0b95\u0bc1 \u0bae\u0bc1\u0ba9\u0bcd",
      "\u0b85\u0ba9\u0bcb \u0b9f\u0bcb\u0bae\u0bbf\u0ba9\u0bbf"
    ],
    "ERAS": [
      "\u0b95\u0bbf.\u0bae\u0bc1.",
      "\u0b95\u0bbf.\u0baa\u0bbf."
    ],
    "FIRSTDAYOFWEEK": 6,
    "MONTH": [
      "\u0b9c\u0ba9\u0bb5\u0bb0\u0bbf",
      "\u0baa\u0bbf\u0baa\u0bcd\u0bb0\u0bb5\u0bb0\u0bbf",
      "\u0bae\u0bbe\u0bb0\u0bcd\u0b9a\u0bcd",
      "\u0b8f\u0baa\u0bcd\u0bb0\u0bb2\u0bcd",
      "\u0bae\u0bc7",
      "\u0b9c\u0bc2\u0ba9\u0bcd",
      "\u0b9c\u0bc2\u0bb2\u0bc8",
      "\u0b86\u0b95\u0bb8\u0bcd\u0b9f\u0bcd",
      "\u0b9a\u0bc6\u0baa\u0bcd\u0b9f\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
      "\u0b85\u0b95\u0bcd\u0b9f\u0bcb\u0baa\u0bb0\u0bcd",
      "\u0ba8\u0bb5\u0bae\u0bcd\u0baa\u0bb0\u0bcd",
      "\u0b9f\u0bbf\u0b9a\u0bae\u0bcd\u0baa\u0bb0\u0bcd"
    ],
    "SHORTDAY": [
      "\u0b9e\u0bbe",
      "\u0ba4\u0bbf",
      "\u0b9a\u0bc6",
      "\u0baa\u0bc1",
      "\u0bb5\u0bbf",
      "\u0bb5\u0bc6",
      "\u0b9a"
    ],
    "SHORTMONTH": [
      "\u0b9c\u0ba9.",
      "\u0baa\u0bbf\u0baa\u0bcd.",
      "\u0bae\u0bbe\u0bb0\u0bcd.",
      "\u0b8f\u0baa\u0bcd.",
      "\u0bae\u0bc7",
      "\u0b9c\u0bc2\u0ba9\u0bcd",
      "\u0b9c\u0bc2\u0bb2\u0bc8",
      "\u0b86\u0b95.",
      "\u0b9a\u0bc6\u0baa\u0bcd.",
      "\u0b85\u0b95\u0bcd.",
      "\u0ba8\u0bb5.",
      "\u0b9f\u0bbf\u0b9a."
    ],
    "WEEKENDRANGE": [
      6,
      6
    ],
    "fullDate": "EEEE, d MMMM, y",
    "longDate": "d MMMM, y",
    "medium": "d MMM, y h:mm:ss a",
    "mediumDate": "d MMM, y",
    "mediumTime": "h:mm:ss a",
    "short": "d-M-yy h:mm a",
    "shortDate": "d-M-yy",
    "shortTime": "h:mm a"
  },
  "NUMBER_FORMATS": {
    "CURRENCY_SYM": "\u20b9",
    "DECIMAL_SEP": ".",
    "GROUP_SEP": ",",
    "PATTERNS": [
      {
        "gSize": 2,
        "lgSize": 3,
        "maxFrac": 3,
        "minFrac": 0,
        "minInt": 1,
        "negPre": "-",
        "negSuf": "",
        "posPre": "",
        "posSuf": ""
      },
      {
        "gSize": 2,
        "lgSize": 3,
        "maxFrac": 2,
        "minFrac": 2,
        "minInt": 1,
        "negPre": "\u00a4\u00a0-",
        "negSuf": "",
        "posPre": "\u00a4\u00a0",
        "posSuf": ""
      }
    ]
  },
  "id": "ta",
  "pluralCat": function(n, opt_precision) {  if (n == 1) {    return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;}
});
}]);