<commit_before>/**
* simplePagination.js v1.1
* A simple jQuery pagination plugin.
* Author: Flavius Matis - http://flaviusmatis.github.com/
* URL: https://github.com/flaviusmatis/simplePagination.js
*/

(function($){

	var methods = {
		init: function(options) {
			var o = $.extend({
				items: 1,
				itemsOnPage: 1,
				pages: 0,
				displayedPages: 5,
				edges: 2,
				currentPage: 1,
				hrefText: '#page-',
				prevText: 'Prev',
				nextText: 'Next',
				ellipseText: '…',
				cssStyle: 'light-theme',
				selectOnClick: true,
				onClick: function() {
					return false;
				},
				callback: function() {
					return false;
				}
			}, options || {});

			return this.each(function() {
				o.pages = o.pages ? o.pages : Math.ceil(o.items / o.itemsOnPage) ? Math.ceil(o.items / o.itemsOnPage) : 1;
				o.currentPage = o.currentPage - 1;
				o.halfDisplayed = o.displayedPages / 2;
				$(this).addClass(o.cssStyle).data('pagination', o);
				methods._draw.call(this);
				o.callback(o.currentPage, this);
			});
		},

		selectPage: function(page) {
			methods._selectPage.call(this, page - 1);
		},

		prevPage: function() {
			var o = $(this).data('pagination');
			if (o.currentPage > 0) {
				methods._selectPage.call(this, o.currentPage - 1);
			}
		},

		nextPage: function() {
			var o = $(this).data('pagination');
			if (o.currentPage < o.pages - 1) {
				methods._selectPage.call(this, o.currentPage + 1);
			}
		},

		_draw: function() {
			var $panel = $(this).empty(),
				o = $panel.data('pagination'),
				interval = methods._getInterval(o),
				i;

			// Generate Prev link
			if (o.prevText) {
				methods._appendItem(this, o.currentPage - 1, {text: o.prevText, classes: 'prev'});
			}

			// Generate start edges
			if (interval.start > 0 && o.edges > 0) {
				var end = Math.min(o.edges, interval.start);
				for (i = 0; i < end; i++) {
					methods._appendItem(this, i);
				}
				if (o.edges < interval.start && o.ellipseText) {
					$panel.append('' + o.ellipseText + '');
				}
			}

			// Generate interval links
			for (i = interval.start; i < interval.end; i++) {
				methods._appendItem(this, i);
			}

			// Generate end edges
			if (interval.end < o.pages && o.edges > 0) {
				if (o.pages - o.edges > interval.end && o.ellipseText) {
					$panel.append('' + o.ellipseText + '');
				}
				var begin = Math.max(o.pages - o.edges, interval.end);
				for (i = begin; i < o.pages; i++) {
					methods._appendItem(this, i);
				}
			}

			// Generate Next link
			if (o.nextText) {
				methods._appendItem(this, o.currentPage + 1, {text: o.nextText, classes: 'next'});
			}
		},

		_getInterval: function(o) {
			return {
				start: Math.ceil(o.currentPage > o.halfDisplayed ? Math.max(Math.min(o.currentPage - o.halfDisplayed, (o.pages - o.displayedPages)), 0) : 0),
				end: Math.ceil(o.currentPage > o.halfDisplayed ? Math.min(o.currentPage + o.halfDisplayed, o.pages) : Math.min(o.displayedPages, o.pages))
			};
		},

		_appendItem: function(panel, pageIndex, opts) {
			var options, $link, o = $(panel).data('pagination');

			pageIndex = pageIndex < 0 ? 0 : (pageIndex < o.pages ? pageIndex : o.pages - 1);

			options = $.extend({
				text: pageIndex + 1,
				classes: ''
			}, opts || {});

			if (pageIndex == o.currentPage) {
				$link = $('' + (options.text) + '');
			} else {
				$link = $('' + (options.text) + '');
				$link.click(function(){
					methods._selectPage.call(panel, pageIndex);
				});
			}
			if (options.classes) {
				$link.addClass(options.classes);
			}

			$(panel).append($link);
		},

		_selectPage: function(pageIndex) {
			var o = $(this).data('pagination');
			o.currentPage = pageIndex;
			if (o.selectOnClick) {
				o.onClick(pageIndex + 1, $(this));
				methods._draw.call(this);
			} else {
				o.onClick(pageIndex + 1, $(this));
			}
		}

	};

	$.fn.pagination = function(method) {

		// Method calling logic
		if (methods[method] && method.charAt(0) != '_') {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		} else {
			$.error('Method ' +  method + ' does not exist on jQuery.pagination');
		}

	};

})(jQuery);<commit_msg>Renamed onClick to onPageClick and callback to onInit. Added page number parameter to onPageClick.<commit_after>/**
* simplePagination.js v1.2
* A simple jQuery pagination plugin.
* Author: Flavius Matis - http://flaviusmatis.github.com/
* URL: https://github.com/flaviusmatis/simplePagination.js
*/

(function($){

	var methods = {
		init: function(options) {
			var o = $.extend({
				items: 1,
				itemsOnPage: 1,
				pages: 0,
				displayedPages: 5,
				edges: 2,
				currentPage: 1,
				hrefText: '#page-',
				prevText: 'Prev',
				nextText: 'Next',
				ellipseText: '…',
				cssStyle: 'light-theme',
				selectOnClick: true,
				onPageClick: function(pageNumber) {
					// Callback triggered when a page is clicked
					// Page number is given as an optional parameter
				},
				onInit: function() {
					// Callback triggered immediately after initialization
				}
			}, options || {});

			return this.each(function() {
				o.pages = o.pages ? o.pages : Math.ceil(o.items / o.itemsOnPage) ? Math.ceil(o.items / o.itemsOnPage) : 1;
				o.currentPage = o.currentPage - 1;
				o.halfDisplayed = o.displayedPages / 2;
				$(this).addClass(o.cssStyle).data('pagination', o);
				methods._draw.call(this);
				o.onInit();
			});
		},

		selectPage: function(page) {
			methods._selectPage.call(this, page - 1);
		},

		prevPage: function() {
			var o = $(this).data('pagination');
			if (o.currentPage > 0) {
				methods._selectPage.call(this, o.currentPage - 1);
			}
		},

		nextPage: function() {
			var o = $(this).data('pagination');
			if (o.currentPage < o.pages - 1) {
				methods._selectPage.call(this, o.currentPage + 1);
			}
		},

		_draw: function() {
			var $panel = $(this).empty(),
				o = $panel.data('pagination'),
				interval = methods._getInterval(o),
				i;

			// Generate Prev link
			if (o.prevText) {
				methods._appendItem(this, o.currentPage - 1, {text: o.prevText, classes: 'prev'});
			}

			// Generate start edges
			if (interval.start > 0 && o.edges > 0) {
				var end = Math.min(o.edges, interval.start);
				for (i = 0; i < end; i++) {
					methods._appendItem(this, i);
				}
				if (o.edges < interval.start && o.ellipseText) {
					$panel.append('' + o.ellipseText + '');
				}
			}

			// Generate interval links
			for (i = interval.start; i < interval.end; i++) {
				methods._appendItem(this, i);
			}

			// Generate end edges
			if (interval.end < o.pages && o.edges > 0) {
				if (o.pages - o.edges > interval.end && o.ellipseText) {
					$panel.append('' + o.ellipseText + '');
				}
				var begin = Math.max(o.pages - o.edges, interval.end);
				for (i = begin; i < o.pages; i++) {
					methods._appendItem(this, i);
				}
			}

			// Generate Next link
			if (o.nextText) {
				methods._appendItem(this, o.currentPage + 1, {text: o.nextText, classes: 'next'});
			}
		},

		_getInterval: function(o) {
			return {
				start: Math.ceil(o.currentPage > o.halfDisplayed ? Math.max(Math.min(o.currentPage - o.halfDisplayed, (o.pages - o.displayedPages)), 0) : 0),
				end: Math.ceil(o.currentPage > o.halfDisplayed ? Math.min(o.currentPage + o.halfDisplayed, o.pages) : Math.min(o.displayedPages, o.pages))
			};
		},

		_appendItem: function(panel, pageIndex, opts) {
			var options, $link, o = $(panel).data('pagination');

			pageIndex = pageIndex < 0 ? 0 : (pageIndex < o.pages ? pageIndex : o.pages - 1);

			options = $.extend({
				text: pageIndex + 1,
				classes: ''
			}, opts || {});

			if (pageIndex == o.currentPage) {
				$link = $('' + (options.text) + '');
			} else {
				$link = $('' + (options.text) + '');
				$link.click(function(){
					methods._selectPage.call(panel, pageIndex);
				});
			}
			if (options.classes) {
				$link.addClass(options.classes);
			}

			$(panel).append($link);
		},

		_selectPage: function(pageIndex) {
			var o = $(this).data('pagination');
			o.currentPage = pageIndex;
			if (o.selectOnClick) {
				o.onPageClick(pageIndex + 1);
				methods._draw.call(this);
			} else {
				o.onPageClick(pageIndex + 1);
			}
		}

	};

	$.fn.pagination = function(method) {

		// Method calling logic
		if (methods[method] && method.charAt(0) != '_') {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		} else {
			$.error('Method ' +  method + ' does not exist on jQuery.pagination');
		}

	};

})(jQuery);<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
 * See the License for the specific language governing rights and
 * limitations under the License.
 *
 * The Original Code is Bespin and CodeMirror.
 *
 * The Initial Developer of the Original Code is Marijn Haverbeke.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Bespin Team (bespin@mozilla.com)
 *
 * ORIGINAL CodeMirror BSD-style-licensed CODE LICENSE HEADER FOLLOWS:

