<commit_before>/*  wrench.js
 *
 *  A collection of various utility functions I've found myself in need of
 *  for use with Node.js (http://nodejs.org/). This includes things like:
 *
 *  - Recursively deleting directories in Node.js (Sync, not Async)
 *  - Recursively copying directories in Node.js (Sync, not Async)
 *  - Recursively chmoding a directory structure from Node.js (Sync, not Async)
 *  - Other things that I'll add here as time goes on. Shhhh...
 *
 *  ~ Ryan McGrath (ryan [at] venodesigns.net)
 */

var fs = require("fs"),
    _path = require("path");

/*  wrench.readdirSyncRecursive("directory_path");
 *
 *  Recursively dives through directories and read the contents of all the
 *  children directories.
 */
exports.readdirSyncRecursive = function(baseDir) {
    baseDir = baseDir.replace(/\/$/, '');

    var readdirSyncRecursive = function(baseDir) {
        var files = [],
            curFiles,
            nextDirs,
            isDir = function(fname){
                return fs.statSync( _path.join(baseDir, fname) ).isDirectory();
            },
            prependBaseDir = function(fname){
                return _path.join(baseDir, fname);
            };

        curFiles = fs.readdirSync(baseDir);
        nextDirs = curFiles.filter(isDir);
        curFiles = curFiles.map(prependBaseDir);

        files = files.concat( curFiles );

        while (nextDirs.length) {
            files = files.concat( readdirSyncRecursive( _path.join(baseDir, nextDirs.shift()) ) );
        }

        return files;
    };

    // convert absolute paths to relative
    var fileList = readdirSyncRecursive(baseDir).map(function(val){
        return _path.relative(baseDir, val);
    });

    return fileList;
};

/*  wrench.readdirRecursive("directory_path", function(error, files) {});
 *
 *  Recursively dives through directories and read the contents of all the
 *  children directories.
 *
 *  Asynchronous, so returns results/error in callback.
 *  Callback receives the of files in currently recursed directory.
 *  When no more directories are left, callback is called with null for all arguments.
 *
 */
exports.readdirRecursive = function(baseDir, fn) {
    baseDir = baseDir.replace(/\/$/, '');

    var waitCount = 0;

    function readdirRecursive(curDir) {
        var prependcurDir = function(fname){
            return _path.join(curDir, fname);
        };

        waitCount++;
        fs.readdir(curDir, function(e, curFiles) {
            if (e) {
                fn(e);
                return;
            }
            waitCount--;

            curFiles = curFiles.map(prependcurDir);

            curFiles.forEach(function(it) {
                waitCount++;

                fs.stat(it, function(e, stat) {
                    waitCount--;

                    if (e) {
                        fn(e);
                    } else {
                        if (stat.isDirectory()) {
                            readdirRecursive(it);
                        }
                    }

                    if (waitCount == 0) {
                        fn(null, null);
                    }
                });
            });

            fn(null, curFiles.map(function(val) {
                // convert absolute paths to relative
                return _path.relative(baseDir, val);
            }));

            if (waitCount == 0) {
                fn(null, null);
            }
        });
    };

    readdirRecursive(baseDir);
};

/*  wrench.rmdirSyncRecursive("directory_path", forceDelete, failSilent);
 *
 *  Recursively dives through directories and obliterates everything about it. This is a
 *  Sync-function, which blocks things until it's done. No idea why anybody would want an
 *  Asynchronous version. :\
 */
exports.rmdirSyncRecursive = function(path, failSilent) {
    var files;

    try {
        files = fs.readdirSync(path);
    } catch (err) {
        if(failSilent) return;
        throw new Error(err.message);
    }

    /*  Loop through and delete everything in the sub-tree after checking it */
    for(var i = 0; i < files.length; i++) {
        var currFile = fs.lstatSync(_path.join(path, files[i]));

        if(currFile.isDirectory()) // Recursive function back to the beginning
            exports.rmdirSyncRecursive(_path.join(path, files[i]));

        else if(currFile.isSymbolicLink()) // Unlink symlinks
            fs.unlinkSync(_path.join(path, files[i]));

        else // Assume it's a file - perhaps a try/catch belongs here?
            fs.unlinkSync(_path.join(path, files[i]));
    }

    /*  Now that we know everything in the sub-tree has been deleted, we can delete the main
     directory. Huzzah for the shopkeep. */
    return fs.rmdirSync(path);
};

/*  wrench.copyDirSyncRecursive("directory_to_copy", "new_directory_location", opts);
 *
 *  Recursively dives through a directory and moves all its files to a new location. This is a
 *  Synchronous function, which blocks things until it's done. If you need/want to do this in
 *  an Asynchronous manner, look at wrench.copyDirRecursively() below. Specify forceDelete to force directory overwrite.
 *
 *  Note: Directories should be passed to this function without a trailing slash.
 */
exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) {
    try {
    	if(fs.statSync(newDirLocation).isDirectory()) {
    		if(typeof opts !== 'undefined' && opts.forceDelete) {
			exports.rmdirSyncRecursive(newDirLocation);
        	} else {
	    		return new Error('You are trying to delete a directory that already exists. Specify forceDelete in the opts argument to override this. Bailing~');
        	}
    	}
    } catch(e) { }

    /*  Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
    var checkDir = fs.statSync(sourceDir);
    try {
        fs.mkdirSync(newDirLocation, checkDir.mode);
    } catch (e) {
        //if the directory already exists, that's okay
        if (e.code !== 'EEXIST') throw e;
    }

    var files = fs.readdirSync(sourceDir);

    for(var i = 0; i < files.length; i++) {
        // ignores all files or directories which match the RegExp in opts.filter
		if(typeof opts !== 'undefined') {
            if(!opts.whitelist && opts.filter && files[i].match(opts.filter)) continue;
		    // if opts.whitelist is true every file or directory which doesn't match opts.filter will be ignored
		    if(opts.whitelist && opts.filter && !files[i].match(opts.filter)) continue;
            if (opts.excludeHiddenUnix && /^\./.test(files[i])) continue;
        }

        var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));

        var fCopyFile = function(srcFile, destFile) {
            if(typeof opts !== 'undefined' && opts.preserveFiles && fs.existsSync(destFile)) return;

            var contents = fs.readFileSync(srcFile);
            fs.writeFileSync(destFile, contents);
        };

        if(currFile.isDirectory()) {
            /*  recursion this thing right on back. */
            exports.copyDirSyncRecursive(_path.join(sourceDir, files[i]), _path.join(newDirLocation, files[i]), opts);
        } else if(currFile.isSymbolicLink()) {
            var symlinkFull = fs.readlinkSync(_path.join(sourceDir, files[i]));

            if (typeof opts !== 'undefined' && !opts.inflateSymlinks) {
                fs.symlinkSync(symlinkFull, _path.join(newDirLocation, files[i]));
                continue;
            }

            var tmpCurrFile = fs.lstatSync(_path.join(sourceDir, symlinkFull));
            if (tmpCurrFile.isDirectory()) {
                exports.copyDirSyncRecursive(_path.join(sourceDir, symlinkFull), _path.join(newDirLocation, files[i]), opts);
            } else {
                /*  At this point, we've hit a file actually worth copying... so copy it on over. */
                fCopyFile(_path.join(sourceDir, symlinkFull), _path.join(newDirLocation, files[i]));
            }
        } else {
            /*  At this point, we've hit a file actually worth copying... so copy it on over. */
            fCopyFile(_path.join(sourceDir, files[i]), _path.join(newDirLocation, files[i]));
        }
    }
};

/*  wrench.chmodSyncRecursive("directory", filemode);
 *
 *  Recursively dives through a directory and chmods everything to the desired mode. This is a
 *  Synchronous function, which blocks things until it's done.
 *
 *  Note: Directories should be passed to this function without a trailing slash.
 */
exports.chmodSyncRecursive = function(sourceDir, filemode) {
    var files = fs.readdirSync(sourceDir);

    for(var i = 0; i < files.length; i++) {
        var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));

        if(currFile.isDirectory()) {
            /*  ...and recursion this thing right on back. */
            exports.chmodSyncRecursive(_path.join(sourceDir, files[i]), filemode);
        } else {
            /*  At this point, we've hit a file actually worth copying... so copy it on over. */
            fs.chmod(_path.join(sourceDir, files[i]), filemode);
        }
    }

    /*  Finally, chmod the parent directory */
    fs.chmod(sourceDir, filemode);
};

/*  wrench.chownSyncRecursive("directory", uid, gid);
 *
 *  Recursively dives through a directory and chowns everything to the desired user and group. This is a
 *  Synchronous function, which blocks things until it's done.
 *
 *  Note: Directories should be passed to this function without a trailing slash.
 */
exports.chownSyncRecursive = function(sourceDir, uid, gid) {
    var files = fs.readdirSync(sourceDir);

    for(var i = 0; i < files.length; i++) {
        var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));

        if(currFile.isDirectory()) {
            /*  ...and recursion this thing right on back. */
            exports.chownSyncRecursive(_path.join(sourceDir, files[i]), uid, gid);
        } else {
            /*  At this point, we've hit a file actually worth chowning... so own it. */
            fs.chownSync(_path.join(sourceDir, files[i]), uid, gid);
        }
    }

    /*  Finally, chown the parent directory */
    fs.chownSync(sourceDir, uid, gid);
};

/*  wrench.rmdirRecursive("directory_path", callback);
 *
 *  Recursively dives through directories and obliterates everything about it.
 */
exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){
    fs.readdir(dir, function(err, files){
        if(err && typeof failSilent === 'boolean' && !failSilent)
		return clbk(err);

	if(typeof failSilent === 'function')
		clbk = failSilent;

        (function rmFile(err){
            if (err) return clbk(err);

            var filename = files.shift();
            if (filename === null || typeof filename == 'undefined')
                return fs.rmdir(dir, clbk);

            var file = dir+'/'+filename;
            fs.lstat(file, function(err, stat){
                if (err) return clbk(err);
                if (stat.isDirectory())
                    rmdirRecursive(file, rmFile);
                else
                    fs.unlink(file, rmFile);
            });
        })();
    });
};

/*  wrench.copyDirRecursive("directory_to_copy", "new_location", {forceDelete: bool}, callback);
 *
 *  Recursively dives through a directory and moves all its files to a new
 *  location. Specify forceDelete to force directory overwrite.
 *
 *  Note: Directories should be passed to this function without a trailing slash.
 */
exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) {
    fs.stat(newDir, function(err, newDirStat){
        if(!err) {
		if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete)
			return exports.rmdirRecursive(newDir, function(err){
				copyDirRecursive.apply(this, arguments);
        		});
		else
			return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.'));
	}

	if(typeof opts === 'function')
		clbk = opts;

        fs.stat(srcDir, function(err, srcDirStat){
            if (err) return clbk(err);
            fs.mkdir(newDir, srcDirStat.mode, function(err){
                if (err) return clbk(err);
                fs.readdir(srcDir, function(err, files){
                    if (err) return clbk(err);
                    (function copyFiles(err){
                        if (err) return clbk(err);

                        var filename = files.shift();
                        if (filename === null || typeof filename == 'undefined')
                            return clbk(null);

                        var file = srcDir+'/'+filename,
                            newFile = newDir+'/'+filename;

                        fs.stat(file, function(err, fileStat){
                            if (fileStat.isDirectory())
                                copyDirRecursive(file, newFile, copyFiles);
                            else if (fileStat.isSymbolicLink())
                                fs.readlink(file, function(err, link){
                                    fs.symlink(link, newFile, copyFiles);
                                });
                            else
                                fs.readFile(file, function(err, data){
                                    fs.writeFile(newFile, data, copyFiles);
                                });
                        });
                    })();
                });
            });
        });
    });
};

var mkdirSyncRecursive = function(path, mode) {
    var self = this;
    path = _path.normalize(path)

    try {
        fs.mkdirSync(path, mode);
    } catch(err) {
        if(err.code == "ENOENT") {
            var slashIdx = path.lastIndexOf(_path.sep);

            if(slashIdx > 0) {
                var parentPath = path.substring(0, slashIdx);
                mkdirSyncRecursive(parentPath, mode);
                mkdirSyncRecursive(path, mode);
            } else {
                throw err;
            }
        } else if(err.code == "EEXIST") {
            return;
        } else {
            throw err;
        }
    }
};
exports.mkdirSyncRecursive = mkdirSyncRecursive;

exports.LineReader = function(filename, bufferSize) {
    this.bufferSize = bufferSize || 8192;
    this.buffer = "";
    this.fd = fs.openSync(filename, "r");
    this.currentPosition = 0;
};

exports.LineReader.prototype = {
    close: function() {
        return fs.closeSync(this.fd);
    },

    getBufferAndSetCurrentPosition: function(position) {
        var res = fs.readSync(this.fd, this.bufferSize, position, "ascii");

        this.buffer += res[0];
        if(res[1] === 0) {
            this.currentPosition = -1;
        } else {
            this.currentPosition = position + res[1];
        }

        return this.currentPosition;
    },

    hasNextLine: function() {
        while(this.buffer.indexOf('\n') === -1) {
            this.getBufferAndSetCurrentPosition(this.currentPosition);
            if(this.currentPosition === -1) return false;
        }

        if(this.buffer.indexOf("\n") > -1 || this.buffer.length !== 0) return true;
        return false;
    },

    getNextLine: function() {
        var lineEnd = this.buffer.indexOf("\n"),
            result = this.buffer.substring(0, lineEnd != -1 ? lineEnd : this.buffer.length);

        this.buffer = this.buffer.substring(result.length + 1, this.buffer.length);
        return result;
    }
};

// vim: et ts=4 sw=4
<commit_msg>Update wrench.js<commit_after>/*  wrench.js
 *
 *  A collection of various utility functions I've found myself in need of
 *  for use with Node.js (http://nodejs.org/). This includes things like:
 *
 *  - Recursively deleting directories in Node.js (Sync, not Async)
 *  - Recursively copying directories in Node.js (Sync, not Async)
 *  - Recursively chmoding a directory structure from Node.js (Sync, not Async)
 *  - Other things that I'll add here as time goes on. Shhhh...
 *
 *  ~ Ryan McGrath (ryan [at] venodesigns.net)
 */

var fs = require("fs"),
    _path = require("path");

/*  wrench.readdirSyncRecursive("directory_path");
 *
 *  Recursively dives through directories and read the contents of all the
 *  children directories.
 */
exports.readdirSyncRecursive = function(baseDir) {
    baseDir = baseDir.replace(/\/$/, '');

    var readdirSyncRecursive = function(baseDir) {
        var files = [],
            curFiles,
            nextDirs,
            isDir = function(fname){
                return fs.statSync( _path.join(baseDir, fname) ).isDirectory();
            },
            prependBaseDir = function(fname){
                return _path.join(baseDir, fname);
            };

        curFiles = fs.readdirSync(baseDir);
        nextDirs = curFiles.filter(isDir);
        curFiles = curFiles.map(prependBaseDir);

        files = files.concat( curFiles );

        while (nextDirs.length) {
            files = files.concat( readdirSyncRecursive( _path.join(baseDir, nextDirs.shift()) ) );
        }

        return files;
    };

    // convert absolute paths to relative
    var fileList = readdirSyncRecursive(baseDir).map(function(val){
        return _path.relative(baseDir, val);
    });

    return fileList;
};

/*  wrench.readdirRecursive("directory_path", function(error, files) {});
 *
 *  Recursively dives through directories and read the contents of all the
 *  children directories.
 *
 *  Asynchronous, so returns results/error in callback.
 *  Callback receives the of files in currently recursed directory.
 *  When no more directories are left, callback is called with null for all arguments.
 *
 */
exports.readdirRecursive = function(baseDir, fn) {
    baseDir = baseDir.replace(/\/$/, '');

    var waitCount = 0;

    function readdirRecursive(curDir) {
        var prependcurDir = function(fname){
            return _path.join(curDir, fname);
        };

        waitCount++;
        fs.readdir(curDir, function(e, curFiles) {
            if (e) {
                fn(e);
                return;
            }
            waitCount--;

            curFiles = curFiles.map(prependcurDir);

            curFiles.forEach(function(it) {
                waitCount++;

                fs.stat(it, function(e, stat) {
                    waitCount--;

                    if (e) {
                        fn(e);
                    } else {
                        if (stat.isDirectory()) {
                            readdirRecursive(it);
                        }
                    }

                    if (waitCount == 0) {
                        fn(null, null);
                    }
                });
            });

            fn(null, curFiles.map(function(val) {
                // convert absolute paths to relative
                return _path.relative(baseDir, val);
            }));

            if (waitCount == 0) {
                fn(null, null);
            }
        });
    };

    readdirRecursive(baseDir);
};

/*  wrench.rmdirSyncRecursive("directory_path", forceDelete, failSilent);
 *
 *  Recursively dives through directories and obliterates everything about it. This is a
 *  Sync-function, which blocks things until it's done. No idea why anybody would want an
 *  Asynchronous version. :\
 */
exports.rmdirSyncRecursive = function(path, failSilent) {
    var files;

    try {
        files = fs.readdirSync(path);
    } catch (err) {
        if(failSilent) return;
        throw new Error(err.message);
    }

    /*  Loop through and delete everything in the sub-tree after checking it */
    for(var i = 0; i < files.length; i++) {
        var currFile = fs.lstatSync(_path.join(path, files[i]));

        if(currFile.isDirectory()) // Recursive function back to the beginning
            exports.rmdirSyncRecursive(_path.join(path, files[i]));

        else if(currFile.isSymbolicLink()) // Unlink symlinks
            fs.unlinkSync(_path.join(path, files[i]));

        else // Assume it's a file - perhaps a try/catch belongs here?
            fs.unlinkSync(_path.join(path, files[i]));
    }

    /*  Now that we know everything in the sub-tree has been deleted, we can delete the main
     directory. Huzzah for the shopkeep. */
    return fs.rmdirSync(path);
};

/*  wrench.copyDirSyncRecursive("directory_to_copy", "new_directory_location", opts);
 *
 *  Recursively dives through a directory and moves all its files to a new location. This is a
 *  Synchronous function, which blocks things until it's done. If you need/want to do this in
 *  an Asynchronous manner, look at wrench.copyDirRecursively() below. Specify forceDelete to force directory overwrite.
 *
 *  Note: Directories should be passed to this function without a trailing slash.
 */
exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) {
    try {
    	if(fs.statSync(newDirLocation).isDirectory()) {
    		if(typeof opts !== 'undefined' && opts.forceDelete) {
			exports.rmdirSyncRecursive(newDirLocation);
        	} else {
	    		return new Error('You are trying to delete a directory that already exists. Specify forceDelete in the opts argument to override this. Bailing~');
        	}
    	}
    } catch(e) { }

    /*  Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
    var checkDir = fs.statSync(sourceDir);
    try {
        fs.mkdirSync(newDirLocation, checkDir.mode);
    } catch (e) {
        //if the directory already exists, that's okay
        if (e.code !== 'EEXIST') throw e;
    }

    var files = fs.readdirSync(sourceDir);

    for(var i = 0; i < files.length; i++) {
        // ignores all files or directories which match the RegExp in opts.filter
		if(typeof opts !== 'undefined') {
            if(!opts.whitelist && opts.filter && files[i].match(opts.filter)) continue;
		    // if opts.whitelist is true every file or directory which doesn't match opts.filter will be ignored
		    if(opts.whitelist && opts.filter && !files[i].match(opts.filter)) continue;
            if (opts.excludeHiddenUnix && /^\./.test(files[i])) continue;
        }

        var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));

        var fCopyFile = function(srcFile, destFile) {
            if(typeof opts !== 'undefined' && opts.preserveFiles && fs.existsSync(destFile)) return;

            var contents = fs.readFileSync(srcFile);
            fs.writeFileSync(destFile, contents);
        };

        if(currFile.isDirectory()) {
            /*  recursion this thing right on back. */
            exports.copyDirSyncRecursive(_path.join(sourceDir, files[i]), _path.join(newDirLocation, files[i]), opts);
        } else if(currFile.isSymbolicLink()) {
            var symlinkFull = fs.readlinkSync(_path.join(sourceDir, files[i]));

            if (typeof opts !== 'undefined' && !opts.inflateSymlinks) {
                fs.symlinkSync(symlinkFull, _path.join(newDirLocation, files[i]));
                continue;
            }

            var tmpCurrFile = fs.lstatSync(_path.join(sourceDir, symlinkFull));
            if (tmpCurrFile.isDirectory()) {
                exports.copyDirSyncRecursive(_path.join(sourceDir, symlinkFull), _path.join(newDirLocation, files[i]), opts);
            } else {
                /*  At this point, we've hit a file actually worth copying... so copy it on over. */
                fCopyFile(_path.join(sourceDir, symlinkFull), _path.join(newDirLocation, files[i]));
            }
        } else {
            /*  At this point, we've hit a file actually worth copying... so copy it on over. */
            fCopyFile(_path.join(sourceDir, files[i]), _path.join(newDirLocation, files[i]));
        }
    }
};

/*  wrench.chmodSyncRecursive("directory", filemode);
 *
 *  Recursively dives through a directory and chmods everything to the desired mode. This is a
 *  Synchronous function, which blocks things until it's done.
 *
 *  Note: Directories should be passed to this function without a trailing slash.
 */
exports.chmodSyncRecursive = function(sourceDir, filemode) {
    var files = fs.readdirSync(sourceDir);

    for(var i = 0; i < files.length; i++) {
        var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));

        if(currFile.isDirectory()) {
            /*  ...and recursion this thing right on back. */
            exports.chmodSyncRecursive(_path.join(sourceDir, files[i]), filemode);
        } else {
            /*  At this point, we've hit a file actually worth copying... so copy it on over. */
            fs.chmod(_path.join(sourceDir, files[i]), filemode);
        }
    }

    /*  Finally, chmod the parent directory */
    fs.chmod(sourceDir, filemode);
};

