Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial import

  • Loading branch information...
commit fb5232f05f04ee8e96ab076981aff1ea1a29d36c 1 parent 6ea7bcf
@julienledem authored
View
116 ui/css/file-picker-tree.css
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of Yahoo! Inc. nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of Yahoo! Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#filePickerTree {
+ border: 1px solid #4C4C4C;
+ height: 548px;
+ overflow: scroll;
+ width: 460px;
+}
+#filePickerTree .ygtvspacer {
+ height: 22px;
+ width: 35px;
+}
+#filePickerTree .file-picker-file-node a.ygtvspacer {
+ height: 22px;
+ width: 16px;
+}
+#filePickerTree span{
+ color: #4C4C4C;
+ font-size: 11px;
+ font-family: arial,helvetica,clean,sans-serif;
+}
+
+/* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
+
+/* first or middle sibling, no children */
+#filePickerTree .ygtvtn { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/tn.gif) 0 0 no-repeat; width:17px; height:22px; }
+
+/* first or middle sibling, collapsable */
+#filePickerTree .ygtvtm { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/tm.gif) 0 0 no-repeat; width:34px; height:22px; cursor:pointer }
+
+/* first or middle sibling, collapsable, hover */
+#filePickerTree .ygtvtmh { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/tmh.gif) 0 0 no-repeat; width:34px; height:22px; cursor:pointer }
+
+/* first or middle sibling, expandable */
+#filePickerTree .ygtvtp { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/tp.gif) 0 0 no-repeat; width:34px; height:22px; cursor:pointer }
+
+/* first or middle sibling, expandable, hover */
+#filePickerTree .ygtvtph { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/tph.gif) 0 0 no-repeat; width:34px; height:22px; cursor:pointer }
+
+/* last sibling, no children */
+#filePickerTree .ygtvln { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/ln.gif) 0 0 no-repeat; width:17px; height:22px; }
+
+/* Last sibling, collapsable */
+#filePickerTree .ygtvlm { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/lm.gif) 0 0 no-repeat; width:34px; height:22px; cursor:pointer }
+
+/* Last sibling, collapsable, hover */
+#filePickerTree .ygtvlmh { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/lmh.gif) 0 0 no-repeat; width:34px; height:22px; cursor:pointer }
+
+/* Last sibling, expandable */
+#filePickerTree .ygtvlp { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/lp.gif) 0 0 no-repeat; width:34px; height:22px; cursor:pointer }
+
+/* Last sibling, expandable, hover */
+#filePickerTree .ygtvlph { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/lph.gif) 0 0 no-repeat; width:34px; height:22px; cursor:pointer }
+
+/* Loading icon */
+#filePickerTree .ygtvloading { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/loading.gif) 0 0 no-repeat; width:16px; height:22px; }
+
+/* the style for the empty cells that are used for rendering the depth
+ * of the node */
+#filePickerTree .ygtvdepthcell { background: url(http://developer.yahoo.com/yui/examples/treeview/assets/img/folders/vline.gif) 0 0 no-repeat; width:17px; height:22px; }
+
+#filePickerTree .ygtvblankdepthcell { width:17px; height:22px; }
+
+/* the style of the div around each node */
+#filePickerTree .ygtvitem { }
+
+#filePickerTree .ygtvitem table{
+ margin-bottom:0;
+}
+#filePickerTree .ygtvitem td {
+ border: none;
+ padding: 0;
+ white-space: nowrap;
+}
+/* the style of the div around each node's collection of children */
+#filePickerTree .ygtvchildren { }
+* html .ygtvchildren { height:1%; }
+
+/* the style of the text label in ygTextNode */
+#filePickerTree .ygtvlabel, .ygtvlabel:link, .ygtvlabel:visited, .ygtvlabel:hover {
+ margin-left:2px;
+ text-decoration: none;
+}
View
39 ui/css/map-reduce-console-widget.css
@@ -0,0 +1,39 @@
+/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of Yahoo! Inc. nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of Yahoo! Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+
+#curationMapReduceConsole div#functions{
+ padding: 60px 0;
+}
View
128 ui/html/map-reduce.html
@@ -0,0 +1,128 @@
+<!--
+
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of Yahoo! Inc. nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of Yahoo! Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<html>
+ <head>
+ <title>Javascript console</title>
+
+ <link type="text/css" rel="stylesheet" href="assets/map-reduce-console-widget.css">
+ <link type="text/css" rel="stylesheet" href="assets/file-picker-tree.css">
+ <link type="text/css" rel="stylesheet" href="http://developer.yahoo.com/yui/examples/treeview/assets/css/folders/tree.css">
+ </head>
+ <body>
+ <div id="curationMapReduceConsole">
+ <form name=f>
+ <table>
+ <tr id="inputOutputContainer" valign="top">
+ <td>
+ <table>
+ <tr>
+ <td height=50>
+ Pick a file:
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="filePickerTree"></div>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tr>
+ <td height=50>
+ Input: <img id="inputImage" src="img/check.png" width=20 height=20>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <textarea id="in" rows="38" cols="40"></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p id="dataError"></p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="examples">
+ <input id="wordCountButton" type="button" value="wordcount example">
+ <input id="entityRelButton" type="button" value="entity relationships example">
+ </div>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td id="newColumn">
+ <div id="functions">
+ <input id="mapButton" type="button" value="map"><br>
+ <input id="flattenButton" type="button" value="flatten"><br>
+ <input id="groupByButton" type="button" value="group by"><br><br>
+ <input id="removeLastButton" type="button" value="remove last"><br><br>
+ <input id="submitToGridButton" type="button" value="Submit to the grid">
+ </div>
+ </td>
+ <td>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </td>
+ <td valign="middle">
+ <div id="loading"></div>
+ </td>
+ <td id="farRight">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+
+ <!--<script src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>-->
+ <script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/yui/yui.js"></script>
+
+ <script type="text/javascript" charset="utf-8">
+ if("undefined"==typeof Y)
+ Y = YUI({debug:true, useConsole:true, combine:false, filter:'raw'});
+ </script>
+
+ <script src="assets/map-reduce-widget.js"></script>
+ <script src="assets/map-reduce-ui.js"></script>
+
+ </body>
+</html>
+
View
BIN  ui/img/check.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  ui/img/err.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  ui/img/loading.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
531 ui/js/json.js
@@ -0,0 +1,531 @@
+/*
+ json.js
+ 2011-02-23
+
+ Public Domain
+
+ No warranty expressed or implied. Use at your own risk.
+
+ This file has been superceded by http://www.JSON.org/json2.js
+
+ See http://www.JSON.org/js.html
+
+ This code should be minified before deployment.
+ See http://javascript.crockford.com/jsmin.html
+
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+ NOT CONTROL.
+
+ This file adds these methods to JavaScript:
+
+ object.toJSONString(whitelist)
+ This method produce a JSON text from a JavaScript value.
+ It must not contain any cyclical references. Illegal values
+ will be excluded.
+
+ The default conversion for dates is to an ISO string. You can
+ add a toJSONString method to any date object to get a different
+ representation.
+
+ The object and array methods can take an optional whitelist
+ argument. A whitelist is an array of strings. If it is provided,
+ keys in objects not found in the whitelist are excluded.
+
+ string.parseJSON(filter)
+ This method parses a JSON text to produce an object or
+ array. It can throw a SyntaxError exception.
+
+ The optional filter parameter is a function which can filter and
+ transform the results. It receives each of the keys and values, and
+ its return value is used instead of the original value. If it
+ returns what it received, then structure is not modified. If it
+ returns undefined then the member is deleted.
+
+ Example:
+
+ // Parse the text. If a key contains the string 'date' then
+ // convert the value to a date.
+
+ myData = text.parseJSON(function (key, value) {
+ return key.indexOf('date') >= 0 ? new Date(value) : value;
+ });
+
+ This file will break programs with improper for..in loops. See
+ http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
+
+ This file creates a global JSON object containing two methods: stringify
+ and parse.
+
+ JSON.stringify(value, replacer, space)
+ value any JavaScript value, usually an object or array.
+
+ replacer an optional parameter that determines how object
+ values are stringified for objects. It can be a
+ function or an array of strings.
+
+ space an optional parameter that specifies the indentation
+ of nested structures. If it is omitted, the text will
+ be packed without extra whitespace. If it is a number,
+ it will specify the number of spaces to indent at each
+ level. If it is a string (such as '\t' or '&nbsp;'),
+ it contains the characters used to indent at each level.
+
+ This method produces a JSON text from a JavaScript value.
+
+ When an object value is found, if the object contains a toJSON
+ method, its toJSON method will be called and the result will be
+ stringified. A toJSON method does not serialize: it returns the
+ value represented by the name/value pair that should be serialized,
+ or undefined if nothing should be serialized. The toJSON method
+ will be passed the key associated with the value, and this will be
+ bound to the object holding the key.
+
+ For example, this would serialize Dates as ISO strings.
+
+ Date.prototype.toJSON = function (key) {
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ return this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z';
+ };
+
+ You can provide an optional replacer method. It will be passed the
+ key and value of each member, with this bound to the containing
+ object. The value that is returned from your method will be
+ serialized. If your method returns undefined, then the member will
+ be excluded from the serialization.
+
+ If the replacer parameter is an array of strings, then it will be
+ used to select the members to be serialized. It filters the results
+ such that only members with keys listed in the replacer array are
+ stringified.
+
+ Values that do not have JSON representations, such as undefined or
+ functions, will not be serialized. Such values in objects will be
+ dropped; in arrays they will be replaced with null. You can use
+ a replacer function to replace those with JSON values.
+ JSON.stringify(undefined) returns undefined.
+
+ The optional space parameter produces a stringification of the
+ value that is filled with line breaks and indentation to make it
+ easier to read.
+
+ If the space parameter is a non-empty string, then that string will
+ be used for indentation. If the space parameter is a number, then
+ the indentation will be that many spaces.
+
+ Example:
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}]);
+ // text is '["e",{"pluribus":"unum"}]'
+
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+ text = JSON.stringify([new Date()], function (key, value) {
+ return this[key] instanceof Date ?
+ 'Date(' + this[key] + ')' : value;
+ });
+ // text is '["Date(---current time---)"]'
+
+
+ JSON.parse(text, reviver)
+ This method parses a JSON text to produce an object or array.
+ It can throw a SyntaxError exception.
+
+ The optional reviver parameter is a function that can filter and
+ transform the results. It receives each of the keys and values,
+ and its return value is used instead of the original value.
+ If it returns what it received, then the structure is not modified.
+ If it returns undefined then the member is deleted.
+
+ Example:
+
+ // Parse the text. Values that look like ISO date strings will
+ // be converted to Date objects.
+
+ myData = JSON.parse(text, function (key, value) {
+ var a;
+ if (typeof value === 'string') {
+ a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+ if (a) {
+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+ +a[5], +a[6]));
+ }
+ }
+ return value;
+ });
+
+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+ var d;
+ if (typeof value === 'string' &&
+ value.slice(0, 5) === 'Date(' &&
+ value.slice(-1) === ')') {
+ d = new Date(value.slice(5, -1));
+ if (d) {
+ return d;
+ }
+ }
+ return value;
+ });
+
+
+ This is a reference implementation. You are free to copy, modify, or
+ redistribute.
+*/
+
+/*jslint evil: true, regexp: false */
+
+/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
+ call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+ lastIndex, length, parse, parseJSON, prototype, push, replace, slice,
+ stringify, test, toJSON, toJSONString, toString, valueOf
+*/
+
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+var JSON;
+if (!JSON) {
+ JSON = {};
+}
+
+(function () {
+ "use strict";
+
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10 ? '0' + n : n;
+ }
+
+ if (typeof Date.prototype.toJSON !== 'function') {
+
+ Date.prototype.toJSON = function (key) {
+
+ return isFinite(this.valueOf()) ?
+ this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z' : null;
+ };
+
+ String.prototype.toJSON =
+ Number.prototype.toJSON =
+ Boolean.prototype.toJSON = function (key) {
+ return this.valueOf();
+ };
+ }
+
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ gap,
+ indent,
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ },
+ rep;
+
+
+ function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+ escapable.lastIndex = 0;
+ return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string' ? c :
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"' : '"' + string + '"';
+ }
+
+
+ function str(key, holder) {
+
+// Produce a string from holder[key].
+
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+ if (value && typeof value === 'object' &&
+ typeof value.toJSON === 'function') {
+ value = value.toJSON(key);
+ }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
+ }
+
+// What happens next depends on the value's type.
+
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+ return isFinite(value) ? String(value) : 'null';
+
+ case 'boolean':
+ case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+ return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+ case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+ if (!value) {
+ return 'null';
+ }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+ gap += indent;
+ partial = [];
+
+// Is the value an array?
+
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+ v = partial.length === 0 ? '[]' : gap ?
+ '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
+ '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ k = rep[i];
+ if (typeof k === 'string') {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+ for (k in value) {
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
+ }
+ }
+ }
+ }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+ v = partial.length === 0 ? '{}' : gap ?
+ '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
+ '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+ }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+ if (typeof JSON.stringify !== 'function') {
+ JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+ var i;
+ gap = '';
+ indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+ } else if (typeof space === 'string') {
+ indent = space;
+ }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function' &&
+ (typeof replacer !== 'object' ||
+ typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+ return str('', {'': value});
+ };
+ }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+ if (typeof JSON.parse !== 'function') {
+ JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+ var j;
+
+ function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+ text = String(text);
+ cx.lastIndex = 0;
+ if (cx.test(text)) {
+ text = text.replace(cx, function (a) {
+ return '\\u' +
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+ if (/^[\],:{}\s]*$/
+ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
+ .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+ j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+ return typeof reviver === 'function' ?
+ walk({'': j}, '') : j;
+ }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+ throw new SyntaxError('JSON.parse');
+ };
+ }
+
+// Augment the basic prototypes if they have not already been augmented.
+// These forms are obsolete. It is recommended that JSON.stringify and
+// JSON.parse be used instead.
+
+ if (!Object.prototype.toJSONString) {
+ Object.prototype.toJSONString = function (filter) {
+ return JSON.stringify(this, filter);
+ };
+ Object.prototype.parseJSON = function (filter) {
+ return JSON.parse(this, filter);
+ };
+ }
+}());
+
View
269 ui/js/map-reduce-ui.js
@@ -0,0 +1,269 @@
+/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of Yahoo! Inc. nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of Yahoo! Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+
+Y.use('curation-map-reduce-console', 'yui2-connection', 'yui2-datasource', 'yui2-treeview', 'yui2-logger', function(Y){
+
+ var YAHOO = Y.YUI2;
+
+ var channelsDS = new YAHOO.util.DataSource("assets/hdfs-channels.php",{
+ responseType : YAHOO.util.DataSource.TYPE_XML,
+ useXPath: true,
+ doBeforeCallback : function (req,raw,res,cb) {
+ // This is the filter function
+ /*var data = res.results || [],
+ filtered = [],
+ i,l, searchText, ofInterestOnly, interested, name, desc, owner;
+
+ if (req) {
+ searchText = req.text.toLowerCase();
+ ofInterestOnly = req.ofInterest;
+
+ for (i = 0, l = data.length; i < l; ++i) {
+ interested = data[i].of_interest === "true" || data[i].of_interest === true ? true : false;
+ if(ofInterestOnly && !interested)
+ continue;
+
+ name = data[i].name.toLowerCase();
+ desc = data[i].description.toLowerCase();
+ owner = data[i].owner.toLowerCase();
+ if(searchText === '')
+ filtered.push(data[i]);
+ else{
+ if(name.search(searchText) != -1 || desc.search(searchText) != -1 || owner.search(searchText) != -1)
+ filtered.push(data[i]);
+ }
+ }
+ res.results = filtered;
+ }*/
+ var listItems = raw.childNodes[0].childNodes,
+ files = [], i, j, attrs;//[0].attributes
+
+ for(i in listItems){
+ if(listItems[i].localName != 'file')
+ continue;
+ else{
+ attrs = listItems[i].attributes;
+ for(j in attrs){
+ if(attrs[j].localName == 'path')
+ files.push(attrs[j].nodeValue);
+ }
+ }
+ }
+
+ res.files = files;
+ return res;
+ }
+ });
+
+ channelsDS.responseSchema = {
+ metaFields: {
+ root:"/listing/@path"
+ },
+ resultNode: "directory",
+ fields: [{key:"path", locator:"@path"}]
+ };
+
+ var tree;
+
+ var createFolderSubtree = function(currentPath, root, files){
+ var res,
+ currFolder, subPath,
+ child, file, filePath, fileName;
+
+ if(currentPath.search('/') < 0){
+ res = {
+ type: 'text',
+ label: currentPath
+ };
+ currFolder = currentPath;
+ }else{
+ currFolder = currentPath.split('/')[0];
+ res = {
+ type: 'text',
+ label: currFolder
+ };
+
+ subPath = currentPath.split(currFolder+'/')[1];
+ child = createFolderSubtree(subPath, root+'/'+currFolder, files);
+ }
+
+ if(child){
+ res.children = [];
+ res.children.push(child);
+ }
+
+ for(var j in files){
+ filePath = files[j];
+ if(filePath.search(root+'/'+currFolder) == 0){
+ fileName = filePath.split(root+'/'+currFolder+'/')[1];
+ if(fileName.search('/') >= 0)
+ continue;
+
+ if(!res.children)
+ res.children = [];
+
+ file = {
+ type: 'text',
+ label: fileName,
+ className: 'file-picker-file-node'
+ };
+
+ res.children.push(file);
+ }
+ }
+
+ return res;
+ };
+
+ var mergeFolders = function(f1, f2){
+ var res = f1, i, j, label1, label2,
+ unique, isFolder,
+ c1 = res.children,
+ c2 = f2.children;
+
+ for(i in c2){
+ unique = true;
+ isFolder = false;
+ label1 = c2[i].label;
+
+ for(j in c1){
+ label2 = c1[j].label;
+ if(label1 == label2){
+ unique = false;
+ if(c2[i].children != null || c1[j].children != null){
+ isFolder = true;
+ }
+ break;
+ }
+ }
+
+ if(unique){
+ c1.push(c2[i]);
+ }else if(isFolder){
+ c1[j] = mergeFolders(c1[j], c2[i]);
+ }
+ }
+
+ res.children = c1;
+ return res;
+ };
+
+ var getChannelsSuccessCB = function(sRequest, oResponse, oPayload){
+ if(oResponse){
+ var treeData,
+ treeNode, dirPath, children, filePath, fileName, file,
+ files = oResponse.files,
+ dirs = oResponse.results, i,
+ root = oResponse.meta.root;
+
+ treeData = {
+ type: 'text',
+ label: root
+ };
+
+ treeData.children = [];
+
+ for(i in dirs){
+ if(dirs[i].path == root)
+ continue;
+
+ dirPath = dirs[i].path.split(root+'/')[1];
+
+ treeNode = createFolderSubtree(dirPath, root, files, treeData);
+
+ treeData.children.push(treeNode);
+ }
+
+ var merged = {}, folders = treeData.children, folder, folderLabel;
+
+ for(i in folders){
+ folder = folders[i];
+ folderLabel = folder.label;
+
+ if(!merged[folderLabel]){
+ merged[folderLabel] = folder;
+ continue;
+ }else{
+ merged[folderLabel] = mergeFolders(merged[folderLabel], folder);
+ }
+ }
+
+ treeData.children = [];
+ for(i in merged){
+ treeData.children.push(merged[i]);
+ }
+
+ tree = new YAHOO.widget.TreeView("filePickerTree", [treeData]);
+ //tree = new YAHOO.widget.TreeView("filePickerTree", [merged]);
+ tree.render();
+ tree.subscribe('clickEvent', Y.bind(nodeClickEventHandler, this));
+ }
+ };
+
+ var getChannelsFailureCB = function(sRequest, oResponse, oPayload){
+ if(oResponse){
+
+ }
+ };
+
+ channelsDS.sendRequest(null,
+ {
+ success : getChannelsSuccessCB,
+ failure : getChannelsFailureCB,
+ scope : this,
+ argument: {}
+ });
+
+ var config = {
+ srcNode: "#curationMapReduceConsole"
+ };
+
+ var mapReduceConsole = new Y.CurationMapReduceConsole(config);
+ mapReduceConsole.render();
+ //mapReduceConsole.set('input', "\"this is example one\"\n\"another example\"\n\"yet another one\"\n\"one more example\"");
+
+ var nodeClickEventHandler = function(event){
+ // Only update input if file is picked
+ if(event.node.className == 'file-picker-file-node'){
+ if(!mapReduceConsole)
+ return;
+
+ mapReduceConsole.set('input', "\"Maui\"\n\"Kaui\"\n\"Oahu\"\n\"Honolulu\"");
+
+ }
+ };
+
+});
View
510 ui/js/map-reduce-widget.js
@@ -0,0 +1,510 @@
+/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of Yahoo! Inc. nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of Yahoo! Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+Y.add('curation-map-reduce-console', function(Y){
+
+ var isUndefined = Y.Lang.isUndefined,
+ isObject = Y.Lang.isObject,
+ isArray = Y.Lang.isArray,
+ isFunction = Y.Lang.isFunction,
+ isNull = Y.Lang.isNull,
+ isString = Y.Lang.isString,
+ isNumber = Y.Lang.isNumber;
+
+ /* constructor */
+ var CurationMapReduceConsole = function(config) {
+ CurationMapReduceConsole.superclass.constructor.apply(this, arguments);
+ }
+
+ /*
+ * Required NAME static field, to identify the Widget class and
+ * used as an event prefix, to generate class names etc. (set to the
+ * class name in camel case).
+ */
+ CurationMapReduceConsole.NAME = "curation-map-reduce-console";
+
+ /*
+ * The attribute configuration for the Spinner widget. Attributes can be
+ * defined with default values, get/set functions and validator functions
+ * as with any other class extending Base.
+ */
+ CurationMapReduceConsole.ATTRS = {
+ // The current value of the spinner.
+ input : {
+ value:{},
+ setter: function(val){
+ this.inputTextArea.set('value', val);
+ this._eventUpdate();
+ },
+ getter: function(){
+ return this.inputTextArea.get('value');
+ }/*,
+ validator: function(val) {
+ return this._validateValue(val);
+ }*/
+ },
+
+ // The strings for the map reduce console UI. This attribute is
+ // defined by the base Widget class but has an empty value. The
+ // spinner is simply providing a default value for the attribute.
+ strings: {
+ value: {
+ mapFunctionLabel: "Map:",
+ flattenFunctionLabel: "Flatten",
+ groupByFunctionLabel: "Group By:",
+ intermediaryOutputLabel: "Intermediary Output:"
+ }
+ }
+ };
+
+ /* Static constant used to identify the classname applied to the spinners value field */
+ CurationMapReduceConsole.INPUT_CLASS = Y.ClassNameManager.getClassName(CurationMapReduceConsole.NAME, "input");
+
+ /* Static constants used to define the markup templates used to create Spinner DOM elements */
+ //Spinner.INPUT_TEMPLATE = '<input type="text" class="' + Spinner.INPUT_CLASS + '">';
+ //Spinner.BTN_TEMPLATE = '<button type="button"></button>';
+
+ /*
+ * The HTML_PARSER static constant is used by the Widget base class to populate
+ * the configuration for the spinner instance from markup already on the page.
+ *
+ * The Spinner class attempts to set the value of the spinner widget if it
+ * finds the appropriate input element on the page.
+ */
+ CurationMapReduceConsole.HTML_PARSER = {
+ //value: function (srcNode) {
+ //var val = parseInt(srcNode.get("value"));
+ //return Y.Lang.isNumber(val) ? val : null;
+ //}
+ };
+
+ /* CurationMapReduceConsole extends the base Widget class */
+ Y.extend(CurationMapReduceConsole, Y.Widget, {
+ /* instance data */
+ good: 'img/check.png',
+ bad: 'img/err.png',
+ steps: [],
+
+ /*
+ * initializer is part of the lifecycle introduced by
+ * the Widget class. It is invoked during construction,
+ * and can be used to setup instance specific state.
+ *
+ */
+ initializer: function() {
+ // Not doing anything special during initialization
+ },
+
+ /*
+ * destructor is part of the lifecycle introduced by
+ * the Widget class. It is invoked during destruction,
+ * and can be used to cleanup instance specific state.
+ *
+ * The map reduce console widget cleans up any node
+ * references it's holding onto. The Widget classes destructor
+ * will purge the widget's bounding box of event listeners, so
+ * spinner only needs to clean up listeners it attaches outside
+ * of the bounding box.
+ */
+ destructor : function() {
+ //this._documentMouseUpHandle.detach();
+
+ this.inputTextArea = null;
+ this.inputImage = null;
+ this.dataErrorMsg = null;
+ this.loadingDiv = null;
+ this.inputOutputContainer = null;
+ this.farRight = null;
+ },
+
+ /*
+ * renderUI is part of the lifecycle introduced by the
+ * Widget class. Widget's renderer method invokes:
+ *
+ * renderUI()
+ * bindUI()
+ * syncUI()
+ *
+ * renderUI is intended to be used by the Widget subclass
+ * to create or insert new elements into the DOM.
+ *
+ */
+ renderUI : function() {
+ //this._renderInput();
+ //this._renderButtons();
+ var boundingBox = this.get("boundingBox");
+ this.inputTextArea = boundingBox.one('#in');
+ this.inputImage = boundingBox.one('#inputImage');
+ this.dataErrorMsg = boundingBox.one('#dataError');
+ this.loadingDiv = boundingBox.one("#loading");
+ this.inputOutputContainer = boundingBox.one('#inputOutputContainer');
+ this.farRight = boundingBox.one("#farRight");
+ },
+
+ /*
+ * bindUI is intended to be used by the Widget subclass
+ * to bind any event listeners which will drive the Widget UI.
+ *
+ * It will generally bind event listeners for attribute change
+ * events, to update the state of the rendered UI in response
+ * to attribute value changes, and also attach any DOM events,
+ * to activate the UI.
+ *
+ * For spinner, the method:
+ *
+ * - Sets up the attribute change listener for the "value" attribute
+ *
+ * - Binds key listeners for the arrow/page keys
+ * - Binds mouseup/down listeners on the boundingBox, document respectively.
+ * - Binds a simple change listener on the input box.
+ */
+ bindUI : function() {
+ //this.after("valueChange", this._afterValueChange);
+
+
+
+ // Looking for a key event which will fire continously across browsers while the key is held down. 38, 40 = arrow up/down, 33, 34 = page up/down
+ //var keyEventSpec = (!Y.UA.opera) ? "down:" : "press:";
+ //keyEventSpec += "38, 40, 33, 34";
+
+ //Y.on("key", Y.bind(this._onDirectionKey, this), boundingBox, keyEventSpec);
+ //Y.on("mousedown", Y.bind(this._onMouseDown, this), boundingBox);
+ //this._documentMouseUpHandle = Y.on("mouseup", Y.bind(this._onDocMouseUp, this), boundingBox.get("ownerDocument"));
+
+ //Y.on("change", Y.bind(this._onInputChange, this), this.inputNode);
+
+ //this.inputTextArea.on('keyup', Y.bind(this._eventUpdate, this));
+ Y.delegate("keyup", Y.bind(this._eventUpdate, this), '#inputOutputContainer', "textarea");
+ Y.delegate("click", Y.bind(this._functionButtonClickHandler, this), '#functions', "input");
+ Y.delegate("click", Y.bind(this._exampleButtonClickHandler, this), '#examples', "input");
+ },
+
+ /*
+ * syncUI is intended to be used by the Widget subclass to
+ * update the UI to reflect the current state of the widget.
+ *
+ * For spinner, the method sets the value of the input field,
+ * to match the current state of the value attribute.
+ */
+ syncUI : function() {
+ //this._uiSetValue(this.get("value"));
+ },
+
+ /*
+ * Private Methods (naming convention with underscore as prefix)
+ */
+ _functionButtonClickHandler : function(e) {
+ var button = e.currentTarget,
+ buttonId = button.get("id");
+
+ if(buttonId == "mapButton")
+ this._newMap();
+ else if(buttonId == "flattenButton")
+ this._newFlatten();
+ else if(buttonId == "groupByButton")
+ this._newGroupBy();
+ else if(buttonId == "removeLastButton")
+ this._deleteLastStep();
+ else if(buttonId == "submitToGridButton")
+ this._submitJS();
+
+ },
+
+ _exampleButtonClickHandler : function(e){
+ var button = e.currentTarget,
+ buttonId = button.get("id");
+
+ if(buttonId == "wordCountButton")
+ this._wordCount();
+ else if(buttonId == "entityRelButton")
+ this._entityRels();
+ },
+
+ _eventUpdate : function() {
+ //var inputData = this.inputTextArea.get('value').split("\n"),
+ var inputData = this.get('input').split("\n"),
+ inputs = new Array(),
+ input;
+ for (var i=0;i<inputData.length;i++) {
+ try {
+ eval('input='+inputData[i]);
+ inputs.push(input);
+ this.inputImage.set('src', this.good);
+ this.dataErrorMsg.set('innerHTML', '');
+ } catch (error) {
+ this.inputImage.set('src', this.bad);
+ this.dataErrorMsg.set('innerHTML', error);
+ return;
+ }
+ }
+ var boundingBox = this.get("boundingBox"),
+ outputNode;
+ for (var i in this.steps) {
+ inputs=this.steps[i].compute(inputs);
+ outputNode = boundingBox.one('#output_'+i);
+ outputNode.set('value', this._toDisplay(inputs));
+ }
+ },
+
+ _getFunc : function(func_index) {
+ try {
+ var f, boundingBox = this.get("boundingBox")
+ eval('f='+boundingBox.one('#function_'+func_index).get('value'));
+ boundingBox.one('#functionImage_'+func_index).set('src', this.good);
+ boundingBox.one('#functionError_'+func_index).set('innerHTML', '');
+ return f;
+ } catch (error) {
+ boundingBox.one('#functionImage_'+func_index).set('src', this.bad);
+ boundingBox.one('#functionError_'+func_index).set('innerHTML', error);
+ throw error;
+ }
+ },
+
+ _submitJS : function() {
+ this.loadingDiv.set('innerHTML', '<img src="img/loading.gif">');
+ },
+
+ _toDisplay : function(inputs) {
+ var outputData = new Array();
+ for (var i in inputs) {
+ outputData.push(Y.JSON.stringify(inputs[i], undefined, " "));
+ }
+ return outputData.join("\n");
+ },
+
+ _insertNewColumn : function(id, html) {
+ var boundingBox = this.get('boundingBox'),
+ parent = this.inputOutputContainer,
+ marker = boundingBox.one("#newColumn"),
+ newColumn = parent.create('<td id="'+id+'"></td>');
+
+ parent.insertBefore(newColumn, marker);
+ newColumn.set('innerHTML', html);
+
+ this.farRight.scrollIntoView(true);
+ },
+
+ _newIntermediaryOutput : function() {
+ var index = this.steps.length - 1;
+ this._insertNewColumn('column_'+index+'_output',
+ '<table>'+
+ '<tr>'+
+ ' <td height=50>'+
+ ' Intermediary Output:'+
+ ' </td>'+
+ '</tr>'+
+ '<tr>'+
+ ' <td>'+
+ ' <textarea id="output_'+index+'" rows="38" cols="30" READONLY></textarea>'+
+ '</td>'+
+ '</tr>'+
+ '</table>');
+ },
+
+ _newMap : function() {
+ var index = this.steps.length,
+ that = this;
+ this.steps.push({ type:"map", index:index,
+ compute: function(inputs) {
+ var result = new Array();
+ var f = that._getFunc(this.index);
+ for (i=0; i<inputs.length; i++) {
+ result.push(f(inputs[i]));
+ }
+ return result;
+ }});
+
+ this._insertNewColumn('column_'+index,
+ '<table>'+
+ '<tr>'+
+ ' <td height=50>'+
+ ' Map: <img id="functionImage_'+index+'" src="img/check.png" width=20 height=20>'+
+ ' </td>'+
+ '</tr>'+
+ '<tr>'+
+ ' <td>'+
+ ' <textarea id="function_'+index+'" rows="38" cols="40">function(input){\n'+
+ ' return input;\n'+
+ '}</textarea>'+
+ '</td>'+
+ '</tr>'+
+ '<tr>'+
+ ' <td>'+
+ ' <p id="functionError_'+index+'"></p>'+
+ ' </td>'+
+ '</tr>'+
+ '</table>');
+
+ this._newIntermediaryOutput();
+ this._eventUpdate();
+ },
+
+ _newFlatten : function() {
+ var boundingBox = this.get('boundingBox'),
+ index = this.steps.length;
+ this.steps.push({ type:"flatten", index:index ,
+ compute: function(inputs) {
+ var result = new Array();
+ for (var i=0; i<inputs.length; i++) {
+ for (var j=0; j<inputs[i].length; j++) {
+ result.push(inputs[i][j]);
+ }
+ }
+ return result;
+ }});
+
+ this._insertNewColumn('column_'+index,'Flatten');
+
+ boundingBox.one('#column_'+index).set('vAlign', "middle");
+
+ this._newIntermediaryOutput();
+ this._eventUpdate();
+ },
+
+ _newGroupBy : function() {
+ var index = this.steps.length,
+ that = this;
+ this.steps.push({ type:"GroupBy", index:index ,
+ compute: function(inputs) {
+ var result = new Object();
+ var f = that._getFunc(this.index);
+ for (var i=0; i<inputs.length; i++) {
+ var key = f(inputs[i]);
+ var group = result[key];
+ if (group == undefined) {
+ group = {key:key, values:new Array()};
+ result[key] = group;
+ }
+ group.values.push(inputs[i]);
+ }
+ var ret = new Array();
+ for (var key in result) {
+ // alert(key);
+ if (key!="parseJSON" && key!="toJSONString") {
+ ret.push(result[key]);
+ }
+ }
+ // alert(JSON.stringify(ret));
+ return ret;
+ }});
+
+ this._insertNewColumn('column_'+index,
+ '<table>'+
+ '<tr>'+
+ ' <td height=50>'+
+ ' Group By: <img id="functionImage_'+index+'" src="img/check.png" width=20 height=20>'+
+ ' </td>'+
+ '</tr>'+
+ '<tr>'+
+ ' <td>'+
+ ' <textarea id="function_'+index+'" rows="38" cols="40">function(input){\n'+
+ ' return input;\n'+
+ '}</textarea>'+
+ '</td>'+
+ '</tr>'+
+ '<tr>'+
+ ' <td>'+
+ ' <p id="functionError_'+index+'"></p>'+
+ ' </td>'+
+ '</tr>'+
+ '</table>');
+
+ this._newIntermediaryOutput();
+ this._eventUpdate();
+ },
+
+ _deleteLastStep : function() {
+ var boundingBox = this.get('boundingBox'),
+ index = this.steps.length - 1,
+ c = boundingBox.one('#column_'+index),
+ co = boundingBox.one('#column_'+index+'_output'),
+ parent = this.inputOutputContainer;
+
+ parent.removeChild(c);
+ parent.removeChild(co);
+
+ this.steps.splice(index, 1);
+ this._eventUpdate();
+ },
+
+ _clearAllColumns : function() {
+ var n = this.steps.length;
+ for (var i=0; i < n; ++i) {
+ this._deleteLastStep();
+ }
+ },
+
+ _wordCount : function() {
+ this._clearAllColumns();
+ //this.inputTextArea.set('value', '"this is example one"\n"another example"\n"yet another one"\n"one more example"');
+
+ this.set('input', "\"this is example one\"\n\"another example\"\n\"yet another one\"\n\"one more example\"");
+ this._newMap();
+ this.inputOutputContainer.one('#function_0').set('value', 'function(input) {\n return input.split(" ");\n}');
+ this._newFlatten();
+ this._newGroupBy();
+ this._newMap();
+ this.inputOutputContainer.one('#function_3').set('value', 'function(input) {\n return {w:input.key,c:input.values.length};\n}');
+ this._eventUpdate();
+ },
+
+ _entityRels : function() {
+ this._clearAllColumns();
+ //this.set('input', '{"article":1, "entities":[1,2,7]}\n{"article":2, "entities":[2,3]}\n{"article":3, "entities":[2,5,6]}\n{"article":4, "entities":[7]}\n{"article":5, "entities":[7,5,6]}\n{"article":6, "entities":[1,5,6,2]}\n{"article":7, "entities":[6,5]}');
+ this.set('input', "{\"article\":1, \"entities\":[1,2,7]}\n{\"article\":2, \"entities\":[2,3]}\n{\"article\":3, \"entities\":[2,5,6]}\n{\"article\":4, \"entities\":[7]}\n{\"article\":5, \"entities\":[7,5,6]}\n{\"article\":6, \"entities\":[1,5,6,2]}\n{\"article\":7, \"entities\":[6,5]}");
+ this._newMap();//0
+ this.inputOutputContainer.one('#function_0').set('value', 'function(input){\n var entities = input.entities;\n var r = new Array();\n for (var i=0; i<entities.length; i++) {\n for (var j=0; j<i; j++) {\n var e1 = entities[i];\n var e2 = entities[j];\n if (e1<e2) {\n r.push({e1:e1, e2:e2});\n } else {\n r.push({e1:e2, e2:e1});\n }\n }\n }\n return r;\n}');
+ this._newFlatten();//1
+ this._newGroupBy();//2
+ this.inputOutputContainer.one('#function_2').set('value', 'function(input){\n return input.e1+","+input.e2;\n}');
+ this._newMap();//3
+ this.inputOutputContainer.one('#function_3').set('value', 'function(input){\n var k = input.values[0];\n return [{ e1:k.e1, e2:k.e2, c:input.values.length},\n { e1:k.e2, e2:k.e1, c:input.values.length}];\n}');
+ this._newFlatten();//4
+ this._newGroupBy();//5
+ this.inputOutputContainer.one('#function_5').set('value', 'function(input){\n return input.e1;\n}');
+ this._newMap();//6
+ this.inputOutputContainer.one('#function_6').set('value', 'function(input){\n var r = new Array();\n for (var i=0;i<input.values.length;i++) {\n r.push({entity:input.values[i].e2, score:input.values[i].c});\n }\n return {entity:input.key, related:r};\n}');
+ this._eventUpdate();
+ }
+ });
+
+ if(isUndefined(Y.CurationMapReduceConsole))
+ Y.namespace("CurationMapReduceConsole");
+
+ Y.CurationMapReduceConsole = CurationMapReduceConsole;
+
+}, '1.0.0' /* module version */, {
+ requires: ['base', 'widget', 'node', 'json', 'event']
+});
View
162 ui/test/html/map-reduce-widget-test-suite.html
@@ -0,0 +1,162 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+
+<!--
+
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of Yahoo! Inc. nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of Yahoo! Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<title>Map Reduce Console Widget Test Suite</title>
+
+<style type="text/css">
+/*margin and padding on body element
+ can introduce errors in determining
+ element position and are not recommended;
+ we turn them off as a foundation for YUI
+ CSS treatments. */
+body {
+ margin:0;
+ padding:0;
+}
+</style>
+
+<link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/3.3.0/build/cssfonts/fonts-min.css" />
+<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>
+
+
+<!--begin custom header content for this example-->
+
+<style type="text/css">
+#testLogger {
+ margin-bottom: 1em;
+ position: fixed;
+ right: 0;
+ top: 30px;
+}
+
+#testLogger .yui3-console .yui3-console-title {
+ border: 0 none;
+ color: #000;
+ font-size: 13px;
+ font-weight: bold;
+ margin: 0;
+ text-transform: none;
+}
+#testLogger .yui3-console .yui3-console-entry-meta {
+ margin: 0;
+}
+
+.yui3-skin-sam .yui3-console-entry-pass .yui3-console-entry-cat {
+ background: #070;
+ color: #fff;
+}
+</style>
+
+<!--end custom header content for this example-->
+
+</head>
+
+<body class="yui3-skin-sam yui-skin-sam">
+
+<h1>Map Reduce Console Widget Test Suite</h1>
+
+<div id="testLogger"></div>
+
+ <div id="curationMapReduceConsole">
+ <form name=f>
+ <table>
+ <tr id="inputOutputContainer" valign="top">
+ <td>
+ <table>
+ <tr>
+ <td height=50>
+ Input: <img id="inputImage" src="../img/check.png" width=20 height=20>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <textarea id="in" rows="20" cols="40">"example number one"
+"another example"
+"yet another one"
+"last example"
+ </textarea>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p id="dataError"></p>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td id="newColumn" valign="middle">
+ <div id="functions">
+ <input id="mapButton" type="button" value="map"><br>
+ <input id="flattenButton" type="button" value="flatten"><br>
+ <input id="groupByButton" type="button" value="group by"><br><br>
+ <input id="removeLastButton" type="button" value="remove last"><br><br>
+ <input id="submitToGridButton" type="button" value="Submit to the grid">
+ </div>
+ </td>
+ <td>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </td>
+ <td valign="middle">
+ <div id="loading"></div>
+ </td>
+ <td id="farRight">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+ </td>
+ </tr>
+ </table>
+ <div id="examples">
+ <input id="wordCountButton" type="button" value="wordcount example">
+ <input id="entityRelButton" type="button" value="entity relationships example">
+ </div>
+ </form>
+ </div>
+
+<script type="text/javascript" charset="utf-8">
+ if("undefined"==typeof Y)
+ Y = YUI({debug:true, useConsole:true, filter: 'raw'});
+</script>
+
+<script src="../assets/map-reduce-widget.js"></script>
+<script src="assets/map-reduce-widget-test-suite.js"></script>
+
+</body>
+</html>
View
BIN  ui/test/img/check.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  ui/test/img/err.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  ui/test/img/loading.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
221 ui/test/js/map-reduce-widget-test-suite.js
@@ -0,0 +1,221 @@
+/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of Yahoo! Inc. nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of Yahoo! Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+Y.use("node", "node-event-simulate", "console", "test", "curation-map-reduce-console", function (Y) {
+
+ Y.namespace("CurationMapReduceConsoleTest");
+
+ Y.CurationMapReduceConsoleTest.FunctionTestCase = new Y.Test.Case({
+
+ //name of the test case - if not provided, one is auto-generated
+ name : "Function Tests",
+
+ //---------------------------------------------------------------------
+ // setUp and tearDown methods - optional
+ //---------------------------------------------------------------------
+
+ /*
+ * Sets up data that is needed by each test.
+ */
+ setUp : function () {
+ this.mapReduceConsole = Y.CurationMapReduceConsoleTest.TestSuite.mapReduceConsole;
+ if(!this.mapReduceConsole.get('rendered')){
+ this.mapReduceConsole.render();
+ }
+ this.functionsDiv = Y.one('#functions');
+ this.inputTextArea = Y.one('#in');
+ this.inputTextArea.set('value', '');
+ this.removeLastButton = Y.one('#removeLastButton');
+ },
+
+ /*
+ * Cleans up everything that was created by setUp().
+ */
+ tearDown : function () {
+ this.functionsDiv = null;
+ this.inputTextArea = null;
+ this.removeLastButton = null;
+ this.mapReduceConsole = null;
+ },
+
+ //---------------------------------------------------------------------
+ // Test methods - names must begin with "test"
+ //---------------------------------------------------------------------
+
+ testMap: function (){
+ var Assert = Y.Assert,
+ mapButton = this.functionsDiv.one('#mapButton');
+
+ Assert.isNotUndefined(mapButton);
+ Assert.isNotUndefined(this.inputTextArea);
+
+ this.inputTextArea.set('value', '"this is example one"\n"another example"\n"yet another one"\n"one more example"');
+ mapButton.simulate("click");
+
+ var function0 = Y.one('#function_0'),
+ output0 = Y.one('#output_0');
+
+ Assert.isNotUndefined(function0);
+ Assert.isNotUndefined(output0);
+
+ var function0val = function0.get('value');
+ Assert.areEqual(function0val, 'function(input){\n'+
+ ' return input;\n}');
+
+ var output0val = output0.get('value');
+ Assert.areEqual(output0val, '"this is example one"\n"another example"\n"yet another one"\n"one more example"');
+
+ this.removeLastButton.simulate('click');
+ },
+
+ testGroupBy: function(){
+ var Assert = Y.Assert,
+ groupByButton = this.functionsDiv.one('#groupByButton');
+
+ Assert.isNotUndefined(groupByButton);
+ Assert.isNotUndefined(this.inputTextArea);
+
+ this.inputTextArea.set('value', '"this is example one"\n"another example"\n"yet another one"');
+ groupByButton.simulate("click");
+
+ var function0 = Y.one('#function_0'),
+ output0 = Y.one('#output_0');
+
+ Assert.isNotUndefined(function0);
+ Assert.isNotUndefined(output0);
+
+ var function0val = function0.get('value');
+ Assert.areEqual(function0val, 'function(input){\n'+
+ ' return input;\n}');
+
+ var expectedOutput = '{\n "key": "this is example one",\n "values": [\n "this is example one"\n ]\n}\n{\n "key": "another example",\n "values": [\n "another example"\n ]\n}\n{\n "key": "yet another one",\n "values": [\n "yet another one"\n ]\n}';
+ var output0val = output0.get('value');
+ Assert.areEqual(expectedOutput, output0val);
+
+ this.removeLastButton.simulate('click');
+ },
+
+ testFlatten: function(){
+ var Assert = Y.Assert,
+ flattenButton = this.functionsDiv.one('#flattenButton');
+
+ Assert.isNotUndefined(flattenButton);
+ Assert.isNotUndefined(this.inputTextArea);
+
+ this.inputTextArea.set('value', '"test input"');
+ flattenButton.simulate("click");
+
+ var output0 = Y.one('#output_0');
+
+ Assert.isNotUndefined(output0);
+
+ var output0val = output0.get('value');
+ Assert.areEqual(output0val, '"t"\n"e"\n"s"\n"t"\n" "\n"i"\n"n"\n"p"\n"u"\n"t"');
+
+ this.removeLastButton.simulate('click');
+ },
+
+ testRemoveLast: function(){
+ var Assert = Y.Assert,
+ groupByButton = this.functionsDiv.one('#groupByButton');
+
+ Assert.isNotUndefined(groupByButton);
+ Assert.isNotUndefined(this.inputTextArea);
+
+ this.inputTextArea.set('value', '"this is example one"\n"another example"\n"yet another one"\n"one more example"');
+ groupByButton.simulate("click");
+
+ var function0 = Y.one('#function_0'),
+ output0 = Y.one('#output_0');
+
+ Assert.isNotUndefined(function0);
+ Assert.isNotUndefined(output0);
+
+ this.removeLastButton.simulate('click');
+
+ function0 = Y.one('#function_0'),
+ output0 = Y.one('#output_0');
+
+ Assert.isNull(function0);
+ Assert.isNull(output0);
+ },
+
+ testSubmit: function(){
+ var Assert = Y.Assert,
+ submitButton = this.functionsDiv.one('#submitToGridButton');
+
+ submitButton.simulate('click');
+
+ var loadingDiv = Y.one('#loading'),
+ loadingImg = loadingDiv.one('img');
+
+ Assert.isInstanceOf(Y.Node, loadingImg);
+ }
+
+ });
+
+ //create a test suite
+ Y.CurationMapReduceConsoleTest.TestSuite = new Y.Test.Suite({
+ name : "Curation Map Reduce Widget Test Suite",
+
+ setUp : function () {
+ var config = {
+ srcNode: "#curationMapReduceConsole"
+ };
+ this.mapReduceConsole = new Y.CurationMapReduceConsole(config);
+ //this.mapReduceConsole.render();
+ },
+
+ tearDown: function () {
+ this.mapReduceConsole = null;
+ }
+ });
+
+ Y.CurationMapReduceConsoleTest.TestSuite.add(Y.CurationMapReduceConsoleTest.FunctionTestCase);
+
+ //create the console
+ var r = new Y.Console({
+ newestOnTop : false,
+ height: '500px'
+ });
+
+ r.render('#testLogger');
+
+ Y.Test.Runner.add(Y.CurationMapReduceConsoleTest.TestSuite);
+
+ //run the tests
+ Y.Test.Runner.run();
+
+});
View
82 ui/xml/hdfs-channels.php
@@ -0,0 +1,82 @@
+<?php
+/*
+Copyright (c) 2011, Yahoo! Inc. All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the
+ following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the
+ following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+* Neither the name of Yahoo! Inc. nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior
+ written permission of Yahoo! Inc.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+
+//Set the content-type header to xml
+header("Content-type: application/xml");
+//echo the XML declaration
+echo chr(60).chr(63).'xml version="1.0" encoding="utf-8" '.chr(63).chr(62);
+?>
+<listing time="2011-06-24T00:20:43+0000" recursive="yes" path="/user/ledemj/nightcrawler" exclude="" filter=".*" version="0.20.202.1.1101050227">
+ <directory path="/user/ledemj/nightcrawler" modified="2011-05-19T00:09:35+0000" accesstime="1970-01-01T00:00:00+0000" permission="drwxrwxrwx" owner="ledemj" group="users"/>
+ <directory path="/user/ledemj/nightcrawler/test"/>
+ <file path="/user/ledemj/nightcrawler/test/file1"/>
+ <file path="/user/ledemj/nightcrawler/test/file2"/>
+ <directory path="/user/ledemj/nightcrawler/test/folder1"/>
+ <file path="/user/ledemj/nightcrawler/test/folder1/file1"/>
+ <file path="/user/ledemj/nightcrawler/test/folder1/file2"/>
+ <directory path="/user/ledemj/nightcrawler/test/folder1/folder11/folder111"/>
+ <directory path="/user/ledemj/nightcrawler/test/folder1/folder11/folder112"/>
+ <directory path="/user/ledemj/nightcrawler/test/folder2"/>
+ <directory path="/user/ledemj/nightcrawler/test/folder1/folder11"/>
+ <file path="/user/ledemj/nightcrawler/test/folder1/folder11/folder111/file1"/>
+ <file path="/user/ledemj/nightcrawler/test/folder1/folder11/folder112/file1"/>
+ <file path="/user/ledemj/nightcrawler/test/folder1/folder11/file1"/>
+ <file path="/user/ledemj/nightcrawler/test/folder1/folder11/file2"/>
+ <file path="/user/ledemj/nightcrawler/test/folder1/folder11/file3"/>
+ <file path="/user/ledemj/nightcrawler/test/folder2/file1"/>
+ <file path="/user/ledemj/nightcrawler/test/folder2/file2"/>
+ <directory path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_13696efb-65f4-486c-8fe3-2c0e26f844ea" modified="2011-05-19T00:09:35+0000" accesstime="1970-01-01T00:00:00+0000" permission="drwxrwxrwx" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_13696efb-65f4-486c-8fe3-2c0e26f844ea/_SUCCESS" modified="2011-05-16T23:23:00+0000" accesstime="2011-05-16T23:23:00+0000" size="0" replication="3" blocksize="134217728" permission="-rw-rw-rw-" owner="nova_tst" group="users"/>
+ <directory path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_2ad86235-b8aa-41c5-b929-830977170efa" modified="2011-04-15T16:41:01+0000" accesstime="1970-01-01T00:00:00+0000" permission="drwxrwxrwx" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_2ad86235-b8aa-41c5-b929-830977170efa/_SUCCESS" modified="2011-04-15T16:41:01+0000" accesstime="2011-04-15T16:41:01+0000" size="0" replication="3" blocksize="134217728" permission="-rw-------" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_2ad86235-b8aa-41c5-b929-830977170efa/part-r-00000" modified="2011-04-15T16:39:37+0000" accesstime="2011-04-15T16:39:37+0000" size="12134" replication="3" blocksize="134217728" permission="-rw-------" owner="nova_tst" group="users"/>
+ <directory path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_47947478-8762-4c49-a1e6-a247f37efd2c" modified="2011-04-16T00:08:38+0000" accesstime="1970-01-01T00:00:00+0000" permission="drwxrwxrwx" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_47947478-8762-4c49-a1e6-a247f37efd2c/_SUCCESS" modified="2011-04-16T00:08:38+0000" accesstime="2011-04-16T00:08:38+0000" size="0" replication="3" blocksize="134217728" permission="-rw-rw-rw-" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_47947478-8762-4c49-a1e6-a247f37efd2c/part-r-00000" modified="2011-04-16T00:08:13+0000" accesstime="2011-04-16T00:08:13+0000" size="12134" replication="3" blocksize="134217728" permission="-rw-rw-rw-" owner="nova_tst" group="users"/>
+ <directory path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_57b0fa77-b667-4385-9a3e-5d237660d7da" modified="2011-04-14T00:22:23+0000" accesstime="1970-01-01T00:00:00+0000" permission="drwxrwxrwx" owner="ledemj" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_57b0fa77-b667-4385-9a3e-5d237660d7da/_SUCCESS" modified="2011-04-14T00:22:23+0000" accesstime="2011-04-14T00:22:23+0000" size="0" replication="3" blocksize="134217728" permission="-rw-------" owner="ledemj" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_57b0fa77-b667-4385-9a3e-5d237660d7da/part-r-00000" modified="2011-04-14T00:20:47+0000" accesstime="2011-04-14T00:20:47+0000" size="12134" replication="3" blocksize="134217728" permission="-rw-------" owner="ledemj" group="users"/>
+ <directory path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_a9f270b5-c03c-420e-b00e-7c13673d8fc7" modified="2011-04-15T22:22:08+0000" accesstime="1970-01-01T00:00:00+0000" permission="drwxrwxrwx" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_a9f270b5-c03c-420e-b00e-7c13673d8fc7/_SUCCESS" modified="2011-04-15T22:22:08+0000" accesstime="2011-04-15T22:22:08+0000" size="0" replication="3" blocksize="134217728" permission="-rw-------" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_a9f270b5-c03c-420e-b00e-7c13673d8fc7/part-r-00000" modified="2011-04-15T22:19:10+0000" accesstime="2011-04-15T22:19:10+0000" size="12134" replication="3" blocksize="134217728" permission="-rw-------" owner="nova_tst" group="users"/>
+ <directory path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_b24f05e4-fc64-4c56-85b5-b4e52f8c6875" modified="2011-04-14T17:29:27+0000" accesstime="1970-01-01T00:00:00+0000" permission="drwxrwxrwx" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_b24f05e4-fc64-4c56-85b5-b4e52f8c6875/_SUCCESS" modified="2011-04-14T17:29:27+0000" accesstime="2011-04-14T17:29:27+0000" size="0" replication="3" blocksize="134217728" permission="-rw-------" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_b24f05e4-fc64-4c56-85b5-b4e52f8c6875/part-r-00000" modified="2011-04-14T17:27:22+0000" accesstime="2011-04-14T17:27:22+0000" size="12134" replication="3" blocksize="134217728" permission="-rw-------" owner="nova_tst" group="users"/>
+ <directory path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_cb3e25d7-a971-4356-b512-b5aee9c994db" modified="2011-04-15T23:26:45+0000" accesstime="1970-01-01T00:00:00+0000" permission="drwxrwxrwx" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_cb3e25d7-a971-4356-b512-b5aee9c994db/_SUCCESS" modified="2011-04-15T23:26:45+0000" accesstime="2011-04-15T23:26:45+0000" size="0" replication="3" blocksize="134217728" permission="-rw-------" owner="nova_tst" group="users"/>
+ <file path="/user/ledemj/nightcrawler/report__channel_sameerm.stats.input__executionId_cb3e25d7-a971-4356-b512-b5aee9c994db/part-r-00000" modified="2011-04-15T23:26:37+0000" accesstime="2011-04-15T23:26:37+0000" size="12134" replication="3" blocksize="134217728" permission="-rw-------" owner="nova_tst" group="users"/>
+</listing>
Please sign in to comment.
Something went wrong with that request. Please try again.