// Copyright (c) 2007-2009 Marijn Haverbeke
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any
// damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any
// purpose, including commercial applications, and to alter it and
// redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must
//    not claim that you wrote the original software. If you use this
//    software in a product, an acknowledgment in the product
//    documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must
//    not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
// Marijn Haverbeke
// marijnh at gmail
 * ***** END LICENSE BLOCK ***** */

// = Tokenizer and parser utilities =

dojo.provide("bespin.syntax.codemirror._base");

// ** {{{ bespin.syntax.codemirror.Model }}} **
//
// Tracks syntax highlighting data on a per-visible-lines basis.
dojo.declare("bespin.syntax.codemirror.Model", bespin.syntax.Model, {
    worker: true,

    constructor: function() {
        // required for worker facade
        this.resolver = bespin.syntax.codemirror.Resolver;
    },

    // ** {{{ getSyntaxStyles }}} **
    //
    // Given rows, visible range and syntax type (e.g. css, js, html) hunt down the engine, ask it to syntax highlight, and return the regions
    getSyntaxStyles: function(rows, firstLineToRender, lastLineToRender, language) {
        var syntaxResults = {};

        if (this.language != language) {
            this.invalidateEntireCache();
            this.engine = this.resolver.resolve(language);
            this.language = language;
        } else {
            // try to get syntaxResults from cache
            var decr = lastLineToRender - firstLineToRender + 1;

            for (var currentLine = firstLineToRender; currentLine <= lastLineToRender; currentLine++) {
                var cached = this.getFromCache(currentLine);
                if (cached) {
                    syntaxResults[currentLine] = cached;
                    decr--;
                } else {
                    firstLineToRender = currentLine;
                    break;
                }
            }

            if (decr == 0) {
               return syntaxResults;
            }
        }

        var newResults = this.engine.highlight(rows, firstLineToRender, lastLineToRender, this.resolver.engines) ;

        for (var currentLine = firstLineToRender; currentLine <= lastLineToRender; currentLine++) {
            this.addToCache(currentLine, newResults[currentLine]);
            syntaxResults[currentLine] = newResults[currentLine];
        }

        return syntaxResults;
    }
});

// ** {{{ bespin.syntax.codemirror.Resolver }}} **
//
// The resolver holds the engines per language that are available to do the actual syntax highlighting
bespin.syntax.codemirror.Resolver = new function() {
  return {
      engines: {},

      // ** {{{ Noop }}} **
      //
      // Return plain regions / entire lines for all visible lines
      NoopSyntaxEngine: {
          highlight: function(rows, firstLineToRender, lastLineToRender) {
              var lineInfos = {};

              for (var lineNumber = firstLineToRender; lineNumber <= lastLineToRender; lineNumber++) {
                  lineInfos[lineNumber] = {};
                  lineInfos[lineNumber].text = rows[lineNumber];
                  lineInfos[lineNumber].regions = [];
                  lineInfos[lineNumber].regions.push({plain: [{
                      start: 0,
                      stop: rows[lineNumber].length
                  }]});
              }

              return lineInfos;
          }
      },

      // ** {{{ highlight }}} **
      //
      // A high level highlight function that uses the {{{language}}} to get the engine, and asks it to highlight
      highlight: function(language, rows, firstLineToRender, lastLineToRender) {
          this.resolve(language).highlight(rows, firstLineToRender, lastLineToRender);
      },

      // ** {{{ register }}} **
      //
      // Engines register themselves,
      // e.g. {{{bespin.syntax.codemirror.Resolver.register(new bespin.syntax.codemirror.CSSS(), ['css']);}}}
      register: function(languageEngine, languages) {
          for (var i = 0; i < languages.length; i++) {
              this.engines[languages[i]] = languageEngine;
          }
      },

      // ** {{{ resolve }}} **
      //
      // Hunt down the engine for the given {{{type}}} (e.g. css, js, html) or return the {{{NoopSyntaxEngine}}}
      resolve: function(language) {
          return this.engines[language] || this.NoopSyntaxEngine;
      }
  };
}();

// ** {{{ bespin.syntax.codemirror.Base }}} **
dojo.declare("bespin.syntax.codemirror.Base", null, {

    indentUnit: 4,

    // the parser and its frozen state on a per line basis
    parsers: [],

    // the textlines (minus "\n" at line-end)
    rows: [],

    // The value used to signal the end of a sequence in iterators.
    StopIteration: {
        toString: function() {
            return "StopIteration";
        }
    },

    // Helper function for for regular expression matches
    matcher: function(regexp){
        return function(value) {
            return regexp.test(value);
        };
    },

    // Checks whether the argument is an iterator or a regular sequence,
    // turns it into an iterator.
    iter: function(seq) {
        var self = this;
        var i = 0;

        if (seq.next) {
            return seq;
        } else {
            return {
                next: function() {
                    if (i >= seq.length) {
                        throw self.StopIteration;
                    } else {
                        return seq[i++];
                    }
                }
            };
        }
    },

    // Apply a function to each element in a sequence.
    forEach: function(iter, f) {
        var self = this;

        if (iter.next) {
            try {
                while (true) {
                    f(iter.next());
                }
            } catch (e) {
                if (e != self.StopIteration) throw e;
            }
        }
      else {
          for (var i = 0; i < iter.length; i++) {
              f(iter[i]);
          }
        }
    },

    // Provides a stream interface for a traverser-wrapped document
    stringStream: function(source) {
        var self = this;

        source = this.iter(source);

        // String that's currently being iterated over.
        var current = "";

        // Position in that string.
        var pos = 0;

        // for Bespin
        var start = 0;
        var lineNumber = 0;

        // Accumulator for strings that have been iterated over but not
        // get()-ed yet.
        var accum = "";

        var sourceNextObj;

        // Wrapper for source.next().
        function sourceNext() {
            sourceNextObj = source.next();
            current = sourceNextObj.text;
        }

        // Make sure there are more characters ready, or throw
        // StopIteration.
        function ensureChars() {
            while (pos == current.length) {
                accum += current;
                current = ""; // In case source.next() throws
                pos = 0;
                try {
                    sourceNext();
                } catch (e) {
                    if (e != self.StopIteration) {
                        throw e;
                    } else {
                        return false;
                    }
                }
            }
            return true;
        }

        return {
            // Return the next character in the stream.
            peek: function() {
                if (!ensureChars()) {
                    return null;
                }
                return current.charAt(pos);
            },

            // Get the next character, throw StopIteration if at end, check
            // for unused content.
            next: function() {
                if (!ensureChars()) {
                    if (accum.length > 0) {
                        throw "End of stringstream reached without emptying buffer ('" + accum + "').";
                    } else {
                        throw self.StopIteration;
                    }
                }

                var ch = current.charAt(pos++);
                if (ch == "\n"){
                    start = 0;
                } else {
                    start++;
                }
                return ch;

            },

            // Return the characters iterated over since the last call to
            // .get().
            get: function() {
                var temp = accum;
                accum = "";
                colBeforeGet = pos;
                lineNumber = sourceNextObj.lineNumber;
                if (pos > 0){
                    temp += current.slice(0, pos);
                    current = current.slice(pos);
                    pos = 0;
                }
                return temp;
            },

            // Push a string back into the stream.
            push: function(str) {
                current = current.slice(0, pos) + str + current.slice(pos);
            },

            lookAhead: function(str, consume, skipSpaces, caseInsensitive) {
                function cased(str) {
                    return caseInsensitive ? str.toLowerCase() : str;
                }
                str = cased(str);
                var found = false;

                var _accum = accum;
                var _pos = pos;
                if (skipSpaces) {
                    this.nextWhile(self.matcher(/[\s\u00a0]/));
                }

                while (true) {
                    var end = pos + str.length;
                    var left = current.length - pos;
                    if (end <= current.length) {
                        found = str == cased(current.slice(pos, end));
                        pos = end;
                        break;
                    } else if (str.slice(0, left) == cased(current.slice(pos))) {
                        accum += current; current = "";
                        try {
                            sourceNext();
                        } catch (e) {
                            break;
                        }
                        pos = 0;
                        str = str.slice(left);
                    } else {
                        break;
                    }
                }

                if (!(found && consume)) {
                    current = accum.slice(_accum.length) + current;
                    pos = _pos;
                    accum = _accum;
                }

                return found;
            },

            // Utils built on top of the above
            more: function() {
                return this.peek() !== null;
            },

            applies: function(test) {
                var next = this.peek();
                return (next !== null && test(next));
            },

            nextWhile: function(test) {
                while (this.applies(test)) {
                    this.next();
                }
            },

            equals: function(ch) {
                return ch === this.peek();
            },

            endOfLine: function() {
                var next = this.peek();
                return next == null || next == "\n";
            },

            start: function() {
                return start;
            },

            lineNumber: function() {
                return lineNumber;
            }
        };
    },

    // traverses the document, its output is the input for stringStream
    traverser: function(rows, start) {
        var self = this;
        var cc = push(handleLine, start, stop);

        function yield(value, c) {
            cc = c;
            return value;
        }

        function push(fun, arg, c) {
            return function() { return fun(arg, c);};
        }

        // Stops the iterator
        function stop() {
            cc = stop;
            throw self.StopIteration;
        };

        // Handle a line. Add its successor to the continuation if there
        // is one.
        // Yield content of the line
        function handleLine(lineNumber, c){
            c = push(handleLine, lineNumber + 1, c);

            return yield({
                text: rows[lineNumber] + "\n",
                lineNumber: lineNumber
            }, c);
        }

        // Iterator with a next function that returns the next value
        // or throws StopIteration when there are no more values.
        return {
            next: function() {
                return cc();
            }
        };
    },

    baseTokenizer: function(source, state) {
        var self = this;

        // Newlines are always a separate token.
        function isWhiteSpace(ch) {
            // The messy regexp is because IE's regexp matcher is of the
            // opinion that non-breaking spaces are no whitespace.
            return ch != "\n" && (/^[\s\u00a0]*$/.test(ch));
        }

        var tokenizer = {
            state: state,

            take: function(type) {
                if (typeof(type) == "string"){
                    type = {style: type, type: type};
                }
                type.content = (type.content || "") + source.get();
                if (!(/\n$/.test(type.content))){
                    source.nextWhile(isWhiteSpace);
                }
                type.value = type.content + source.get();
                type.lineNumber = source.lineNumber();
                if ((type.type != "whitespace") || (type.content != "\n")) {
                    type.start = source.start() - type.value.length;
                    type.stop = type.start + type.content.length;
                }
                return type;
            },

            next: function () {
                if (!source.more()){
                    throw self.StopIteration;
                }

                var type;
                if (source.equals("\n")) {
                    source.next();
                    return this.take("whitespace");
                }

                if (source.applies(isWhiteSpace)) {
                    type = "whitespace";
                } else {
                    while (!type) {
                        type = this.state(source, function(s) {
                            tokenizer.state = s;
                        });
                    }
                }
                return this.take(type);
            }
        };

        return tokenizer;
    },

    highlight: function(rows, firstLineToRender, lastLineToRender, engines) {
        this.rows = rows;
        this.engines = engines;

        var self = this;
        var lineInfos = {};
        var from = firstLineToRender;
        var parser;

        for (var currentLine = firstLineToRender; currentLine <= lastLineToRender; currentLine++) {
            lineInfos[currentLine] = {};
            lineInfos[currentLine].text = rows[currentLine];
            lineInfos[currentLine].regions = [];
        }

        while (from > 0){
            if (from < firstLineToRender && this.parsers[from]) {
               parser = this.parsers[from];
               from++;
               break;
            } else {
               from--;
            }
        }

        var stream = this.stringStream(this.traverser(rows, from));
        var parsed = (parser) ? parser(stream) : this.makeParser(stream);

        this.forEach.call(this, parsed, function(token){
            if (token.value == "\n") {
                self.parsers[token.lineNumber] = parsed.copy();
            }

            if (token.lineNumber > lastLineToRender) {
                throw self.StopIteration;
            } else if ((token.lineNumber >= firstLineToRender) && (token.value != "\n")) {
                self.updateLineInfos(lineInfos, token);
            }
        });

        return lineInfos;
    }
});