/*  wrench.chownSyncRecursive("directory", uid, gid);
 *
 *  Recursively dives through a directory and chowns everything to the desired user and group. This is a
 *  Synchronous function, which blocks things until it's done.
 *
 *  Note: Directories should be passed to this function without a trailing slash.
 */
exports.chownSyncRecursive = function(sourceDir, uid, gid) {
    var files = fs.readdirSync(sourceDir);

    for(var i = 0; i < files.length; i++) {
        var currFile = fs.lstatSync(_path.join(sourceDir, files[i]));

        if(currFile.isDirectory()) {
            /*  ...and recursion this thing right on back. */
            exports.chownSyncRecursive(_path.join(sourceDir, files[i]), uid, gid);
        } else {
            /*  At this point, we've hit a file actually worth chowning... so own it. */
            fs.chownSync(_path.join(sourceDir, files[i]), uid, gid);
        }
    }

    /*  Finally, chown the parent directory */
    fs.chownSync(sourceDir, uid, gid);
};

/*  wrench.rmdirRecursive("directory_path", callback);
 *
 *  Recursively dives through directories and obliterates everything about it.
 */
exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){
    fs.readdir(dir, function(err, files){
        if(err && typeof failSilent === 'boolean' && !failSilent)
		return clbk(err);

	if(typeof failSilent === 'function')
		clbk = failSilent;

        (function rmFile(err){
            if (err) return clbk(err);

            var filename = files.shift();
            if (filename === null || typeof filename == 'undefined')
                return fs.rmdir(dir, clbk);

            var file = dir+'/'+filename;
            fs.lstat(file, function(err, stat){
                if (err) return clbk(err);
                if (stat.isDirectory())
                    rmdirRecursive(file, rmFile);
                else
                    fs.unlink(file, rmFile);
            });
        })();
    });
};

/*  wrench.copyDirRecursive("directory_to_copy", "new_location", {forceDelete: bool}, callback);
 *
 *  Recursively dives through a directory and moves all its files to a new
 *  location. Specify forceDelete to force directory overwrite.
 *
 *  Note: Directories should be passed to this function without a trailing slash.
 */
exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) {
    var originalArguments = Array.prototype.slice.apply(arguments);
    fs.stat(newDir, function(err, newDirStat){
        if(!err) {
		if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete)
			return exports.rmdirRecursive(newDir, function(err){
				copyDirRecursive.apply(this, originalArguments);
        		});
		else
			return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.'));
	}

	if(typeof opts === 'function')
		clbk = opts;

        fs.stat(srcDir, function(err, srcDirStat){
            if (err) return clbk(err);
            fs.mkdir(newDir, srcDirStat.mode, function(err){
                if (err) return clbk(err);
                fs.readdir(srcDir, function(err, files){
                    if (err) return clbk(err);
                    (function copyFiles(err){
                        if (err) return clbk(err);

                        var filename = files.shift();
                        if (filename === null || typeof filename == 'undefined')
                            return clbk(null);

                        var file = srcDir+'/'+filename,
                            newFile = newDir+'/'+filename;

                        fs.stat(file, function(err, fileStat){
                            if (fileStat.isDirectory())
                                copyDirRecursive(file, newFile, copyFiles);
                            else if (fileStat.isSymbolicLink())
                                fs.readlink(file, function(err, link){
                                    fs.symlink(link, newFile, copyFiles);
                                });
                            else
                                fs.readFile(file, function(err, data){
                                    fs.writeFile(newFile, data, copyFiles);
                                });
                        });
                    })();
                });
            });
        });
    });
};

var mkdirSyncRecursive = function(path, mode) {
    var self = this;
    path = _path.normalize(path)

    try {
        fs.mkdirSync(path, mode);
    } catch(err) {
        if(err.code == "ENOENT") {
            var slashIdx = path.lastIndexOf(_path.sep);

            if(slashIdx > 0) {
                var parentPath = path.substring(0, slashIdx);
                mkdirSyncRecursive(parentPath, mode);
                mkdirSyncRecursive(path, mode);
            } else {
                throw err;
            }
        } else if(err.code == "EEXIST") {
            return;
        } else {
            throw err;
        }
    }
};
exports.mkdirSyncRecursive = mkdirSyncRecursive;

exports.LineReader = function(filename, bufferSize) {
    this.bufferSize = bufferSize || 8192;
    this.buffer = "";
    this.fd = fs.openSync(filename, "r");
    this.currentPosition = 0;
};

exports.LineReader.prototype = {
    close: function() {
        return fs.closeSync(this.fd);
    },

    getBufferAndSetCurrentPosition: function(position) {
        var res = fs.readSync(this.fd, this.bufferSize, position, "ascii");

        this.buffer += res[0];
        if(res[1] === 0) {
            this.currentPosition = -1;
        } else {
            this.currentPosition = position + res[1];
        }

        return this.currentPosition;
    },

    hasNextLine: function() {
        while(this.buffer.indexOf('\n') === -1) {
            this.getBufferAndSetCurrentPosition(this.currentPosition);
            if(this.currentPosition === -1) return false;
        }

        if(this.buffer.indexOf("\n") > -1 || this.buffer.length !== 0) return true;
        return false;
    },

    getNextLine: function() {
        var lineEnd = this.buffer.indexOf("\n"),
            result = this.buffer.substring(0, lineEnd != -1 ? lineEnd : this.buffer.length);

        this.buffer = this.buffer.substring(result.length + 1, this.buffer.length);
        return result;
    }
};

// vim: et ts=4 sw=4
<|endoftext|>


<commit_before>var fs, path, mkdirp;

function toFileName(delimiter, name) {
  if (delimiter === '') {
    return name;
  }

  return name
    .replace(/[a-z][A-Z]/g, function(str) {
      return str[0] + delimiter + str[1];
    })
    .toLowerCase();
}

if (!process.env.NO_WRITE_FS) {
  fs = require('fs');
  path = require('path');
  mkdirp = require('mkdirp');

  function writeToFS(components, options) {
    options = options || {};

    var outPath = options.path || 'components';
    // may want to do smtg different here but this is to ensure that
    // options.path is preserved if absolute
    if (!path.isAbsolute(outPath)) {
      outPath = path.join(process.cwd(), outPath);
    }
    var delimiter = options.moduleFileNameDelimiter || '';
    var ext = options.fileExtension || 'js';

    mkdirp.sync(outPath);

    Object.keys(components).forEach(function(name) {
      fs.writeFileSync(
        path.join(outPath, toFileName(delimiter, name)) + '.' + ext,
        components[name],
        'utf8'
      );
    });
  }

  module.exports = {
    toFileName: toFileName,
    writeToFS: writeToFS
  };
} else {
  module.exports = {
    toFileName: toFileName
  };
}
<commit_msg>use path.resolve<commit_after>var fs, path, mkdirp;

function toFileName(delimiter, name) {
  if (delimiter === '') {
    return name;
  }

  return name
    .replace(/[a-z][A-Z]/g, function(str) {
      return str[0] + delimiter + str[1];
    })
    .toLowerCase();
}

if (!process.env.NO_WRITE_FS) {
  fs = require('fs');
  path = require('path');
  mkdirp = require('mkdirp');

  function writeToFS(components, options) {
    options = options || {};

    var outPath = path.resolve(options.path || 'components');
    var delimiter = options.moduleFileNameDelimiter || '';
    var ext = options.fileExtension || 'js';

    mkdirp.sync(outPath);

    Object.keys(components).forEach(function(name) {
      fs.writeFileSync(
        path.join(outPath, toFileName(delimiter, name)) + '.' + ext,
        components[name],
        'utf8'
      );
    });
  }

  module.exports = {
    toFileName: toFileName,
    writeToFS: writeToFS
  };
} else {
  module.exports = {
    toFileName: toFileName
  };
}
<|endoftext|>


<commit_before>(function () {
   'use strict';
}());

module.exports = {
    // Wrapper to fs.stat to check if a file exists
    exists: function exists(path) {
        var ret = true;

        try {
            var stats = fs.statSync(path);
        }
        catch (e) {
            if (e.errno == 34) {
                ret = false;
            }
        }

        return ret;
    },

    // Makes a directory or directories depending on the path. Splits the path
    // parameter into individual directories and adds each in order.
    mkdir: function mkdir(path) {
        for (var i = 0; i < path.split('/').length; i++) {
            var dir = path.split('/').slice(0, i + 1).join('/');

            try {
                var stats = fs.statSync(dir);
            }
            catch (e) {
                if (e.errno == 34) {
                    fs.mkdirSync(dir);
                }
            }
        }
    }
};
<commit_msg>Fixed missing dependency in libs/tools.js<commit_after>(function () {
   'use strict';
}());

var fs = require('fs');

module.exports = {
    // Wrapper to fs.stat to check if a file exists
    exists: function exists(path) {
        var ret = true;

        try {
            var stats = fs.statSync(path);
        }
        catch (e) {
            if (e.errno == 34) {
                ret = false;
            }
        }

        return ret;
    },

    // Makes a directory or directories depending on the path. Splits the path
    // parameter into individual directories and adds each in order.
    mkdir: function mkdir(path) {
        for (var i = 0; i < path.split('/').length; i++) {
            var dir = path.split('/').slice(0, i + 1).join('/');
            try {
                var stats = fs.statSync(dir);
            }
            catch (e) {
                if (e.errno == 34) {
                    fs.mkdirSync(dir);
                }
            }
        }
    }
};
<|endoftext|>