// -- Add core syntax files here, can load others later
dojo.require("bespin.syntax.codemirror.javascript");
dojo.require("bespin.syntax.codemirror.css");
dojo.require("bespin.syntax.codemirror.xml");
dojo.require("bespin.syntax.codemirror.html");
dojo.require("bespin.syntax.codemirror.php_base");
dojo.require("bespin.syntax.codemirror.php");
dojo.require("bespin.syntax.codemirror.python");<commit_msg>Comment out an entire file, that seems to not be used<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
 * See the License for the specific language governing rights and
 * limitations under the License.
 *
 * The Original Code is Bespin and CodeMirror.
 *
 * The Initial Developer of the Original Code is Marijn Haverbeke.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Bespin Team (bespin@mozilla.com)
 *
 * ORIGINAL CodeMirror BSD-style-licensed CODE LICENSE HEADER FOLLOWS:

// Copyright (c) 2007-2009 Marijn Haverbeke
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any
// damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any
// purpose, including commercial applications, and to alter it and
// redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must
//    not claim that you wrote the original software. If you use this
//    software in a product, an acknowledgment in the product
//    documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must
//    not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
// Marijn Haverbeke
// marijnh at gmail
 * ***** END LICENSE BLOCK ***** */

// = Tokenizer and parser utilities =

/*

dojo.provide("bespin.syntax.codemirror._base");

// ** {{{ bespin.syntax.codemirror.Model }}} **
//
// Tracks syntax highlighting data on a per-visible-lines basis.
dojo.declare("bespin.syntax.codemirror.Model", bespin.syntax.Model, {
    worker: true,

    constructor: function() {
        // required for worker facade
        this.resolver = bespin.syntax.codemirror.Resolver;
    },

    // ** {{{ getSyntaxStyles }}} **
    //
    // Given rows, visible range and syntax type (e.g. css, js, html) hunt down the engine, ask it to syntax highlight, and return the regions
    getSyntaxStyles: function(rows, firstLineToRender, lastLineToRender, language) {
        var syntaxResults = {};

        if (this.language != language) {
            this.invalidateEntireCache();
            this.engine = this.resolver.resolve(language);
            this.language = language;
        } else {
            // try to get syntaxResults from cache
            var decr = lastLineToRender - firstLineToRender + 1;

            for (var currentLine = firstLineToRender; currentLine <= lastLineToRender; currentLine++) {
                var cached = this.getFromCache(currentLine);
                if (cached) {
                    syntaxResults[currentLine] = cached;
                    decr--;
                } else {
                    firstLineToRender = currentLine;
                    break;
                }
            }

            if (decr == 0) {
               return syntaxResults;
            }
        }

        var newResults = this.engine.highlight(rows, firstLineToRender, lastLineToRender, this.resolver.engines) ;

        for (var currentLine = firstLineToRender; currentLine <= lastLineToRender; currentLine++) {
            this.addToCache(currentLine, newResults[currentLine]);
            syntaxResults[currentLine] = newResults[currentLine];
        }

        return syntaxResults;
    }
});

// ** {{{ bespin.syntax.codemirror.Resolver }}} **
//
// The resolver holds the engines per language that are available to do the actual syntax highlighting
bespin.syntax.codemirror.Resolver = new function() {
  return {
      engines: {},

      // ** {{{ Noop }}} **
      //
      // Return plain regions / entire lines for all visible lines
      NoopSyntaxEngine: {
          highlight: function(rows, firstLineToRender, lastLineToRender) {
              var lineInfos = {};

              for (var lineNumber = firstLineToRender; lineNumber <= lastLineToRender; lineNumber++) {
                  lineInfos[lineNumber] = {};
                  lineInfos[lineNumber].text = rows[lineNumber];
                  lineInfos[lineNumber].regions = [];
                  lineInfos[lineNumber].regions.push({plain: [{
                      start: 0,
                      stop: rows[lineNumber].length
                  }]});
              }

              return lineInfos;
          }
      },

      // ** {{{ highlight }}} **
      //
      // A high level highlight function that uses the {{{language}}} to get the engine, and asks it to highlight
      highlight: function(language, rows, firstLineToRender, lastLineToRender) {
          this.resolve(language).highlight(rows, firstLineToRender, lastLineToRender);
      },

      // ** {{{ register }}} **
      //
      // Engines register themselves,
      // e.g. {{{bespin.syntax.codemirror.Resolver.register(new bespin.syntax.codemirror.CSSS(), ['css']);}}}
      register: function(languageEngine, languages) {
          for (var i = 0; i < languages.length; i++) {
              this.engines[languages[i]] = languageEngine;
          }
      },

      // ** {{{ resolve }}} **
      //
      // Hunt down the engine for the given {{{type}}} (e.g. css, js, html) or return the {{{NoopSyntaxEngine}}}
      resolve: function(language) {
          return this.engines[language] || this.NoopSyntaxEngine;
      }
  };
}();

// ** {{{ bespin.syntax.codemirror.Base }}} **
dojo.declare("bespin.syntax.codemirror.Base", null, {

    indentUnit: 4,

    // the parser and its frozen state on a per line basis
    parsers: [],

    // the textlines (minus "\n" at line-end)
    rows: [],

    // The value used to signal the end of a sequence in iterators.
    StopIteration: {
        toString: function() {
            return "StopIteration";
        }
    },

    // Helper function for for regular expression matches
    matcher: function(regexp){
        return function(value) {
            return regexp.test(value);
        };
    },

    // Checks whether the argument is an iterator or a regular sequence,
    // turns it into an iterator.
    iter: function(seq) {
        var self = this;
        var i = 0;

        if (seq.next) {
            return seq;
        } else {
            return {
                next: function() {
                    if (i >= seq.length) {
                        throw self.StopIteration;
                    } else {
                        return seq[i++];
                    }
                }
            };
        }
    },

    // Apply a function to each element in a sequence.
    forEach: function(iter, f) {
        var self = this;

        if (iter.next) {
            try {
                while (true) {
                    f(iter.next());
                }
            } catch (e) {
                if (e != self.StopIteration) throw e;
            }
        }
      else {
          for (var i = 0; i < iter.length; i++) {
              f(iter[i]);
          }
        }
    },

    // Provides a stream interface for a traverser-wrapped document
    stringStream: function(source) {
        var self = this;

        source = this.iter(source);

        // String that's currently being iterated over.
        var current = "";

        // Position in that string.
        var pos = 0;

        // for Bespin
        var start = 0;
        var lineNumber = 0;

        // Accumulator for strings that have been iterated over but not
        // get()-ed yet.
        var accum = "";

        var sourceNextObj;

        // Wrapper for source.next().
        function sourceNext() {
            sourceNextObj = source.next();
            current = sourceNextObj.text;
        }

        // Make sure there are more characters ready, or throw
        // StopIteration.
        function ensureChars() {
            while (pos == current.length) {
                accum += current;
                current = ""; // In case source.next() throws
                pos = 0;
                try {
                    sourceNext();
                } catch (e) {
                    if (e != self.StopIteration) {
                        throw e;
                    } else {
                        return false;
                    }
                }
            }
            return true;
        }

        return {
            // Return the next character in the stream.
            peek: function() {
                if (!ensureChars()) {
                    return null;
                }
                return current.charAt(pos);
            },

            // Get the next character, throw StopIteration if at end, check
            // for unused content.
            next: function() {
                if (!ensureChars()) {
                    if (accum.length > 0) {
                        throw "End of stringstream reached without emptying buffer ('" + accum + "').";
                    } else {
                        throw self.StopIteration;
                    }
                }

                var ch = current.charAt(pos++);
                if (ch == "\n"){
                    start = 0;
                } else {
                    start++;
                }
                return ch;

            },

            // Return the characters iterated over since the last call to
            // .get().
            get: function() {
                var temp = accum;
                accum = "";
                colBeforeGet = pos;
                lineNumber = sourceNextObj.lineNumber;
                if (pos > 0){
                    temp += current.slice(0, pos);
                    current = current.slice(pos);
                    pos = 0;
                }
                return temp;
            },

            // Push a string back into the stream.
            push: function(str) {
                current = current.slice(0, pos) + str + current.slice(pos);
            },

            lookAhead: function(str, consume, skipSpaces, caseInsensitive) {
                function cased(str) {
                    return caseInsensitive ? str.toLowerCase() : str;
                }
                str = cased(str);
                var found = false;

                var _accum = accum;
                var _pos = pos;
                if (skipSpaces) {
                    this.nextWhile(self.matcher(/[\s\u00a0]/));
                }

                while (true) {
                    var end = pos + str.length;
                    var left = current.length - pos;
                    if (end <= current.length) {
                        found = str == cased(current.slice(pos, end));
                        pos = end;
                        break;
                    } else if (str.slice(0, left) == cased(current.slice(pos))) {
                        accum += current; current = "";
                        try {
                            sourceNext();
                        } catch (e) {
                            break;
                        }
                        pos = 0;
                        str = str.slice(left);
                    } else {
                        break;
                    }
                }

                if (!(found && consume)) {
                    current = accum.slice(_accum.length) + current;
                    pos = _pos;
                    accum = _accum;
                }

                return found;
            },

            // Utils built on top of the above
            more: function() {
                return this.peek() !== null;
            },

            applies: function(test) {
                var next = this.peek();
                return (next !== null && test(next));
            },

            nextWhile: function(test) {
                while (this.applies(test)) {
                    this.next();
                }
            },

            equals: function(ch) {
                return ch === this.peek();
            },

            endOfLine: function() {
                var next = this.peek();
                return next == null || next == "\n";
            },

            start: function() {
                return start;
            },

            lineNumber: function() {
                return lineNumber;
            }
        };
    },

    // traverses the document, its output is the input for stringStream
    traverser: function(rows, start) {
        var self = this;
        var cc = push(handleLine, start, stop);

        function yield(value, c) {
            cc = c;
            return value;
        }

        function push(fun, arg, c) {
            return function() { return fun(arg, c);};
        }

        // Stops the iterator
        function stop() {
            cc = stop;
            throw self.StopIteration;
        };

        // Handle a line. Add its successor to the continuation if there
        // is one.
        // Yield content of the line
        function handleLine(lineNumber, c){
            c = push(handleLine, lineNumber + 1, c);

            return yield({
                text: rows[lineNumber] + "\n",
                lineNumber: lineNumber
            }, c);
        }

        // Iterator with a next function that returns the next value
        // or throws StopIteration when there are no more values.
        return {
            next: function() {
                return cc();
            }
        };
    },

    baseTokenizer: function(source, state) {
        var self = this;

        // Newlines are always a separate token.
        function isWhiteSpace(ch) {
            // The messy regexp is because IE's regexp matcher is of the
            // opinion that non-breaking spaces are no whitespace.
            return ch != "\n" && (/^[\s\u00a0]*$/.test(ch));
        }

        var tokenizer = {
            state: state,

            take: function(type) {
                if (typeof(type) == "string"){
                    type = {style: type, type: type};
                }
                type.content = (type.content || "") + source.get();
                if (!(/\n$/.test(type.content))){
                    source.nextWhile(isWhiteSpace);
                }
                type.value = type.content + source.get();
                type.lineNumber = source.lineNumber();
                if ((type.type != "whitespace") || (type.content != "\n")) {
                    type.start = source.start() - type.value.length;
                    type.stop = type.start + type.content.length;
                }
                return type;
            },

            next: function () {
                if (!source.more()){
                    throw self.StopIteration;
                }

                var type;
                if (source.equals("\n")) {
                    source.next();
                    return this.take("whitespace");
                }

                if (source.applies(isWhiteSpace)) {
                    type = "whitespace";
                } else {
                    while (!type) {
                        type = this.state(source, function(s) {
                            tokenizer.state = s;
                        });
                    }
                }
                return this.take(type);
            }
        };

        return tokenizer;
    },

    highlight: function(rows, firstLineToRender, lastLineToRender, engines) {
        this.rows = rows;
        this.engines = engines;

        var self = this;
        var lineInfos = {};
        var from = firstLineToRender;
        var parser;

        for (var currentLine = firstLineToRender; currentLine <= lastLineToRender; currentLine++) {
            lineInfos[currentLine] = {};
            lineInfos[currentLine].text = rows[currentLine];
            lineInfos[currentLine].regions = [];
        }

        while (from > 0){
            if (from < firstLineToRender && this.parsers[from]) {
               parser = this.parsers[from];
               from++;
               break;
            } else {
               from--;
            }
        }

        var stream = this.stringStream(this.traverser(rows, from));
        var parsed = (parser) ? parser(stream) : this.makeParser(stream);

        this.forEach.call(this, parsed, function(token){
            if (token.value == "\n") {
                self.parsers[token.lineNumber] = parsed.copy();
            }

            if (token.lineNumber > lastLineToRender) {
                throw self.StopIteration;
            } else if ((token.lineNumber >= firstLineToRender) && (token.value != "\n")) {
                self.updateLineInfos(lineInfos, token);
            }
        });

        return lineInfos;
    }
});

// -- Add core syntax files here, can load others later
dojo.require("bespin.syntax.codemirror.javascript");
dojo.require("bespin.syntax.codemirror.css");
dojo.require("bespin.syntax.codemirror.xml");
dojo.require("bespin.syntax.codemirror.html");
dojo.require("bespin.syntax.codemirror.php_base");
dojo.require("bespin.syntax.codemirror.php");
dojo.require("bespin.syntax.codemirror.python");

*/<|endoftext|>


<commit_before>'use strict';

angular.module('baseApp')
  .controller('accountsController', ['$scope', '$http', function($scope, $http) {
  var vm = this;
  vm.init = init;
  vm.accounts = [];

  function init(){
    var account = Parse.Object.extend("account");
    var query = new Parse.Query(account);

    query.containedIn("iban", Parse.User.current().get('accounts'));
    // ["1001"]
    query.find({
      success: function(results) {
        // alert("Successfully retrieved " + results.length);
        console.log(results[0].get('balance'));
        vm.accounts = results;
        for (var account in vm.accounts) {
          vm.accounts[account].iban = vm.accounts[account].get('iban');
          vm.accounts[account].name = vm.accounts[account].get('name');
          vm.accounts[account].balance = vm.accounts[account].get('balance');
        }
        console.log(vm.accounts);
        $scope.$apply();

        // Do something with the returned Parse.Object values
        // for (var i = 0; i < results.length; i++) {
        //   var object = results[i];
        //   alert(object.id + ' - ' + object.get('playerName'));
        // }
      },
      error: function(error) {
        // alert("Error: " + error.code + " " + error.message);
      }
    });
  }

}]);
<commit_msg>controller as<commit_after>'use strict';