<commit_before>define([
  'logger',
  'backbone',
  'injector',
  'marionette',
  'vent',
  '#qt_core/controllers/api',
  'commands/index',
  'controllers/nav',
  'controllers/initdata',
  'routers/router',
  'views/layout',
  '#beans/beans',
  "modernizr",
  'fastclick',
  '#qt_core/controllers/config'
],

function (logger, Backbone, injector,Marionette,vent,api,commandoPool,NavController,InitDataController,Router, LayoutView, beans,
  Modernizr, FastClick,Cfg) {
  'use strict';

  //Done
  FastClick.attach(document.body);

  console.error('WARN : mainLocale done in code');
  injector.set(injector.cfg.currentMainLocale,'fr');
  injector.set(injector.cfg.currentSubLocales,[]);

  //A déplacer!!!!
  api.setInterceptEndCallFunction(function(res) {
    try {

      var csrfToken = res.xhr.getResponseHeader("X-CSRF-TOKEN");
      if (csrfToken) {
        //console.log("Ok CSRF : "+csrfToken);
        injector.set(injector.cfg.csrfToken,csrfToken);
        var apiController = injector.get(injector.cfg.apiController);
        apiController.removeHeader("X-CSRF-TOKEN");
        apiController.addHeader("X-CSRF-TOKEN",csrfToken);
      }
      else {
        console.log('No CSRF Token?');
      }
    }
    catch (e) {
      console.error("error while catching end call XHR : "+(e ? JSON.stringify(e) : "NULL?"));
    }
  });

  //end déplacer
  var app = new Marionette.Application();

  app.addInitializer(function () {
    this.commandoPool = commandoPool;

    //temp eric : trace when error
    this.commandoPool.commandError =function(error) {
      console.log('Error : '+error);
      if (error.stack)
        console.log(error.stack);
    };

    window.quemaInjector = injector;
    window.quemaVent = vent;

    injector.set(injector.config['commando.pool'], commandoPool);

    this.apiController = api;
    injector.set(injector.config.api, api.api);
    injector.set(injector.config.apiController, api);

  });

  return app;
});
<commit_msg>Fix improper CSRF token request<commit_after>define([
  'logger',
  'backbone',
  'injector',
  'marionette',
  'vent',
  '#qt_core/controllers/api',
  'commands/index',
  'controllers/nav',
  'controllers/initdata',
  'routers/router',
  'views/layout',
  '#beans/beans',
  "modernizr",
  'fastclick',
  '#qt_core/controllers/config'
],

function (logger, Backbone, injector,Marionette,vent,api,commandoPool,NavController,InitDataController,Router, LayoutView, beans,
  Modernizr, FastClick,Cfg) {
  'use strict';

  //Done
  FastClick.attach(document.body);

  console.error('WARN : mainLocale done in code');
  injector.set(injector.cfg.currentMainLocale,'fr');
  injector.set(injector.cfg.currentSubLocales,[]);

  //A déplacer!!!!
  api.setInterceptEndCallFunction(function(res) {
    try {

      // Get CSRF Token value from Cookie using jQuery
      function getCookie(name) {
          var cookieValue = null;
          if (document.cookie && document.cookie !== '') {
              var cookies = document.cookie.split(';');
              for (var i = 0; i < cookies.length; i++) {
                  var cookie = jQuery.trim(cookies[i]);
                  // Does this cookie string begin with the name we want?
                  if (cookie.substring(0, name.length + 1) === (name + '=')) {
                      cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                      break;
                  }
              }
          }
          return cookieValue;
      }
      var csrfToken = getCookie('csrftoken');
      //var csrfToken = res.xhr.getResponseHeader("X-CSRF-TOKEN");
      if (csrfToken) {
        //console.log("Ok CSRF : "+csrfToken);
        injector.set(injector.cfg.csrfToken,csrfToken);
        var apiController = injector.get(injector.cfg.apiController);
        apiController.removeHeader("X-CSRF-TOKEN");
        apiController.addHeader("X-CSRF-TOKEN",csrfToken);
      }
      else {
        console.log('No CSRF Token?');
      }
    }
    catch (e) {
      console.error("error while catching end call XHR : "+(e ? JSON.stringify(e) : "NULL?"));
    }
  });

  //end déplacer
  var app = new Marionette.Application();

  app.addInitializer(function () {
    this.commandoPool = commandoPool;

    //temp eric : trace when error
    this.commandoPool.commandError =function(error) {
      console.log('Error : '+error);
      if (error.stack)
        console.log(error.stack);
    };

    window.quemaInjector = injector;
    window.quemaVent = vent;

    injector.set(injector.config['commando.pool'], commandoPool);

    this.apiController = api;
    injector.set(injector.config.api, api.api);
    injector.set(injector.config.apiController, api);

  });

  return app;
});
<|endoftext|>


<commit_before>/**
 * Component for rendering the connection indicators as an svg images, with unread count and select handle on the latest (possibly unread) connnectionuri
 * Created by fsuda on 10.04.2017.
 */
import angular from 'angular';
import won from '../won-es6.js';
import 'ng-redux';
import { labels, } from '../won-label-utils.js';
import { actionCreators }  from '../actions/actions.js';
import {
    selectAllOwnNeeds,
} from '../selectors.js';

import {
    attach,
    sortByDate,
} from '../utils.js'
import {
    connect2Redux,
} from '../won-utils.js'

const serviceDependencies = ['$ngRedux', '$scope'];
function genComponentConf() {
    let template = `

                <svg class="indicators__item__icon"
                    title="Show latest message/request"
                    style="--local-primary:#F09F9F;"
                    ng-show="!self.unreadConnectedCount">
                        <use href="#ico36_message"></use>
                </svg>

                <svg style="--local-primary:var(--won-primary-color);"
                     title="Show latest unread message/request"
                     ng-show="self.unreadConnectedCount"
                     class="indicators__item__icon">
                        <use href="#ico36_message"></use>
                </svg>

                    {{ self.getCountLimited(self.unreadConnectedCount)}}

            <svg class="indicators__item__icon"
                style="--local-primary:var(--won-disabled-color);">
                    <use href="#ico36_message"></use>
            </svg>

                <svg class="indicators__item__icon"
                    style="--local-primary:var(--won-primary-color-light);"
                    ng-show="!self.unreadMatchesCount">
                        <use href="#ico36_match"></use>
                </svg>

                <svg style="--local-primary:var(--won-primary-color);"
                    ng-show="self.unreadMatchesCount"
                    class="indicators__item__icon">
                        <use href="#ico36_match"></use>
                </svg>

                    {{ self.getCountLimited(self.unreadMatchesCount) }}

            <svg class="indicators__item__icon"
                style="--local-primary:var(--won-disabled-color);">
                    <use href="#ico36_match"></use>
            </svg>

        {{ self.getCountLimited(self.unreadCountSum) }}
    `;

    class Controller {
        constructor() {
            attach(this, serviceDependencies, arguments);
            this.labels = labels;

            const selectFromState = (state) => {
                const ownNeeds = selectAllOwnNeeds(state);
                const need = ownNeeds && ownNeeds.get(this.needUri);
                const allConnectionsByNeedUri = need && need.get("connections");

                const matches = allConnectionsByNeedUri && allConnectionsByNeedUri.filter(conn => conn.get("state") === won.WON.Suggested);
                const connected = allConnectionsByNeedUri && allConnectionsByNeedUri.filter(conn => conn.get("state") !== won.WON.Suggested && conn.get("state") !== won.WON.Closed);

                const unreadMatches = matches && matches.filter(conn => conn.get("unread"));
                const unreadConversations = connected && connected.filter(conn => conn.get("unread"));

                const unreadMatchesCount = unreadMatches && unreadMatches.size;
                const unreadConnectedCount = unreadConversations && unreadConversations.size;

                const sortedUnreadMatches = sortByDate(unreadMatches);
                const sortedUnreadConversations = sortByDate(unreadConversations);

                const unreadCountSum = unreadConnectedCount + unreadMatchesCount;

                return {
                    WON: won.WON,
                    need,
                    unreadCountSum: unreadCountSum > 0 ? unreadCountSum: undefined,
                    unreadConnectedCount: unreadConnectedCount > 0 ? unreadConnectedCount : undefined,
                    unreadMatchesCount: unreadMatchesCount > 0 ? unreadMatchesCount : undefined,
                    latestConnectedUri: this.retrieveLatestUri(connected),
                    latestMatchUri: this.retrieveLatestUri(matches),
                }
            };

            connect2Redux(
                selectFromState, actionCreators,
                ['self.needUri'],
                this
            );
        }

        /**
         * This method returns either the latest unread uri of the given connection elements, or the latest uri of a read connection, if nothing is found undefined is returned
         * @param elements connection elements to retrieve the latest uri from
         * @returns {*}
         */
        retrieveLatestUri(elements) {
            const unreadElements = elements && elements.filter(conn => conn.get("unread"));

            const sortedUnreadElements = sortByDate(unreadElements);
            const unreadUri = sortedUnreadElements && sortedUnreadElements[0] && sortedUnreadElements[0].get("uri");

            if(unreadUri){
                return unreadUri;
            }else{
                const sortedElements = sortByDate(elements);
                return sortedElements && sortedElements[0] && sortedElements[0].get("uri");
            }
        }

        setOpen(connectionUri) {
            this.onSelectedConnection({connectionUri: connectionUri}); //trigger callback with scope-object
            //TODO either publish a dom-event as well; or directly call the route-change
        }

        getCountLimited(count , threshold = 100) {
            return count < threshold ? count : (threshold-1)+"+";
        }
    }
    Controller.$inject = serviceDependencies;
    return {
        restrict: 'E',
        controller: Controller,
        controllerAs: 'self',
        bindToController: true, //scope-bindings -> ctrl
        scope: {
            needUri: '=',
            onSelectedConnection: "&",
        },
        template: template
    }
}

export default angular.module('won.owner.components.connectionIndicators', [
])
    .directive('wonConnectionIndicators', genComponentConf)
    .name;
<commit_msg>add parentheses just in case<commit_after>/**
 * Component for rendering the connection indicators as an svg images, with unread count and select handle on the latest (possibly unread) connnectionuri
 * Created by fsuda on 10.04.2017.
 */
import angular from 'angular';
import won from '../won-es6.js';
import 'ng-redux';
import { labels, } from '../won-label-utils.js';
import { actionCreators }  from '../actions/actions.js';
import {
    selectAllOwnNeeds,
} from '../selectors.js';

import {
    attach,
    sortByDate,
} from '../utils.js'
import {
    connect2Redux,
} from '../won-utils.js'