angular.module('baseApp')
  .controller('accountsController', ['$scope', '$http', function($scope, $http) {
  var vm = this;
  vm.init = init;
  vm.accounts = [];
  vm.initOK = initOK;
  function initOK(results) {

     // alert("Successfully retrieved " + results.length);
     console.log(results[0].get('balance'));
     vm.accounts = results;
     for (var account in vm.accounts) {
       vm.accounts[account].iban = vm.accounts[account].get('iban');
       vm.accounts[account].name = vm.accounts[account].get('name');
       vm.accounts[account].balance = vm.accounts[account].get('balance');
     }
     console.log(vm.accounts);
     $scope.$apply();

     // Do something with the returned Parse.Object values
     // for (var i = 0; i < results.length; i++) {
     //   var object = results[i];
     //   alert(object.id + ' - ' + object.get('playerName'));
     // }
  }
  function init(){
    var account = Parse.Object.extend("account");
    var query = new Parse.Query(account);

    query.containedIn("iban", Parse.User.current().get('accounts'));
    // ["1001"]
    query.find({
      success: vm.initOK,
      error: function(error) {
        // alert("Error: " + error.code + " " + error.message);
      }
    });

  }

}]);
<|endoftext|>


<commit_before>/*
Set the not-secure cookie

[base-url]COCALC-VERSION

to the version of the client code.  This is used by the hub-proxy server on the
backend, to decide whether or not to allow the client to connect to projects.
Basically, we do not want to allow ancient buggy clients to connect in any
way at all.
*/

const Cookies = require("js-cookie");
const { version } = require("smc-util/smc-version");
const { APP_BASE_URL } = require('./misc_page');

Cookies.set(`${APP_BASE_URL}cocalc_version`, version);
<commit_msg>do not expire the cocalc_version cookie - this may fix #3826<commit_after>/*
Set the not-secure cookie

[base-url]COCALC-VERSION

to the version of the client code.  This is used by the hub-proxy server on the
backend, to decide whether or not to allow the client to connect to projects.
Basically, we do not want to allow ancient buggy clients to connect in any
way at all.
*/

const Cookies = require("js-cookie");
const { version } = require("smc-util/smc-version");
const { APP_BASE_URL } = require("./misc_page");

// We don't want this cookie to expire.  All it does is record the version of
// the code the client has loaded, and the version only goes up.
Cookies.set(`${APP_BASE_URL}cocalc_version`, version, { expires: 10000 });
<|endoftext|>


<commit_before>var _ = require("lodash");

var languages = require("./languages");
var levels = require("./levels");
var cache = require("./cache");
var spelling = require("./spelling");

function rousseau(text, options) {
    var language;

    options = _.defaults(options || {}, {
        // Language to use
        language: "en",

        // Cache limit
        cache: 10000,

        // Only checks to apply
        only: [],

        // Checks to disable/configure
        checks: {
            spelling: false
        }
    });

    // Get associated language
    language = languages[options.language];
    if (!language) throw "Language '"+options.language+"' not found";

    // Init cache
    cache.rename(options.language);
    cache.setLimit(options.cache);

    // Disable associated checks
    var checks = _.chain(language)
        .extend({ spelling: spelling })
        .omit(function(check, name) {
            if (options.only.length > 0 && !_.contains(options.only, name)) return true;
            return options.checks[name] === false;
        })
        .value();

    // Apply checks
    var results = _.chain(checks)
        // Apply checks
        .map(function(check, checkType) {
            return _.map(check(text, options.checks[checkType] || {}) || [], function(tok) {
                tok.type = tok.type || checkType;
                return tok;
            });
        })
        .flatten()

        // Sort suggestions by position and level
        .sort(function(t1, t2) {
            if (t1.index < t2.index) {
                return -1;
            } else if (t1.index > t2.index) {
                return 1;
            } else {
                return (levels.order(t1.level) < levels.order(t2.level)) ?-1 : 1;
            }
        })

        // Return suggestions
        .value();

    return results;
}

module.exports = rousseau;
module.exports.languages = _.keys(languages);
module.exports.levels = levels;<commit_msg>Handle language like "en_US"<commit_after>var _ = require("lodash");

var languages = require("./languages");
var levels = require("./levels");
var cache = require("./cache");
var spelling = require("./spelling");

function rousseau(text, options) {
    var checks;

    options = _.defaults(options || {}, {
        // Language to use
        language: "en",

        // Cache limit
        cache: 10000,

        // Only checks to apply
        only: [],

        // Checks to disable/configure
        checks: {
            spelling: false
        }
    });

    // Build list of checks from language
    checks = _.chain([
            options.language,
            _.first(options.language.split("_"))
        ])
        .uniq()
        .reduce(function(_checks, lng) {
            return checks || languages[lng];
        }, null)
        .assign()
        .extend({ spelling: spelling })
        .omit(function(check, name) {
            if (options.only.length > 0 && !_.contains(options.only, name)) return true;
            return options.checks[name] === false;
        })
        .value();

    // Init cache
    cache.rename(options.language);
    cache.setLimit(options.cache);

    // Apply checks
    var results = _.chain(checks)
        // Apply checks
        .map(function(check, checkType) {
            return _.map(check(text, options.checks[checkType] || {}) || [], function(tok) {
                tok.type = tok.type || checkType;
                return tok;
            });
        })
        .flatten()

        // Sort suggestions by position and level
        .sort(function(t1, t2) {
            if (t1.index < t2.index) {
                return -1;
            } else if (t1.index > t2.index) {
                return 1;
            } else {
                return (levels.order(t1.level) < levels.order(t2.level)) ?-1 : 1;
            }
        })

        // Return suggestions
        .value();

    return results;
}

module.exports = rousseau;
module.exports.languages = _.keys(languages);
module.exports.levels = levels;<|endoftext|>


<commit_before>/**
 * Base layer constructor.
 * @constructor
 */

function BaseLayer(){

    this.layer_name = '';

    this.on = false;

    /*this.dom_obj = this.create_block();
    document.body.appendChild(this.dom_obj);*/
    this.dom_obj = {};

    this.color_buttons = [
        {"color" : "red"},
        {"color" : "green"},
        {"color" : "yellow"},
        {"color" : "blue"}
    ];
}

BaseLayer.prototype.show = function(){
    _debug('BaseLayer.show');

    this.dom_obj.show();
    this.on = true;

    stb.set_cur_place(this.layer_name);
    stb.set_cur_layer(this);
}

BaseLayer.prototype.hide = function(){
    _debug('BaseLayer.hide');

    this.dom_obj.hide();

    this.on = false;
}

BaseLayer.prototype.init = function(){
    _debug('BaseLayer.init');

    if (!this.class_name){
        this.class_name = 'layer_bg';
    }

    this.dom_obj.addClass(this.class_name);

    this.dom_obj.id = this.layer_name;
}

BaseLayer.prototype.create_block = function(class_name, is_active){

    var prefix = '';

    if (is_active){
        prefix = 'active_';
    }

    var block = document.createElement('div');

    if (class_name){
        block.addClass(prefix + class_name);
    }

    return block;
}

BaseLayer.prototype.init_color_buttons = function(map){
    this.buttons_bar = this.create_block('color_button_bar');

    var table = document.createElement('table');

    var row = document.createElement('tr');
    table.appendChild(row);

    for (var i=0; i<=3; i++){

        var cell = document.createElement('td');
        row.appendChild(cell);

        var separator = document.createElement('img');

        if (i == 0){
            separator.src = 'i/1x1.gif';
        }else{
            separator.src = 'i/footer_bg2.png';
        }

        cell.appendChild(separator);

        this.color_buttons[i].img_obj = create_block_element('btn_'+this.color_buttons[i].color, cell);

        this.color_buttons[i].text_obj = create_inline_element('', cell);

        this.color_buttons[i].text_obj.innerHTML = map[i].label;
    }

    if (typeof(map[0].cmd) == 'function'){
        map[0].cmd.bind(key.RED, this);
    }

    if (typeof(map[1].cmd) == 'function'){
        map[1].cmd.bind(key.GREEN, this);
    }

    if (typeof(map[2].cmd) == 'function'){
        map[2].cmd.bind(key.YELLOW, this);
    }

    if (typeof(map[3].cmd) == 'function'){
        map[3].cmd.bind(key.BLUE, this);
    }

    this.buttons_bar.appendChild(table);

    this.dom_obj.appendChild(this.buttons_bar);
}

BaseLayer.prototype.init_left_ear = function(txt){

    var ears_left_container = create_block_element('ears_left_container');

    this.left_ear = create_block_element('ears_left');

    var left_arrow = create_block_element('ears_arrow_left');
    var text_element = create_block_element();
    text_element.innerHTML = txt;

    this.left_ear.appendChild(left_arrow);
    this.left_ear.appendChild(text_element);
    this.left_ear.appendChild(left_arrow.cloneNode(true));

    ears_left_container.appendChild(this.left_ear);

    this.dom_obj.appendChild(ears_left_container);
}

BaseLayer.prototype.init_right_ear = function(txt){

    var ears_right_container = create_block_element('ears_right_container');

    this.right_ear = create_block_element('ears_right');

    var right_arrow = create_block_element('ears_arrow_right');
    var text_element = create_block_element();
    text_element.innerHTML = txt;

    this.right_ear.appendChild(right_arrow);
    this.right_ear.appendChild(text_element);
    this.right_ear.appendChild(right_arrow.cloneNode(true));

    ears_right_container.appendChild(this.right_ear);

    this.dom_obj.appendChild(ears_right_container);
}

BaseLayer.prototype.init_header_path = function(begin){

    this.header_path = this.create_block('mb_header_first text24_white');
    this.path_container = document.createElement('span');
    this.header_path.innerHTML = begin + ' / ';
    this.header_path.appendChild(this.path_container);
    this.dom_obj.appendChild(this.header_path);
}

BaseLayer.prototype.update_header_path = function(map){

    var path = '';

    for(var i=0; i<map.length; i++){

        var idx = this.header_path_map.getIdxByVal('alias', map[i].alias);

        if (this.header_path_map.hasOwnProperty(idx)){

            this.header_path_map.splice(idx, 1);
        }

        if (map[i].item != '*' && map[i].item != ''){
            this.header_path_map.push({"alias" : map[i].alias, "title" : map[i].item + ' /'});
        }
    }

    for (var i=0; i<this.header_path_map.length; i++){
        path += ''+this.header_path_map[i].title+'';
    }

    this.path_container.innerHTML = path;
}

loader.next();<commit_msg>"Modify init_color_buttons"<commit_after>/**
 * Base layer constructor.
 * @constructor
 */

function BaseLayer(){

    this.layer_name = '';

    this.on = false;

    /*this.dom_obj = this.create_block();
    document.body.appendChild(this.dom_obj);*/
    this.dom_obj = {};

    this.color_buttons = [
        {"color" : "red"},
        {"color" : "green"},
        {"color" : "yellow"},
        {"color" : "blue"}
    ];
}

BaseLayer.prototype.show = function(){
    _debug('BaseLayer.show');

    this.dom_obj.show();
    this.on = true;

    stb.set_cur_place(this.layer_name);
    stb.set_cur_layer(this);
}

BaseLayer.prototype.hide = function(){
    _debug('BaseLayer.hide');

    this.dom_obj.hide();

    this.on = false;
}

BaseLayer.prototype.init = function(){
    _debug('BaseLayer.init');

    if (!this.class_name){
        this.class_name = 'layer_bg';
    }

    this.dom_obj.addClass(this.class_name);

    this.dom_obj.id = this.layer_name;
}

BaseLayer.prototype.create_block = function(class_name, is_active){

    var prefix = '';

    if (is_active){
        prefix = 'active_';
    }

    var block = document.createElement('div');

    if (class_name){
        block.addClass(prefix + class_name);
    }

    return block;
}

BaseLayer.prototype.init_color_buttons = function(map){
    this.buttons_bar = this.create_block('color_button_bar');

    var table = document.createElement('table');

    var row = document.createElement('tr');
    table.appendChild(row);

    for (var i=0; i<=3; i++){

        var cell = document.createElement('td');
        row.appendChild(cell);

        var separator = document.createElement('img');

        if (i == 0){
            separator.src = 'i/1x1.gif';
        }else{
            separator.src = 'i/footer_bg2.png';
        }

        cell.appendChild(separator);

        this.color_buttons[i].img_obj = create_block_element('btn_'+this.color_buttons[i].color, cell);

        this.color_buttons[i].text_obj = create_inline_element('', cell);

        this.color_buttons[i].text_obj.innerHTML = map[i].label;

        if (typeof(map[i].cmd) !== 'function'){
            this.color_buttons[i].text_obj.setClass('disable_color_btn_text');
        }
    }

    if (typeof(map[0].cmd) == 'function'){
        map[0].cmd.bind(key.RED, this);
    }

    if (typeof(map[1].cmd) == 'function'){
        map[1].cmd.bind(key.GREEN, this);
    }

    if (typeof(map[2].cmd) == 'function'){
        map[2].cmd.bind(key.YELLOW, this);
    }

    if (typeof(map[3].cmd) == 'function'){
        map[3].cmd.bind(key.BLUE, this);
    }

    this.buttons_bar.appendChild(table);

    this.dom_obj.appendChild(this.buttons_bar);
}

BaseLayer.prototype.init_left_ear = function(txt){

    var ears_left_container = create_block_element('ears_left_container');

    this.left_ear = create_block_element('ears_left');

    var left_arrow = create_block_element('ears_arrow_left');
    var text_element = create_block_element();
    text_element.innerHTML = txt;

    this.left_ear.appendChild(left_arrow);
    this.left_ear.appendChild(text_element);
    this.left_ear.appendChild(left_arrow.cloneNode(true));

    ears_left_container.appendChild(this.left_ear);

    this.dom_obj.appendChild(ears_left_container);
}

BaseLayer.prototype.init_right_ear = function(txt){

    var ears_right_container = create_block_element('ears_right_container');

    this.right_ear = create_block_element('ears_right');

    var right_arrow = create_block_element('ears_arrow_right');
    var text_element = create_block_element();
    text_element.innerHTML = txt;

    this.right_ear.appendChild(right_arrow);
    this.right_ear.appendChild(text_element);
    this.right_ear.appendChild(right_arrow.cloneNode(true));

    ears_right_container.appendChild(this.right_ear);

    this.dom_obj.appendChild(ears_right_container);
}

BaseLayer.prototype.init_header_path = function(begin){

    this.header_path = this.create_block('mb_header_first text24_white');
    this.path_container = document.createElement('span');
    this.header_path.innerHTML = begin + ' / ';
    this.header_path.appendChild(this.path_container);
    this.dom_obj.appendChild(this.header_path);
}

BaseLayer.prototype.update_header_path = function(map){

    var path = '';

    for(var i=0; i<map.length; i++){

        var idx = this.header_path_map.getIdxByVal('alias', map[i].alias);

        if (this.header_path_map.hasOwnProperty(idx)){

            this.header_path_map.splice(idx, 1);
        }

        if (map[i].item != '*' && map[i].item != ''){
            this.header_path_map.push({"alias" : map[i].alias, "title" : map[i].item + ' /'});
        }
    }

    for (var i=0; i<this.header_path_map.length; i++){
        path += ''+this.header_path_map[i].title+'';
    }

    this.path_container.innerHTML = path;
}

loader.next();<|endoftext|>


<commit_before>/*
 * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of iotagent-ul
 *
 * iotagent-ul is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * iotagent-ul is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with iotagent-ul.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::[iot_support@tid.es]
 *
 * Modified by: Daniel Calvo - ATOS Research & Innovation
 */

/* eslint-disable no-prototype-builtins */

const iotAgentLib = require('iotagent-node-lib');
const regenerateTransid = iotAgentLib.regenerateTransid;
const intoTrans = iotAgentLib.intoTrans;
const finishSouthBoundTransaction = iotAgentLib.finishSouthBoundTransaction;
const fillService = iotAgentLib.fillService;
const _ = require('underscore');
const commandHandler = require('./commandHandler');
const transportSelector = require('./transportSelector');
const async = require('async');
const iotaUtils = require('./iotaUtils');
const constants = require('./constants');
const context = {
    op: 'IoTAgentJSON.commonBinding'
};
const config = require('./configService');

/**
 * Parse a message received from a Topic.
 *
 * @param {Buffer} message          Message to be parsed
 * @return {Object}                 Parsed message or null if an error has occurred.
 */
function parseMessage(message) {
    let parsedMessage;
    let stringMessage;
    let parsedMessageError = false;
    let messageArray;

    try {
        stringMessage = message.toString();
        parsedMessage = JSON.parse(stringMessage);
        messageArray = [];
        if (Array.isArray(parsedMessage)) {
            messageArray = parsedMessage;
        } else {
            messageArray.push(parsedMessage);
        }
    } catch (e) {
        config.getLogger().debug(context, 'Parse error treating message [%s]: %j', stringMessage, e);
        messageArray = null;
        parsedMessageError = true;
    }

    if (parsedMessageError) {
        config.getLogger().error(context, 'MEASURES-003: Impossible to handle malformed message: %s', message);
    }

    return messageArray;
}

/**
 * Find the attribute given by its name between all the active attributes of the given device, returning its type, or
 * null otherwise.
 *
 * @param {String} attribute        Name of the attribute to find.
 * @param {Object} device           Device object containing all the information about a device.
 * @return {String}                 String identifier of the attribute type.
 */
function guessType(attribute, device) {
    if (device.active) {
        for (let i = 0; i < device.active.length; i++) {
            if (device.active[i].name === attribute) {
                return device.active[i].type;
            }
        }
    }

    if (attribute === constants.TIMESTAMP_ATTRIBUTE) {
        return constants.TIMESTAMP_TYPE_NGSI2;
    }
    return constants.DEFAULT_ATTRIBUTE_TYPE;
}

function extractAttributes(device, current) {
    const values = [];

    function checkAttributes(k) {
        if (device && device.active) {
            for (let j = 0; j < device.active.length; j++) {
                const objectId = 'object_id';
                const name = 'name';
                if (k === 'TimeInstant' || device.active[j][objectId] === k || device.active[j][name] === k) {
                    return true;
                }
            }
        }
        return false;
    }

    for (const k in current) {
        if (current.hasOwnProperty(k)) {
            values.push({
                name: k,
                type: guessType(k, device),
                value: current[k]
            });
        }
    }
    return values;
}

function sendConfigurationToDevice(device, apiKey, deviceId, results, callback) {
    transportSelector.applyFunctionFromBinding(
        [apiKey, deviceId, results],
        'sendConfigurationToDevice',
        device.transport,
        callback
    );
}