const serviceDependencies = ['$ngRedux', '$scope'];
function genComponentConf() {
    let template = `

                <svg class="indicators__item__icon"
                    title="Show latest message/request"
                    style="--local-primary:#F09F9F;"
                    ng-show="!self.unreadConnectedCount">
                        <use href="#ico36_message"></use>
                </svg>

                <svg style="--local-primary:var(--won-primary-color);"
                     title="Show latest unread message/request"
                     ng-show="self.unreadConnectedCount"
                     class="indicators__item__icon">
                        <use href="#ico36_message"></use>
                </svg>

                    {{ self.getCountLimited(self.unreadConnectedCount)}}

            <svg class="indicators__item__icon"
                style="--local-primary:var(--won-disabled-color);">
                    <use href="#ico36_message"></use>
            </svg>

                <svg class="indicators__item__icon"
                    style="--local-primary:var(--won-primary-color-light);"
                    ng-show="!self.unreadMatchesCount">
                        <use href="#ico36_match"></use>
                </svg>

                <svg style="--local-primary:var(--won-primary-color);"
                    ng-show="self.unreadMatchesCount"
                    class="indicators__item__icon">
                        <use href="#ico36_match"></use>
                </svg>

                    {{ self.getCountLimited(self.unreadMatchesCount) }}

            <svg class="indicators__item__icon"
                style="--local-primary:var(--won-disabled-color);">
                    <use href="#ico36_match"></use>
            </svg>

        {{ self.getCountLimited(self.unreadCountSum) }}
    `;

    class Controller {
        constructor() {
            attach(this, serviceDependencies, arguments);
            this.labels = labels;

            const selectFromState = (state) => {
                const ownNeeds = selectAllOwnNeeds(state);
                const need = ownNeeds && ownNeeds.get(this.needUri);
                const allConnectionsByNeedUri = need && need.get("connections");

                const matches = allConnectionsByNeedUri && allConnectionsByNeedUri.filter(conn => conn.get("state") === won.WON.Suggested);
                const connected = allConnectionsByNeedUri && allConnectionsByNeedUri.filter(conn => conn.get("state") !== won.WON.Suggested && conn.get("state") !== won.WON.Closed);

                const unreadMatches = matches && matches.filter(conn => conn.get("unread"));
                const unreadConversations = connected && connected.filter(conn => conn.get("unread"));

                const unreadMatchesCount = unreadMatches && unreadMatches.size;
                const unreadConnectedCount = unreadConversations && unreadConversations.size;

                const sortedUnreadMatches = sortByDate(unreadMatches);
                const sortedUnreadConversations = sortByDate(unreadConversations);

                const unreadCountSum = unreadConnectedCount + unreadMatchesCount;

                return {
                    WON: won.WON,
                    need,
                    unreadCountSum: unreadCountSum > 0 ? unreadCountSum: undefined,
                    unreadConnectedCount: unreadConnectedCount > 0 ? unreadConnectedCount : undefined,
                    unreadMatchesCount: unreadMatchesCount > 0 ? unreadMatchesCount : undefined,
                    latestConnectedUri: this.retrieveLatestUri(connected),
                    latestMatchUri: this.retrieveLatestUri(matches),
                }
            };

            connect2Redux(
                selectFromState, actionCreators,
                ['self.needUri'],
                this
            );
        }

        /**
         * This method returns either the latest unread uri of the given connection elements, or the latest uri of a read connection, if nothing is found undefined is returned
         * @param elements connection elements to retrieve the latest uri from
         * @returns {*}
         */
        retrieveLatestUri(elements) {
            const unreadElements = elements && elements.filter(conn => conn.get("unread"));

            const sortedUnreadElements = sortByDate(unreadElements);
            const unreadUri = sortedUnreadElements && sortedUnreadElements[0] && sortedUnreadElements[0].get("uri");

            if(unreadUri){
                return unreadUri;
            }else{
                const sortedElements = sortByDate(elements);
                return sortedElements && sortedElements[0] && sortedElements[0].get("uri");
            }
        }

        setOpen(connectionUri) {
            this.onSelectedConnection({connectionUri: connectionUri}); //trigger callback with scope-object
            //TODO either publish a dom-event as well; or directly call the route-change
        }

        getCountLimited(count , threshold = 100) {
            return (count < threshold) ? count : ((threshold-1)+"+");
        }
    }
    Controller.$inject = serviceDependencies;
    return {
        restrict: 'E',
        controller: Controller,
        controllerAs: 'self',
        bindToController: true, //scope-bindings -> ctrl
        scope: {
            needUri: '=',
            onSelectedConnection: "&",
        },
        template: template
    }
}

export default angular.module('won.owner.components.connectionIndicators', [
])
    .directive('wonConnectionIndicators', genComponentConf)
    .name;
<|endoftext|>


<commit_before>import Immutable from "immutable";
import won from "../../won-es6.js";

export function parseNeed(jsonldNeed, ownNeed) {
  const jsonldNeedImm = Immutable.fromJS(jsonldNeed);

  let parsedNeed = {
    uri: undefined,
    nodeUri: undefined,
    title: undefined,
    type: undefined,
    state: undefined,
    connections: Immutable.Map(),
    creationDate: undefined,
    lastUpdateDate: undefined,
    unread: false,
    ownNeed: !!ownNeed,
    isBeingCreated: false,
    isWhatsAround: false,
    isWhatsNew: false,
    matchingContexts: undefined,
    jsonld: jsonldNeed,
  };

  if (jsonldNeedImm) {
    const uri = jsonldNeedImm.get("@id");
    const nodeUri = jsonldNeedImm.getIn(["won:hasWonNode", "@id"]);
    const isPresent = !!jsonldNeedImm.getIn(["won:is", "dc:title"]);
    const seeksPresent = !!jsonldNeedImm.getIn(["won:seeks", "dc:title"]);
    const is = jsonldNeedImm.get("won:is");
    const seeks = jsonldNeedImm.get("won:seeks");

    //TODO We need to decide which is the main title? Or combine?
    const title = isPresent
      ? is.get("dc:title")
      : seeksPresent
        ? seeks.get("dc:title")
        : undefined;
    parsedNeed.title = title;

    if (uri) {
      parsedNeed.uri = uri;
    } else {
      return undefined;
    }

    /*
         * The following code-snippet is solely to determine if the parsed need
         * is a special "whats around"-need, in order to do this we have to make
         * sure that the won:hasFlag is checked in two forms, both as a string
         * and an immutable object
         */
    const wonHasFlags = jsonldNeedImm.get("won:hasFlag");
    const isWhatsAround =
      wonHasFlags &&
      wonHasFlags.filter(function(flag) {
        if (flag instanceof Immutable.Map) {
          return flag.get("@id") === "won:WhatsAround";
        } else {
          return flag === "won:WhatsAround";
        }
      }).size > 0;

    const isWhatsNew =
      wonHasFlags &&
      wonHasFlags.filter(function(flag) {
        if (flag instanceof Immutable.Map) {
          return flag.get("@id") === "won:WhatsNew";
        } else {
          return flag === "won:WhatsNew";
        }
      }).size > 0;

    const wonHasMatchingContexts = jsonldNeedImm.get("won:hasMatchingContext");

    const creationDate =
      jsonldNeedImm.get("dct:created") ||
      jsonldNeedImm.get("http://purl.org/dc/terms/created");
    if (creationDate) {
      parsedNeed.creationDate = new Date(creationDate);
      parsedNeed.lastUpdateDate = parsedNeed.creationDate;
    }

    const state = jsonldNeedImm.getIn([won.WON.isInStateCompacted, "@id"]);
    if (state === won.WON.ActiveCompacted) {
      // we use to check for active
      // state and everything else
      // will be inactive
      parsedNeed.state = state;
    } else {
      parsedNeed.state = won.WON.InactiveCompacted;
    }

    let isPart = undefined;
    let seeksPart = undefined;
    let type = undefined;

    /*
         let description = undefined;
         let tags = undefined;
         let location = undefined;
         */
    //TODO: Type concept?
    if (isPresent) {
      type = seeksPresent
        ? won.WON.BasicNeedTypeCombinedCompacted
        : won.WON.BasicNeedTypeSupplyCompacted;
      let tags = is.get("won:hasTag") ? is.get("won:hasTag") : undefined;
      isPart = {
        title: is.get("dc:title"),
        type: type,
        description: is.get("dc:description")
          ? is.get("dc:description")
          : undefined,
        tags: tags
          ? Immutable.List.isList(tags)
            ? tags
            : Immutable.List.of(tags)
          : undefined,
        person: parsePerson(is),
        location: is.get("won:hasLocation")
          ? parseLocation(is.get("won:hasLocation"))
          : undefined,
        travelAction: is.get("won:travelAction")
          ? parseTravelAction(is.get("won:travelAction"))
          : undefined,
      };
    }
    if (seeksPresent) {
      type = isPresent ? type : won.WON.BasicNeedTypeDemandCompacted;
      let tags = seeks.get("won:hasTag") ? seeks.get("won:hasTag") : undefined;
      seeksPart = {
        title: seeks.get("dc:title"),
        type: type,
        description: seeks.get("dc:description")
          ? seeks.get("dc:description")
          : undefined,
        searchString: seeks.get("won:hasSearchString")
          ? seeks.get("won:hasSearchString")
          : undefined,
        tags: tags
          ? Immutable.List.isList(tags)
            ? tags
            : Immutable.List.of(tags)
          : undefined,
        person: parsePerson(seeks),
        location: seeks.get("won:hasLocation")
          ? parseLocation(seeks.get("won:hasLocation"))
          : undefined,
        travelAction: seeks.get("won:travelAction")
          ? parseTravelAction(seeks.get("won:travelAction"))
          : undefined,
      };
    }

    parsedNeed.is = isPart;
    parsedNeed.seeks = seeksPart;

    if (isWhatsAround) {
      parsedNeed.type = won.WON.BasicNeedTypeWhatsAroundCompacted;
    } else if (isWhatsNew) {
      parsedNeed.type = won.WON.BasicNeedTypeWhatsNewCompacted;
    } else {
      parsedNeed.type = type;
    }

    parsedNeed.isWhatsAround = !!isWhatsAround;
    parsedNeed.isWhatsNew = !!isWhatsNew;
    parsedNeed.matchingContexts = wonHasMatchingContexts
      ? Immutable.List.isList(wonHasMatchingContexts)
        ? wonHasMatchingContexts
        : Immutable.List.of(wonHasMatchingContexts)
      : undefined;
    parsedNeed.nodeUri = nodeUri;
  } else {
    console.error(
      "Cant parse need, data is an invalid need-object: ",
      jsonldNeedImm && jsonldNeedImm.toJS()
    );
    return undefined;
  }

  return Immutable.fromJS(parsedNeed);
}

function parsePerson(isOrSeeks) {
  if (!isOrSeeks) return undefined;

  const isOrSeeksImm = Immutable.fromJS(isOrSeeks);

  let person = {
    name: undefined,
    title: undefined,
    company: undefined,
    position: undefined,
    skills: undefined,
    // bio: undefined,
  };

  person.name = isOrSeeksImm.get("foaf:name");
  person.title = isOrSeeksImm.get("foaf:title");
  person.company = isOrSeeksImm.get("s:worksFor");
  person.position = isOrSeeksImm.get("s:jobTitle");
  person.skills = isOrSeeksImm.get("s:knowsAbout")
    ? Immutable.List.isList(isOrSeeksImm.get("s:knowsAbout"))
      ? isOrSeeksImm.get("s:knowsAbout")
      : Immutable.List.of(isOrSeeksImm.get("s:knowsAbout"))
    : undefined;
  //person.bio = isOrSeeksImm.get("dc:description");

  // if there's anything, use it
  if (
    person.name ||
    person.title ||
    person.company ||
    person.position ||
    person.skills
  ) {
    return Immutable.fromJS(person);
  }

  // console.error(
  //   "Cant parse person, data does not contain enough information: ",
  //   isOrSeeksImm.toJS()
  // );
  return undefined;
}

function parseLocation(jsonldLocation) {
  if (!jsonldLocation) return undefined; // NO LOCATION PRESENT

  const jsonldLocationImm = Immutable.fromJS(jsonldLocation);

  let location = {
    address: undefined,
    lat: undefined,
    lng: undefined,
    nwCorner: {
      lat: undefined,
      lng: undefined,
    },
    seCorner: {
      lat: undefined,
      lng: undefined,
    },
  };

  location.address =
    jsonldLocationImm.get("s:name") ||
    jsonldLocationImm.get("http://schema.org/name");

  location.lat = Number.parseFloat(
    jsonldLocationImm.getIn(["s:geo", "s:latitude"]) ||
      jsonldLocationImm.getIn([
        "http://schema.org/geo",
        "http://schema.org/latitude",
      ])
  );
  location.lng = Number.parseFloat(
    jsonldLocationImm.getIn(["s:geo", "s:longitude"]) ||
      jsonldLocationImm.getIn([
        "http://schema.org/geo",
        "http://schema.org/longitude",
      ])
  );

  location.nwCorner.lat = Number.parseFloat(
    jsonldLocationImm.getIn([
      "won:hasBoundingBox",
      "won:hasNorthWestCorner",
      "s:latitude",
    ]) ||
      jsonldLocationImm.getIn([
        "won:hasBoundingBox",
        "won:hasNorthWestCorner",
        "http://schema.org/latitude",
      ])
  );
  location.nwCorner.lng = Number.parseFloat(
    jsonldLocationImm.getIn([
      "won:hasBoundingBox",
      "won:hasNorthWestCorner",
      "s:longitude",
    ]) ||
      jsonldLocationImm.getIn([
        "won:hasBoundingBox",
        "won:hasNorthWestCorner",
        "http://schema.org/longitude",
      ])
  );
  location.seCorner.lat = Number.parseFloat(
    jsonldLocationImm.getIn([
      "won:hasBoundingBox",
      "won:hasSouthEastCorner",
      "s:latitude",
    ]) ||
      jsonldLocationImm.getIn([
        "won:hasBoundingBox",
        "won:hasSouthEastCorner",
        "http://schema.org/latitude",
      ])
  );
  location.seCorner.lng = Number.parseFloat(
    jsonldLocationImm.getIn([
      "won:hasBoundingBox",
      "won:hasSouthEastCorner",
      "s:longitude",
    ]) ||
      jsonldLocationImm.getIn([
        "won:hasBoundingBox",
        "won:hasSouthEastCorner",
        "http://schema.org/longitude",
      ])
  );

  if (
    location.address &&
    location.lat &&
    location.lng &&
    location.nwCorner.lat &&
    location.nwCorner.lng &&
    location.seCorner.lat &&
    location.seCorner.lng
  ) {
    return Immutable.fromJS(location);
  }

  console.error(
    "Cant parse location, data is an invalid location-object: ",
    jsonldLocationImm.toJS()
  );
  return undefined;
}

function parseTravelAction(jsonTravelAction) {
  if (!jsonTravelAction) return undefined;

  const travelActionImm = Immutable.fromJS(jsonTravelAction);

  let travelAction = {
    fromAddress: undefined,
    fromLocation: {
      lat: undefined,
      lng: undefined,
    },
    toAddress: undefined,
    toLocation: {
      lat: undefined,
      lng: undefined,
    },
  };

  travelAction.fromAddress =
    travelActionImm.getIn(["s:fromLocation", "s:name"]) ||
    travelActionImm.getIn([
      "http://schema.org/fromLocation",
      "http://schema.org/name",
    ]);

  travelAction.fromLocation.lat =
    travelActionImm.getIn(["s:fromLocation", "s:geo", "s:latitude"]) ||
    travelActionImm.getIn([
      "http://schema.org/fromLocation",
      "http://schema.org/geo",
      "http://schema.org/latitude",
    ]);

  travelAction.fromLocation.lng =
    travelActionImm.getIn(["s:fromLocation", "s:geo", "s:longitude"]) ||
    travelActionImm.getIn([
      "http://schema.org/fromLocation",
      "http://schema.org/geo",
      "http://schema.org/longitude",
    ]);

  travelAction.toAddress =
    travelActionImm.getIn(["s:toLocation", "s:name"]) ||
    travelActionImm.getIn([
      "http://schema.org/toLocation",
      "http://schema.org/name",
    ]);

  travelAction.toLocation.lat =
    travelActionImm.getIn(["s:toLocation", "s:geo", "s:latitude"]) ||
    travelActionImm.getIn([
      "http://schema.org/toLocation",
      "http://schema.org/geo",
      "http://schema.org/latitude",
    ]);

  travelAction.toLocation.lng =
    travelActionImm.getIn(["s:toLocation", "s:geo", "s:longitude"]) ||
    travelActionImm.getIn([
      "http://schema.org/toLocation",
      "http://schema.org/geo",
      "http://schema.org/longitude",
    ]);

  if (
    (travelAction.fromAddress &&
      travelAction.fromLocation.lat &&
      travelAction.fromLocation.lng) ||
    (travelAction.toAddress &&
      travelAction.toLocation.lat &&
      travelAction.toLocation.lng)
  ) {
    return Immutable.fromJS(travelAction);
  }

  console.error(
    "Cant parse travelAction, data is an invalid travelAction-object: ",
    travelActionImm.toJS()
  );
}
<commit_msg>Working on title-placeholders.<commit_after>import Immutable from "immutable";
import won from "../../won-es6.js";

export function parseNeed(jsonldNeed, ownNeed) {
  const jsonldNeedImm = Immutable.fromJS(jsonldNeed);

  let parsedNeed = {
    uri: undefined,
    nodeUri: undefined,
    title: undefined,
    type: undefined,
    state: undefined,
    connections: Immutable.Map(),
    creationDate: undefined,
    lastUpdateDate: undefined,
    unread: false,
    ownNeed: !!ownNeed,
    isBeingCreated: false,
    isWhatsAround: false,
    isWhatsNew: false,
    matchingContexts: undefined,
    jsonld: jsonldNeed,
  };

  if (jsonldNeedImm) {
    const uri = jsonldNeedImm.get("@id");
    const nodeUri = jsonldNeedImm.getIn(["won:hasWonNode", "@id"]);
    const isPresent = !!jsonldNeedImm.getIn(["won:is", "dc:title"]);
    const seeksPresent = !!jsonldNeedImm.getIn(["won:seeks", "dc:title"]);
    const is = jsonldNeedImm.get("won:is");
    const seeks = jsonldNeedImm.get("won:seeks");

    //TODO We need to decide which is the main title? Or combine?
    const title = isPresent
      ? is.get("dc:title")
      : seeksPresent
        ? seeks.get("dc:title")
        : undefined;

    if (uri) {
      parsedNeed.uri = uri;
      parsedNeed.title = title || `post:${uri.slice(-12)}`; // "<no title>"; // `<${uri}>`; //`<post …${uri.slice(-13)}>`;
    } else {
      return undefined;
    }

    /*
         * The following code-snippet is solely to determine if the parsed need
         * is a special "whats around"-need, in order to do this we have to make
         * sure that the won:hasFlag is checked in two forms, both as a string
         * and an immutable object
         */
    const wonHasFlags = jsonldNeedImm.get("won:hasFlag");
    const isWhatsAround =
      wonHasFlags &&
      wonHasFlags.filter(function(flag) {
        if (flag instanceof Immutable.Map) {
          return flag.get("@id") === "won:WhatsAround";
        } else {
          return flag === "won:WhatsAround";
        }
      }).size > 0;

    const isWhatsNew =
      wonHasFlags &&
      wonHasFlags.filter(function(flag) {
        if (flag instanceof Immutable.Map) {
          return flag.get("@id") === "won:WhatsNew";
        } else {
          return flag === "won:WhatsNew";
        }
      }).size > 0;

    const wonHasMatchingContexts = jsonldNeedImm.get("won:hasMatchingContext");

    const creationDate =
      jsonldNeedImm.get("dct:created") ||
      jsonldNeedImm.get("http://purl.org/dc/terms/created");
    if (creationDate) {
      parsedNeed.creationDate = new Date(creationDate);
      parsedNeed.lastUpdateDate = parsedNeed.creationDate;
    }

    const state = jsonldNeedImm.getIn([won.WON.isInStateCompacted, "@id"]);
    if (state === won.WON.ActiveCompacted) {
      // we use to check for active
      // state and everything else
      // will be inactive
      parsedNeed.state = state;
    } else {
      parsedNeed.state = won.WON.InactiveCompacted;
    }

    let isPart = undefined;
    let seeksPart = undefined;
    let type = undefined;

    /*
         let description = undefined;
         let tags = undefined;
         let location = undefined;
         */
    //TODO: Type concept?
    if (isPresent) {
      type = seeksPresent
        ? won.WON.BasicNeedTypeCombinedCompacted
        : won.WON.BasicNeedTypeSupplyCompacted;
      let tags = is.get("won:hasTag") ? is.get("won:hasTag") : undefined;
      isPart = {
        title: is.get("dc:title"),
        type: type,
        description: is.get("dc:description")
          ? is.get("dc:description")
          : undefined,
        tags: tags
          ? Immutable.List.isList(tags)
            ? tags
            : Immutable.List.of(tags)
          : undefined,
        person: parsePerson(is),
        location: is.get("won:hasLocation")
          ? parseLocation(is.get("won:hasLocation"))
          : undefined,
        travelAction: is.get("won:travelAction")
          ? parseTravelAction(is.get("won:travelAction"))
          : undefined,
      };
    }
    if (seeksPresent) {
      type = isPresent ? type : won.WON.BasicNeedTypeDemandCompacted;
      let tags = seeks.get("won:hasTag") ? seeks.get("won:hasTag") : undefined;
      seeksPart = {
        title: seeks.get("dc:title"),
        type: type,
        description: seeks.get("dc:description")
          ? seeks.get("dc:description")
          : undefined,
        searchString: seeks.get("won:hasSearchString")
          ? seeks.get("won:hasSearchString")
          : undefined,
        tags: tags
          ? Immutable.List.isList(tags)
            ? tags
            : Immutable.List.of(tags)
          : undefined,
        person: parsePerson(seeks),
        location: seeks.get("won:hasLocation")
          ? parseLocation(seeks.get("won:hasLocation"))
          : undefined,
        travelAction: seeks.get("won:travelAction")
          ? parseTravelAction(seeks.get("won:travelAction"))
          : undefined,
      };
    }

    parsedNeed.is = isPart;
    parsedNeed.seeks = seeksPart;

    if (isWhatsAround) {
      parsedNeed.type = won.WON.BasicNeedTypeWhatsAroundCompacted;
    } else if (isWhatsNew) {
      parsedNeed.type = won.WON.BasicNeedTypeWhatsNewCompacted;
    } else {
      parsedNeed.type = type;
    }

    parsedNeed.isWhatsAround = !!isWhatsAround;
    parsedNeed.isWhatsNew = !!isWhatsNew;
    parsedNeed.matchingContexts = wonHasMatchingContexts
      ? Immutable.List.isList(wonHasMatchingContexts)
        ? wonHasMatchingContexts
        : Immutable.List.of(wonHasMatchingContexts)
      : undefined;
    parsedNeed.nodeUri = nodeUri;
  } else {
    console.error(
      "Cant parse need, data is an invalid need-object: ",
      jsonldNeedImm && jsonldNeedImm.toJS()
    );
    return undefined;
  }

  return Immutable.fromJS(parsedNeed);
}