/**
 * Deals with configuration requests coming from the device. Whenever a new configuration requests arrives with a list
 * of attributes to retrieve, this handler asks the Context Broker for the values of those attributes, and publish a
 * new message in the "/1234/MQTT_2/configuration/values" topic
 *
 * @param {String} apiKey           API Key corresponding to the Devices configuration.
 * @param {String} deviceId         Id of the device to be updated.
 * @param {Object} device           Device object containing all the information about a device.
 * @param {Object} objMessage          Array of JSON object received.
 */
function manageConfigurationRequest(apiKey, deviceId, device, objMessage) {
    for (let i = 0; i < objMessage.length; i++) {
        iotaUtils.manageConfiguration(
            apiKey,
            deviceId,
            device,
            objMessage[i],
            async.apply(sendConfigurationToDevice, device),
            function (error) {
                if (error) {
                    iotAgentLib.alarms.raise(constants.MQTTB_ALARM, error);
                } else {
                    iotAgentLib.alarms.release(constants.MQTTB_ALARM);
                    config
                        .getLogger()
                        .debug(
                            context,
                            'Configuration request finished for APIKey [%s] and Device [%s]',
                            apiKey,
                            deviceId
                        );
                }
                finishSouthBoundTransaction(null);
            }
        );
    }
}

/**
 * Adds a single measure to the context broker. The message for single measures contains the direct value to
 * be inserted in the attribute, given by its name.
 *
 * @param {String} apiKey           API Key corresponding to the Devices configuration.
 * @param {String} deviceId         Id of the device to be updated.
 * @param {String} attribute        Name of the attribute to update.
 * @param {Object} device           Device object containing all the information about a device.
 * @param {Buffer} message          Raw message coming from the client.
 */
function singleMeasure(apiKey, deviceId, attribute, device, message) {
    config.getLogger().debug(context, 'Processing single measure for device [%s] with apiKey [%s]', deviceId, apiKey);

    const values = [
        {
            name: attribute,
            type: guessType(attribute, device),
            value: message.toString()
        }
    ];

    iotAgentLib.update(device.name, device.type, '', values, device, function (error) {
        if (error) {
            config.getLogger().error(
                context,
                /*jshint quotmark: double */
                "MEASURES-002: Couldn't send the updated values to the Context Broker due to an error: %j",
                /*jshint quotmark: single */
                error
            );
        } else {
            config
                .getLogger()
                .debug(
                    context,
                    'Single measure for device [%s] with apiKey [%s] successfully updated',
                    deviceId,
                    apiKey
                );
        }
        finishSouthBoundTransaction(null);
    });
}

/**
 * Adds multiple measures to the Context Broker. Multiple measures come in the form of single-level JSON objects,
 * whose keys are the attribute names and whose values are the attribute values.
 *
 * @param {String} apiKey           API Key corresponding to the Devices configuration.
 * @param {String} deviceId         Id of the device to be updated.
 * @param {Object} device           Device object containing all the information about a device.
 * @param {Object} messageObj       Array of JSON object sent using.
 */
function multipleMeasures(apiKey, deviceId, device, messageObj) {
    let measure;
    config
        .getLogger()
        .debug(context, 'Processing multiple measures for device [%s] with apiKey [%s]', deviceId, apiKey);

    for (let j = 0; j < messageObj.length; j++) {
        measure = messageObj[j];
        const values = [];
        for (const i in measure) {
            if (measure.hasOwnProperty(i)) {
                values.push({
                    name: i,
                    type: guessType(i, device),
                    value: measure[i]
                });
            }
        }

        iotAgentLib.update(device.name, device.type, '', values, device, function (error) {
            if (error) {
                config.getLogger().error(
                    context,
                    /*jshint quotmark: double */
                    "MEASURES-002: Couldn't send the updated values to the Context Broker due to an error: %j",
                    /*jshint quotmark: single */
                    error
                );
            } else {
                config
                    .getLogger()
                    .info(
                        context,
                        'Multiple measures for device [%s] with apiKey [%s] successfully updated',
                        deviceId,
                        apiKey
                    );
            }
            finishSouthBoundTransaction(null);
        });
    }
}

/**
 * Handles an incoming message, extracting the API Key, device Id and attribute to update (in the case of single
 * measures) from the topic.
 *
 * @param {String} topic        Topic of the form: '/<APIKey>/deviceId/attrs[/<attributeName>]'.
 * @param {Object} message      message body (Object or Buffer, depending on the value).
 */
function messageHandler(topic, message, protocol) {
    if (topic[0] !== '/') {
        topic = '/' + topic;
    }
    const topicInformation = topic.split('/');
    if (topicInformation[1].toLowerCase() === 'json') {
        topicInformation.splice(1, 1);
    }
    const apiKey = topicInformation[1];
    const deviceId = topicInformation[2];
    const parsedMessage = parseMessage(message);

    function processMessageForDevice(device, apiKey, topicInformation) {
        if (topicInformation[3] === 'configuration' && topicInformation[4] === 'commands' && parsedMessage) {
            manageConfigurationRequest(apiKey, deviceId, device, parsedMessage);
        } else if (topicInformation[4]) {
            singleMeasure(apiKey, deviceId, topicInformation[4], device, message);
        } else if (topicInformation[3] === constants.CONFIGURATION_COMMAND_UPDATE) {
            for (let i = 0; i < parsedMessage.length; i++) {
                commandHandler.updateCommand(apiKey, deviceId, device, parsedMessage[i]);
            }
        } else if (parsedMessage && typeof parsedMessage === 'object') {
            multipleMeasures(apiKey, deviceId, device, parsedMessage);
        } else {
            config.getLogger().error(
                context,
                /*jshint quotmark: double */
                "Couldn't process message [%s] due to format issues.",
                /*jshint quotmark: single */
                message
            );
        }
    }

    function processDeviceMeasure(error, device) {
        if (error) {
            let ctx = context;
            ctx = fillService(ctx, { service: 'n/a', subservice: 'n/a' });
            config.getLogger().warn(ctx, 'MEASURES-004: Device not found for topic [%s]', topic);
        } else {
            const localContext = _.clone(context);

            localContext.service = device.service;
            localContext.subservice = device.subservice;

            intoTrans(localContext, processMessageForDevice)(device, apiKey, topicInformation);
        }
    }

    iotAgentLib.alarms.release(constants.MQTTB_ALARM);
    iotaUtils.retrieveDevice(deviceId, apiKey, protocol, processDeviceMeasure);
}

/**
 * Handles an incoming AMQP message, extracting the API Key, device Id and attribute to update (in the case of single
 * measures) from the AMQP topic.
 *
 * @param {String} topic        Topic of the form: '/<APIKey>/deviceId/attributes[/<attributeName>]'.
 * @param {Object} message      AMQP message body (Object or Buffer, depending on the value).
 */
function amqpMessageHandler(topic, message) {
    regenerateTransid(topic);
    messageHandler(topic, message, 'AMQP');
}

/**
 * Handles an incoming MQTT message, extracting the API Key, device Id and attribute to update (in the case of single
 * measures) from the MQTT topic.
 *
 * @param {String} topic        Topic of the form: '/<APIKey>/deviceId/attributes[/<attributeName>]'.
 * @param {Object} message      MQTT message body (Object or Buffer, depending on the value).
 */
function mqttMessageHandler(topic, message) {
    regenerateTransid(topic);
    config.getLogger().debug(context, 'message topic: %s', topic);
    messageHandler(topic, message, 'MQTT');
}

exports.amqpMessageHandler = amqpMessageHandler;
exports.mqttMessageHandler = mqttMessageHandler;
exports.messageHandler = messageHandler;
exports.extractAttributes = extractAttributes;
exports.guessType = guessType;
<commit_msg>Remove dead function.<commit_after>/*
 * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of iotagent-ul
 *
 * iotagent-ul is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * iotagent-ul is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with iotagent-ul.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::[iot_support@tid.es]
 *
 * Modified by: Daniel Calvo - ATOS Research & Innovation
 */

/* eslint-disable no-prototype-builtins */

const iotAgentLib = require('iotagent-node-lib');
const regenerateTransid = iotAgentLib.regenerateTransid;
const intoTrans = iotAgentLib.intoTrans;
const finishSouthBoundTransaction = iotAgentLib.finishSouthBoundTransaction;
const fillService = iotAgentLib.fillService;
const _ = require('underscore');
const commandHandler = require('./commandHandler');
const transportSelector = require('./transportSelector');
const async = require('async');
const iotaUtils = require('./iotaUtils');
const constants = require('./constants');
const context = {
    op: 'IoTAgentJSON.commonBinding'
};
const config = require('./configService');

/**
 * Parse a message received from a Topic.
 *
 * @param {Buffer} message          Message to be parsed
 * @return {Object}                 Parsed message or null if an error has occurred.
 */
function parseMessage(message) {
    let parsedMessage;
    let stringMessage;
    let parsedMessageError = false;
    let messageArray;

    try {
        stringMessage = message.toString();
        parsedMessage = JSON.parse(stringMessage);
        messageArray = [];
        if (Array.isArray(parsedMessage)) {
            messageArray = parsedMessage;
        } else {
            messageArray.push(parsedMessage);
        }
    } catch (e) {
        config.getLogger().debug(context, 'Parse error treating message [%s]: %j', stringMessage, e);
        messageArray = null;
        parsedMessageError = true;
    }

    if (parsedMessageError) {
        config.getLogger().error(context, 'MEASURES-003: Impossible to handle malformed message: %s', message);
    }

    return messageArray;
}