function parsePerson(isOrSeeks) {
  if (!isOrSeeks) return undefined;

  const isOrSeeksImm = Immutable.fromJS(isOrSeeks);

  let person = {
    name: undefined,
    title: undefined,
    company: undefined,
    position: undefined,
    skills: undefined,
    // bio: undefined,
  };

  person.name = isOrSeeksImm.get("foaf:name");
  person.title = isOrSeeksImm.get("foaf:title");
  person.company = isOrSeeksImm.get("s:worksFor");
  person.position = isOrSeeksImm.get("s:jobTitle");
  person.skills = isOrSeeksImm.get("s:knowsAbout")
    ? Immutable.List.isList(isOrSeeksImm.get("s:knowsAbout"))
      ? isOrSeeksImm.get("s:knowsAbout")
      : Immutable.List.of(isOrSeeksImm.get("s:knowsAbout"))
    : undefined;
  //person.bio = isOrSeeksImm.get("dc:description");

  // if there's anything, use it
  if (
    person.name ||
    person.title ||
    person.company ||
    person.position ||
    person.skills
  ) {
    return Immutable.fromJS(person);
  }

  // console.error(
  //   "Cant parse person, data does not contain enough information: ",
  //   isOrSeeksImm.toJS()
  // );
  return undefined;
}

function parseLocation(jsonldLocation) {
  if (!jsonldLocation) return undefined; // NO LOCATION PRESENT

  const jsonldLocationImm = Immutable.fromJS(jsonldLocation);

  let location = {
    address: undefined,
    lat: undefined,
    lng: undefined,
    nwCorner: {
      lat: undefined,
      lng: undefined,
    },
    seCorner: {
      lat: undefined,
      lng: undefined,
    },
  };

  location.address =
    jsonldLocationImm.get("s:name") ||
    jsonldLocationImm.get("http://schema.org/name");

  location.lat = Number.parseFloat(
    jsonldLocationImm.getIn(["s:geo", "s:latitude"]) ||
      jsonldLocationImm.getIn([
        "http://schema.org/geo",
        "http://schema.org/latitude",
      ])
  );
  location.lng = Number.parseFloat(
    jsonldLocationImm.getIn(["s:geo", "s:longitude"]) ||
      jsonldLocationImm.getIn([
        "http://schema.org/geo",
        "http://schema.org/longitude",
      ])
  );

  location.nwCorner.lat = Number.parseFloat(
    jsonldLocationImm.getIn([
      "won:hasBoundingBox",
      "won:hasNorthWestCorner",
      "s:latitude",
    ]) ||
      jsonldLocationImm.getIn([
        "won:hasBoundingBox",
        "won:hasNorthWestCorner",
        "http://schema.org/latitude",
      ])
  );
  location.nwCorner.lng = Number.parseFloat(
    jsonldLocationImm.getIn([
      "won:hasBoundingBox",
      "won:hasNorthWestCorner",
      "s:longitude",
    ]) ||
      jsonldLocationImm.getIn([
        "won:hasBoundingBox",
        "won:hasNorthWestCorner",
        "http://schema.org/longitude",
      ])
  );
  location.seCorner.lat = Number.parseFloat(
    jsonldLocationImm.getIn([
      "won:hasBoundingBox",
      "won:hasSouthEastCorner",
      "s:latitude",
    ]) ||
      jsonldLocationImm.getIn([
        "won:hasBoundingBox",
        "won:hasSouthEastCorner",
        "http://schema.org/latitude",
      ])
  );
  location.seCorner.lng = Number.parseFloat(
    jsonldLocationImm.getIn([
      "won:hasBoundingBox",
      "won:hasSouthEastCorner",
      "s:longitude",
    ]) ||
      jsonldLocationImm.getIn([
        "won:hasBoundingBox",
        "won:hasSouthEastCorner",
        "http://schema.org/longitude",
      ])
  );

  if (
    location.address &&
    location.lat &&
    location.lng &&
    location.nwCorner.lat &&
    location.nwCorner.lng &&
    location.seCorner.lat &&
    location.seCorner.lng
  ) {
    return Immutable.fromJS(location);
  }

  console.error(
    "Cant parse location, data is an invalid location-object: ",
    jsonldLocationImm.toJS()
  );
  return undefined;
}

function parseTravelAction(jsonTravelAction) {
  if (!jsonTravelAction) return undefined;

  const travelActionImm = Immutable.fromJS(jsonTravelAction);

  let travelAction = {
    fromAddress: undefined,
    fromLocation: {
      lat: undefined,
      lng: undefined,
    },
    toAddress: undefined,
    toLocation: {
      lat: undefined,
      lng: undefined,
    },
  };

  travelAction.fromAddress =
    travelActionImm.getIn(["s:fromLocation", "s:name"]) ||
    travelActionImm.getIn([
      "http://schema.org/fromLocation",
      "http://schema.org/name",
    ]);

  travelAction.fromLocation.lat =
    travelActionImm.getIn(["s:fromLocation", "s:geo", "s:latitude"]) ||
    travelActionImm.getIn([
      "http://schema.org/fromLocation",
      "http://schema.org/geo",
      "http://schema.org/latitude",
    ]);

  travelAction.fromLocation.lng =
    travelActionImm.getIn(["s:fromLocation", "s:geo", "s:longitude"]) ||
    travelActionImm.getIn([
      "http://schema.org/fromLocation",
      "http://schema.org/geo",
      "http://schema.org/longitude",
    ]);

  travelAction.toAddress =
    travelActionImm.getIn(["s:toLocation", "s:name"]) ||
    travelActionImm.getIn([
      "http://schema.org/toLocation",
      "http://schema.org/name",
    ]);

  travelAction.toLocation.lat =
    travelActionImm.getIn(["s:toLocation", "s:geo", "s:latitude"]) ||
    travelActionImm.getIn([
      "http://schema.org/toLocation",
      "http://schema.org/geo",
      "http://schema.org/latitude",
    ]);

  travelAction.toLocation.lng =
    travelActionImm.getIn(["s:toLocation", "s:geo", "s:longitude"]) ||
    travelActionImm.getIn([
      "http://schema.org/toLocation",
      "http://schema.org/geo",
      "http://schema.org/longitude",
    ]);

  if (
    (travelAction.fromAddress &&
      travelAction.fromLocation.lat &&
      travelAction.fromLocation.lng) ||
    (travelAction.toAddress &&
      travelAction.toLocation.lat &&
      travelAction.toLocation.lng)
  ) {
    return Immutable.fromJS(travelAction);
  }

  console.error(
    "Cant parse travelAction, data is an invalid travelAction-object: ",
    travelActionImm.toJS()
  );
}
<|endoftext|>


<commit_before>export function selectItemsService($mdDialog) {
    'ngInject';

    return {
        open: function() {
            let tabs = {
                processes: false,
                files: false,
                samples: false,
                reviews: false,
                uploadFiles: false
            };

            let opts = {
                experimentId: '',
                singleSelection: false
            };

            if (arguments.length === 0) {
                throw "Invalid arguments to service selectItems:open()";
            }

            for (let i = 0; i < arguments.length; i++) {
                if ((arguments[i] in tabs)) {
                    tabs[arguments[i]] = true;
                } else if (_.isObject(arguments[i])) {
                    opts.experimentId = arguments[i].experimentId;
                    opts.singleSelection = arguments[i].singleSelection;
                }
            }

            let showFilesTree = tabs.files && opts.experimentId === '';
            let showFilesTable = tabs.files && opts.experimentId !== '';
            return $mdDialog.show({
                templateUrl: 'app/global.services/select-items/select-items.html',
                controller: SelectItemsServiceModalController,
                controllerAs: 'ctrl',
                bindToController: true,
                locals: {
                    showProcesses: tabs.processes,

                    showFilesTree: showFilesTree,

                    showFilesTable: showFilesTable,

                    showSamples: tabs.samples,

                    showReviews: tabs.reviews,

                    showUploadFiles: tabs.uploadFiles,

                    options: opts
                }
            });
        }
    };
}

/*@ngInject*/
function SelectItemsServiceModalController($mdDialog, projectsService, $stateParams, mcstate, experimentsService) {
    let ctrl = this;

    ctrl.project = mcstate.get(mcstate.CURRENT$PROJECT);
    ctrl.tabs = loadTabs();
    ctrl.activeTab = ctrl.tabs[0].name;
    ctrl.setActive = setActive;
    ctrl.isActive = isActive;
    ctrl.uploadComplete = uploadComplete;
    ctrl.ok = ok;
    ctrl.cancel = cancel;
    ctrl.processes = [];
    ctrl.samples = [];
    ctrl.uploadedFiles = [];

    /////////////////////////

    function setActive(tab) {
        ctrl.activeTab = tab;
    }

    function isActive(tab) {
        return ctrl.activeTab === tab;
    }

    function ok() {
        const selectedProcesses = ctrl.processes.filter(function(p) {
            return p.input || p.output;
        });

        let selectedSamples = ctrl.samples.filter(function(s) {
            for (let i = 0; i < s.versions.length; i++) {
                if (s.versions[i].selected) {
                    return true;
                }
            }
            return false;
        });

        let selectedFiles = getSelectedFiles();

        $mdDialog.hide({
            processes: selectedProcesses,
            samples: selectedSamples,
            files: selectedFiles
        });
    }

    function getSelectedFiles() {
        let files = [];
        if (ctrl.showFilesTree) {
            let filesFromTree = [];
            let projectFiles = mcstate.get(mcstate.CURRENT$PROJECT).files;
            if (projectFiles && projectFiles.length) {
                let treeModel = new TreeModel(),
                    root = treeModel.parse(mcstate.get(mcstate.CURRENT$PROJECT).files[0]);
                // Walk the tree looking for selected files and adding them to the
                // list of files. Also reset the selected flag so the next time
                // the popup for files is used it doesn't show previously selected
                // items.
                root.walk({strategy: 'pre'}, function(node) {
                    if (node.model.data.selected) {
                        node.model.data.selected = false;
                        if (node.model.data.otype === 'file') {
                            filesFromTree.push(node.model.data);
                        }
                    }
                });
                files = files.concat(filesFromTree);
            }
        }

        if (ctrl.showFilesTable) {
            files = files.concat(ctrl.files.filter(f => f.selected));
        }

        if (ctrl.showUploadFiles) {
            files = files.concat(ctrl.uploadedFiles);
        }

        return files;
    }

    function uploadComplete(fileIds) {
        ctrl.uploadedFiles = fileIds.map(fid => ({id: fid}));
    }

    function cancel() {
        $mdDialog.cancel();
    }

    function loadTabs() {
        let tabs = [];
        if (ctrl.showProcesses) {
            tabs.push(newTab('processes', 'fa-code-fork'));
            if (ctrl.options.experimentId) {
                // get processes for experiment
            } else {
                projectsService.getProjectProcesses($stateParams.project_id).then(function(processes) {
                    ctrl.processes = processes;
                });
            }
        }

        if (ctrl.showSamples) {
            tabs.push(newTab('samples', 'fa-cubes'));
            if (ctrl.options.experimentId && ctrl.options.experimentId !== '') {
                experimentsService.getSamplesForExperiment($stateParams.project_id, ctrl.options.experimentId).then(
                    (samples) => {
                        ctrl.samples = samples;
                    }
                )
            } else {
                projectsService.getProjectSamples($stateParams.project_id).then(function(samples) {
                    ctrl.samples = samples;
                });
            }
        }

        if (ctrl.showFilesTree) {
            tabs.push(newTab('file tree', 'fa-files-o'));
        }

        if (ctrl.showFilesTable) {
            tabs.push(newTab('file table', 'fa-files-o'));
            experimentsService.getFilesForExperiment($stateParams.project_id, ctrl.options.experimentId)
                .then(
                    (files) => {
                        ctrl.files = files;
                    }
                );
        }

        if (ctrl.showReviews) {
            tabs.push(newTab('reviews', 'fa-comment'));
        }

        if (ctrl.showUploadFiles) {
            tabs.push(newTab('Upload Files', 'fa-upload'));
        }

        tabs.sort(function compareByName(t1, t2) {
            if (t1.name < t2.name) {
                return -1;
            }
            if (t1.name > t2.name) {
                return 1;
            }
            return 0;
        });

        return tabs;
    }

    function newTab(name, icon) {
        return {
            name: name,
            icon: icon
        };
    }
}

<commit_msg>Start separating select items into separate calls.<commit_after>export function selectItemsService($mdDialog) {
    'ngInject';

    function getTabs(...args) {
        let tabs = {
            processes: false,
            fileTree: false,
            fileTable: false,
            uploadFiles: false,
            samples: false,
            reviews: false
        };
        args.forEach(tab => tabs[tab] = true);
        return tabs;
    }

    return {
        fileTree(uploadFiles = false) {
            // By default assume uploading files when getting tabs, and then reset that tab to the
            // value of the uploadFiles parameter.
            let tabs = getTabs('fileTree', 'uploadFiles');
            tabs.uploadFiles = uploadFiles;
        },

        fileTable(uploadFiles = false, files = []) {
            // By default assume uploading files when getting tabs, and then reset that tab to the
            // value of the uploadFiles parameter.
            let tabs = getTabs('fileTable', 'uploadFiles');
            tabs.uploadFiles = uploadFiles;
        },

        samples(samples = []) {
            let tabs = getTabs('samples');
        },

        processes(processes = []) {
            let tabs = getTabs('processes');
        },

        open: function() {
            let tabs = {
                processes: false,
                files: false,
                samples: false,
                reviews: false,
                uploadFiles: false
            };

            let opts = {
                experimentId: '',
                singleSelection: false
            };

            if (arguments.length === 0) {
                throw "Invalid arguments to service selectItems:open()";
            }

            for (let i = 0; i < arguments.length; i++) {
                if ((arguments[i] in tabs)) {
                    tabs[arguments[i]] = true;
                } else if (_.isObject(arguments[i])) {
                    opts.experimentId = arguments[i].experimentId;
                    opts.singleSelection = arguments[i].singleSelection;
                }
            }

            let showFilesTree = tabs.files && opts.experimentId === '';
            let showFilesTable = tabs.files && opts.experimentId !== '';
            return $mdDialog.show({
                templateUrl: 'app/global.services/select-items/select-items.html',
                controller: SelectItemsServiceModalController,
                controllerAs: 'ctrl',
                bindToController: true,
                locals: {
                    showProcesses: tabs.processes,

                    showFilesTree: showFilesTree,

                    showFilesTable: showFilesTable,

                    showSamples: tabs.samples,

                    showReviews: tabs.reviews,

                    showUploadFiles: tabs.uploadFiles,

                    options: opts
                }
            });
        }
    };
}

/*@ngInject*/
function SelectItemsServiceModalController($mdDialog, projectsService, $stateParams, mcstate, experimentsService) {
    let ctrl = this;

    ctrl.project = mcstate.get(mcstate.CURRENT$PROJECT);
    ctrl.tabs = loadTabs();
    ctrl.activeTab = ctrl.tabs[0].name;
    ctrl.setActive = setActive;
    ctrl.isActive = isActive;
    ctrl.uploadComplete = uploadComplete;
    ctrl.ok = ok;
    ctrl.cancel = cancel;
    ctrl.processes = [];
    ctrl.samples = [];
    ctrl.uploadedFiles = [];

    /////////////////////////

    function setActive(tab) {
        ctrl.activeTab = tab;
    }

    function isActive(tab) {
        return ctrl.activeTab === tab;
    }

    function ok() {
        const selectedProcesses = ctrl.processes.filter(function(p) {
            return p.input || p.output;
        });

        let selectedSamples = ctrl.samples.filter(function(s) {
            for (let i = 0; i < s.versions.length; i++) {
                if (s.versions[i].selected) {
                    return true;
                }
            }
            return false;
        });

        let selectedFiles = getSelectedFiles();

        $mdDialog.hide({
            processes: selectedProcesses,
            samples: selectedSamples,
            files: selectedFiles
        });
    }

    function getSelectedFiles() {
        let files = [];
        if (ctrl.showFilesTree) {
            let filesFromTree = [];
            let projectFiles = mcstate.get(mcstate.CURRENT$PROJECT).files;
            if (projectFiles && projectFiles.length) {
                let treeModel = new TreeModel(),
                    root = treeModel.parse(mcstate.get(mcstate.CURRENT$PROJECT).files[0]);
                // Walk the tree looking for selected files and adding them to the
                // list of files. Also reset the selected flag so the next time
                // the popup for files is used it doesn't show previously selected
                // items.
                root.walk({strategy: 'pre'}, function(node) {
                    if (node.model.data.selected) {
                        node.model.data.selected = false;
                        if (node.model.data.otype === 'file') {
                            filesFromTree.push(node.model.data);
                        }
                    }
                });
                files = files.concat(filesFromTree);
            }
        }

        if (ctrl.showFilesTable) {
            files = files.concat(ctrl.files.filter(f => f.selected));
        }

        if (ctrl.showUploadFiles) {
            files = files.concat(ctrl.uploadedFiles);
        }

        return files;
    }

    function uploadComplete(fileIds) {
        ctrl.uploadedFiles = fileIds.map(fid => ({id: fid}));
    }

    function cancel() {
        $mdDialog.cancel();
    }

    function loadTabs() {
        let tabs = [];
        if (ctrl.showProcesses) {
            tabs.push(newTab('processes', 'fa-code-fork'));
            if (ctrl.options.experimentId) {
                // get processes for experiment
            } else {
                projectsService.getProjectProcesses($stateParams.project_id).then(function(processes) {
                    ctrl.processes = processes;
                });
            }
        }

        if (ctrl.showSamples) {
            tabs.push(newTab('samples', 'fa-cubes'));
            if (ctrl.options.experimentId && ctrl.options.experimentId !== '') {
                experimentsService.getSamplesForExperiment($stateParams.project_id, ctrl.options.experimentId).then(
                    (samples) => {
                        ctrl.samples = samples;
                    }
                )
            } else {
                projectsService.getProjectSamples($stateParams.project_id).then(function(samples) {
                    ctrl.samples = samples;
                });
            }
        }

        if (ctrl.showFilesTree) {
            tabs.push(newTab('file tree', 'fa-files-o'));
        }

        if (ctrl.showFilesTable) {
            tabs.push(newTab('file table', 'fa-files-o'));
            experimentsService.getFilesForExperiment($stateParams.project_id, ctrl.options.experimentId)
                .then(
                    (files) => {
                        ctrl.files = files;
                    }
                );
        }

        if (ctrl.showReviews) {
            tabs.push(newTab('reviews', 'fa-comment'));
        }

        if (ctrl.showUploadFiles) {
            tabs.push(newTab('Upload Files', 'fa-upload'));
        }

        tabs.sort(function compareByName(t1, t2) {
            if (t1.name < t2.name) {
                return -1;
            }
            if (t1.name > t2.name) {
                return 1;
            }
            return 0;
        });

        return tabs;
    }

    function newTab(name, icon) {
        return {
            name: name,
            icon: icon
        };
    }
}

<|endoftext|>


<commit_before>var Promise = require('bluebird');
var AWS = require('aws-sdk');
var s3 = new AWS.S3();
Promise.promisifyAll(Object.getPrototypeOf(s3));

function getUser(bucket, key) {
  console.log("Going to get " + key + " from " + bucket);
  return s3.getObjectAsync({Bucket: bucket, Key: key}).then(function(data) {
    var s = new Buffer(data.Body).toString();
    return JSON.parse(s);
  }).catch(function() {
    return {};
  });
}

function list(username) {
  console.log("Going to list entries for " + username);
  var bucket = 'constellational-store';
  var prefix = username + '/';
  return getUser(bucket, username).then(function(user) {
    return s3.listObjectsAsync({Bucket: bucket, Prefix: prefix}).then(function(data) {
      user.articles = data.Contents.map(function(o) {
        return o.Key.substring(prefix.length);
      });
      user.articles.reverse();
      return user;
    });
  });
}

exports.handler = function(event, context) {
  console.log("Starting");
  console.log(event);
  return list(event.username).then(context.succeed).catch(context.fail);
};
<commit_msg>update user's file when entry is added, with entry urls<commit_after>var BUCKET = 'constellational-store';
var Promise = require('bluebird');
var AWS = require('aws-sdk');
var s3 = new AWS.S3();
Promise.promisifyAll(Object.getPrototypeOf(s3));

function getUser(key) {
  console.log("Going to get " + key + " from " + bucket);
  return s3.getObjectAsync({Bucket: BUCKET, Key: key}).then(function(data) {
    var s = new Buffer(data.Body).toString();
    return JSON.parse(s);
  }).catch(function() {
    return {};
  });
}

function list(username) {
  console.log("Going to list entries for " + username);
  var bucket = 'constellational-store';
  var prefix = username + '/';
  return getUser(username).then(function(user) {
    return s3.listObjectVersionsAsync({Bucket: BUCKET, Prefix: prefix}).then(function(data) {
      var latest = data.Versions.filter(function(o) {
        return o.IsLatest;
      });
      user.articles = latest.map(function(o) {
        return o.Key.substring(prefix.length) + '?VersionId=' + o.VersionId;
      });
      user.articles.reverse();
      return user;
    });
  });
}

function storeStaticFile(key, json) {
  console.log("Going to put " + key + " in " + BUCKET);
  return s3.putObjectAsync({
    Bucket: BUCKET,
    Key: key,
    Body: JSON.stringify(json),
    ContentType: 'application/json',
    ACL: 'public-read'
  });
}

exports.handler = function(event, context) {
  console.log("Starting");
  console.log(event);
  var key = event.Records[0].s3.object.key;
  console.log("The key is: "+key);
  if (splitKey.length < 2) context.fail("Not an entry");
  var username = splitKey[0];
  return list(username).then(function(data) {
    console.log("Going to store static file");
    return storeStaticFile(username, data);
  }).then(context.succeed).catch(context.fail);
};
<|endoftext|>