/**
 * Find the attribute given by its name between all the active attributes of the given device, returning its type, or
 * null otherwise.
 *
 * @param {String} attribute        Name of the attribute to find.
 * @param {Object} device           Device object containing all the information about a device.
 * @return {String}                 String identifier of the attribute type.
 */
function guessType(attribute, device) {
    if (device.active) {
        for (let i = 0; i < device.active.length; i++) {
            if (device.active[i].name === attribute) {
                return device.active[i].type;
            }
        }
    }

    if (attribute === constants.TIMESTAMP_ATTRIBUTE) {
        return constants.TIMESTAMP_TYPE_NGSI2;
    }
    return constants.DEFAULT_ATTRIBUTE_TYPE;
}

function extractAttributes(device, current) {
    const values = [];
    for (const k in current) {
        if (current.hasOwnProperty(k)) {
            values.push({
                name: k,
                type: guessType(k, device),
                value: current[k]
            });
        }
    }
    return values;
}

function sendConfigurationToDevice(device, apiKey, deviceId, results, callback) {
    transportSelector.applyFunctionFromBinding(
        [apiKey, deviceId, results],
        'sendConfigurationToDevice',
        device.transport,
        callback
    );
}

/**
 * Deals with configuration requests coming from the device. Whenever a new configuration requests arrives with a list
 * of attributes to retrieve, this handler asks the Context Broker for the values of those attributes, and publish a
 * new message in the "/1234/MQTT_2/configuration/values" topic
 *
 * @param {String} apiKey           API Key corresponding to the Devices configuration.
 * @param {String} deviceId         Id of the device to be updated.
 * @param {Object} device           Device object containing all the information about a device.
 * @param {Object} objMessage          Array of JSON object received.
 */
function manageConfigurationRequest(apiKey, deviceId, device, objMessage) {
    for (let i = 0; i < objMessage.length; i++) {
        iotaUtils.manageConfiguration(
            apiKey,
            deviceId,
            device,
            objMessage[i],
            async.apply(sendConfigurationToDevice, device),
            function (error) {
                if (error) {
                    iotAgentLib.alarms.raise(constants.MQTTB_ALARM, error);
                } else {
                    iotAgentLib.alarms.release(constants.MQTTB_ALARM);
                    config
                        .getLogger()
                        .debug(
                            context,
                            'Configuration request finished for APIKey [%s] and Device [%s]',
                            apiKey,
                            deviceId
                        );
                }
                finishSouthBoundTransaction(null);
            }
        );
    }
}

/**
 * Adds a single measure to the context broker. The message for single measures contains the direct value to
 * be inserted in the attribute, given by its name.
 *
 * @param {String} apiKey           API Key corresponding to the Devices configuration.
 * @param {String} deviceId         Id of the device to be updated.
 * @param {String} attribute        Name of the attribute to update.
 * @param {Object} device           Device object containing all the information about a device.
 * @param {Buffer} message          Raw message coming from the client.
 */
function singleMeasure(apiKey, deviceId, attribute, device, message) {
    config.getLogger().debug(context, 'Processing single measure for device [%s] with apiKey [%s]', deviceId, apiKey);

    const values = [
        {
            name: attribute,
            type: guessType(attribute, device),
            value: message.toString()
        }
    ];

    iotAgentLib.update(device.name, device.type, '', values, device, function (error) {
        if (error) {
            config.getLogger().error(
                context,
                /*jshint quotmark: double */
                "MEASURES-002: Couldn't send the updated values to the Context Broker due to an error: %j",
                /*jshint quotmark: single */
                error
            );
        } else {
            config
                .getLogger()
                .debug(
                    context,
                    'Single measure for device [%s] with apiKey [%s] successfully updated',
                    deviceId,
                    apiKey
                );
        }
        finishSouthBoundTransaction(null);
    });
}

/**
 * Adds multiple measures to the Context Broker. Multiple measures come in the form of single-level JSON objects,
 * whose keys are the attribute names and whose values are the attribute values.
 *
 * @param {String} apiKey           API Key corresponding to the Devices configuration.
 * @param {String} deviceId         Id of the device to be updated.
 * @param {Object} device           Device object containing all the information about a device.
 * @param {Object} messageObj       Array of JSON object sent using.
 */
function multipleMeasures(apiKey, deviceId, device, messageObj) {
    let measure;
    config
        .getLogger()
        .debug(context, 'Processing multiple measures for device [%s] with apiKey [%s]', deviceId, apiKey);

    for (let j = 0; j < messageObj.length; j++) {
        measure = messageObj[j];
        const values = [];
        for (const i in measure) {
            if (measure.hasOwnProperty(i)) {
                values.push({
                    name: i,
                    type: guessType(i, device),
                    value: measure[i]
                });
            }
        }

        iotAgentLib.update(device.name, device.type, '', values, device, function (error) {
            if (error) {
                config.getLogger().error(
                    context,
                    /*jshint quotmark: double */
                    "MEASURES-002: Couldn't send the updated values to the Context Broker due to an error: %j",
                    /*jshint quotmark: single */
                    error
                );
            } else {
                config
                    .getLogger()
                    .info(
                        context,
                        'Multiple measures for device [%s] with apiKey [%s] successfully updated',
                        deviceId,
                        apiKey
                    );
            }
            finishSouthBoundTransaction(null);
        });
    }
}

/**
 * Handles an incoming message, extracting the API Key, device Id and attribute to update (in the case of single
 * measures) from the topic.
 *
 * @param {String} topic        Topic of the form: '/<APIKey>/deviceId/attrs[/<attributeName>]'.
 * @param {Object} message      message body (Object or Buffer, depending on the value).
 */
function messageHandler(topic, message, protocol) {
    if (topic[0] !== '/') {
        topic = '/' + topic;
    }
    const topicInformation = topic.split('/');
    if (topicInformation[1].toLowerCase() === 'json') {
        topicInformation.splice(1, 1);
    }
    const apiKey = topicInformation[1];
    const deviceId = topicInformation[2];
    const parsedMessage = parseMessage(message);

    function processMessageForDevice(device, apiKey, topicInformation) {
        if (topicInformation[3] === 'configuration' && topicInformation[4] === 'commands' && parsedMessage) {
            manageConfigurationRequest(apiKey, deviceId, device, parsedMessage);
        } else if (topicInformation[4]) {
            singleMeasure(apiKey, deviceId, topicInformation[4], device, message);
        } else if (topicInformation[3] === constants.CONFIGURATION_COMMAND_UPDATE) {
            for (let i = 0; i < parsedMessage.length; i++) {
                commandHandler.updateCommand(apiKey, deviceId, device, parsedMessage[i]);
            }
        } else if (parsedMessage && typeof parsedMessage === 'object') {
            multipleMeasures(apiKey, deviceId, device, parsedMessage);
        } else {
            config.getLogger().error(
                context,
                /*jshint quotmark: double */
                "Couldn't process message [%s] due to format issues.",
                /*jshint quotmark: single */
                message
            );
        }
    }

    function processDeviceMeasure(error, device) {
        if (error) {
            let ctx = context;
            ctx = fillService(ctx, { service: 'n/a', subservice: 'n/a' });
            config.getLogger().warn(ctx, 'MEASURES-004: Device not found for topic [%s]', topic);
        } else {
            const localContext = _.clone(context);

            localContext.service = device.service;
            localContext.subservice = device.subservice;

            intoTrans(localContext, processMessageForDevice)(device, apiKey, topicInformation);
        }
    }

    iotAgentLib.alarms.release(constants.MQTTB_ALARM);
    iotaUtils.retrieveDevice(deviceId, apiKey, protocol, processDeviceMeasure);
}

/**
 * Handles an incoming AMQP message, extracting the API Key, device Id and attribute to update (in the case of single
 * measures) from the AMQP topic.
 *
 * @param {String} topic        Topic of the form: '/<APIKey>/deviceId/attributes[/<attributeName>]'.
 * @param {Object} message      AMQP message body (Object or Buffer, depending on the value).
 */
function amqpMessageHandler(topic, message) {
    regenerateTransid(topic);
    messageHandler(topic, message, 'AMQP');
}

/**
 * Handles an incoming MQTT message, extracting the API Key, device Id and attribute to update (in the case of single
 * measures) from the MQTT topic.
 *
 * @param {String} topic        Topic of the form: '/<APIKey>/deviceId/attributes[/<attributeName>]'.
 * @param {Object} message      MQTT message body (Object or Buffer, depending on the value).
 */
function mqttMessageHandler(topic, message) {
    regenerateTransid(topic);
    config.getLogger().debug(context, 'message topic: %s', topic);
    messageHandler(topic, message, 'MQTT');
}

exports.amqpMessageHandler = amqpMessageHandler;
exports.mqttMessageHandler = mqttMessageHandler;
exports.messageHandler = messageHandler;
exports.extractAttributes = extractAttributes;
exports.guessType = guessType;
<|endoftext|>