Bug 458884: Node.js Implementation of Fast Grep Search

- Addressed magic number issues
- Renamed functions and variables to better descriptions
- Removed unused variables

Signed-off-by: Hyunjoon Song <rsong@mit.edu>
diff --git a/modules/orionode/lib/search.js b/modules/orionode/lib/search.js
index 0a3b264..d1e28ce 100644
--- a/modules/orionode/lib/search.js
+++ b/modules/orionode/lib/search.js
@@ -12,8 +12,6 @@
 var connect = require('connect');
 var url = require('url');
 var fs = require('fs');
-var util = require('util');
-var api = require('./api'), writeError = api.writeError;
 var fileUtil = require('./fileUtil');
 var resource = require('./resource');
 
@@ -24,15 +22,29 @@
 	if (!workspaceRoot) { throw 'options.root path required'; }
 	var workspaceId = 'orionode';
 	var workspaceName = 'Orionode Workspace';
-
-	var fieldNames = "Name,NameLower,Length,Directory,LastModified,Location,Path,RegEx,CaseSensitive";
-	var fieldList = fieldNames.split(",");
+	var fieldList = "Name,NameLower,Length,Directory,LastModified,Location,Path,RegEx,CaseSensitive".split(",");
 
 	function originalFileRoot(req) {
 		return fileUtil.getContextPath(req) + fileRoot;
 	}
-	function originalWorkspaceRoot(req) {
-		return fileUtil.getContextPath(req) + workspaceRoot;
+
+	function isSearchField(term) {
+		for (var i = 0; i < fieldList.length; i++) {
+			if (term.lastIndexOf(fieldList[i] + ":", 0) === 0) {
+				return true;
+			};
+		};
+		return false;
+	}
+
+	function undoLuceneEscape(searchTerm){
+		var specialChars = "+-&|!(){}[]^\"~:\\";
+		for (var i = 0; i < specialChars.length; i++) {
+			var character = specialChars.substring(i,i+1);
+			var escaped = "\\" + character;
+			searchTerm = searchTerm.replace(new RegExp(escaped,"g"), character);
+		};
+		return searchTerm;
 	}
 
 	function SearchOptions(req, res){
@@ -48,21 +60,12 @@
 		this.searchTermCaseSensitive = false;
 		this.username = null;
 
-		this.isSearchField = function(term) {
-			for (var i = 0; i < fieldList.length; i++) {
-				if (term.lastIndexOf(fieldList[i] + ":", 0) === 0) {
-					return true;
-				}
-			}
-			return false;
-		}
-
-		this.buildOptions = function() {
+		this.buildSearchOptions = function() {
 			var queryObject = url.parse(req.url, true).query;
 			var terms = queryObject.q.split(" ");
 			for (var i = 0; i < terms.length; i++) {
 				var term = terms[i];
-				if (this.isSearchField(term)) {
+				if (isSearchField(term)) {
 					if (term.lastIndexOf("NameLower:", 0) === 0) {
 						this.filenamePatternCaseSensitive = false;
 						this.filenamePattern = term.substring(10);
@@ -83,25 +86,16 @@
 			}
 
 			this.defaultLocation = "/file/" + workspaceId;
-		}
+		};
 	};
 
-	function undoLuceneEscape(searchTerm){
-		var specialChars = "+-&|!(){}[]^\"~:\\";
-		for (var i = 0; i < specialChars.length; i++) {
-			var character = specialChars.substring(i,i+1);
-			var escaped = "\\" + character;
-			searchTerm = searchTerm.replace(new RegExp(escaped,"g"), character);
-		}
-		return searchTerm;
-	}
-
 	function buildSearchPattern(searchOpts){
 		var searchTerm = searchOpts.searchTerm;
 		if (!searchOpts.regEx) {
 			if (searchTerm.indexOf("\"") === 0) {
 				searchTerm = searchTerm.substring(1, searchTerm.length - 1);
 			}
+
 			searchTerm = undoLuceneEscape(searchTerm);
 			if (searchTerm.indexOf("?") != -1 || searchTerm.indexOf("*") != -1) {
 				if (searchTerm.indexOf("*") === 0) {
@@ -116,11 +110,12 @@
 			}
 
 			if (!searchOpts.searchTermCaseSensitive) {
-				return new RegExp(searchTerm, "i");
+				searchTerm = new RegExp(searchTerm, "i");
 			} else {
-				return new RegExp(searchTerm);
+				searchTerm = new RegExp(searchTerm);
 			}
-		};
+		}
+		return searchTerm;
 	}
 
 	function buildFilenamePattern(searchOpts){
@@ -144,26 +139,31 @@
 		}
 	}
 
-	function searchChild(dirLocation, fileLocation, searchPattern, filenamePattern, results, workspaceRootUrl){
-		var location = dirLocation + fileLocation;
-		var stats = fs.statSync(location);
+	function searchFile(dirLocation, filename, searchPattern, filenamePattern, results){
+		var filePath = dirLocation + filename;
+		var stats = fs.statSync(filePath);
+
 		if (stats.isDirectory()) {
-			if (location.substring(location.length - 1) != "/") location = location + "/";
-			var dirFiles = fs.readdirSync(location);
-			dirFiles.forEach(function (dirFile) {
-				var resultsForEach = searchChild(location, dirFile, searchPattern, filenamePattern, results, workspaceRootUrl);
-				if (resultsForEach) results.concat(resultsForEach);
-			})
+			if (filePath.substring(filePath.length-1) != "/") filePath = filePath + "/";
+
+			var directoryFiles = fs.readdirSync(filePath);
+			directoryFiles.forEach(function (directoryFile) {
+				var fileResults = searchFile(filePath, directoryFile, searchPattern, filenamePattern, results);
+				if (fileResults) results.concat(fileResults);
+			});
+
 		} else {
-			var file = fs.readFileSync(location, 'utf8');
-			if (fileLocation.match(filenamePattern) && file.match(searchPattern)){
+			var file = fs.readFileSync(filePath, 'utf8');
+			if (filename.match(filenamePattern) && file.match(searchPattern)){
+				var filePathFromWorkspace = filePath.substring(workspaceDir.length);
+
 				results.push({
 					"Directory": stats.isDirectory(),
 					"LastModified": stats.mtime.getTime(),
 					"Length": stats.size,
-					"Location": "/file" + location.substring(workspaceDir.length),
-					"Name": fileLocation,
-					"Path": workspaceName + location.substring(workspaceDir.length)
+					"Location": "/file" + filePathFromWorkspace,
+					"Name": filename,
+					"Path": workspaceName + filePathFromWorkspace
 				});
 			}
 		}
@@ -174,23 +174,25 @@
 	.use(connect.json())
 	.use(resource(workspaceRoot, {
 		GET: function(req, res, next, rest) {
-			var workspaceRootUrl = originalWorkspaceRoot(req);
-
 			var searchOpt = new SearchOptions(req, res);
-			searchOpt.buildOptions();
+			searchOpt.buildSearchOptions();
 
 			var searchPattern = buildSearchPattern(searchOpt);
 			var filenamePattern = buildFilenamePattern(searchOpt);
 
 			var parentFileLocation = originalFileRoot(req);
-			var scope = workspaceDir + searchOpt.location.substring(5, searchOpt.location.length - 1);
-			if (scope.charAt(scope.length-1) != "/") scope = scope + "/";
-			fileUtil.getChildren(scope, parentFileLocation, function(children) {
+			var endOfFileRootIndex = 5;
+
+			var searchScope = workspaceDir + searchOpt.location.substring(endOfFileRootIndex, searchOpt.location.length - 1);
+			if (searchScope.charAt(searchScope.length - 1) != "/") searchScope = searchScope + "/";
+
+			fileUtil.getChildren(searchScope, parentFileLocation, function(children) {
 				var results = [];
 				for (var i = 0; i < children.length; i++){
 					var child = children[i];
-					var childResults = [];
-					var matches = searchChild(scope, child.Location.substring(6), searchPattern, filenamePattern, childResults, workspaceRootUrl);
+					var childName = child.Location.substring(endOfFileRootIndex + 1);
+
+					var matches = searchFile(searchScope, childName, searchPattern, filenamePattern, []);
 					if (matches) results = results.concat(matches);
 				};
 
@@ -215,6 +217,7 @@
 				    "status": 0
 				  }
 				});
+
 				res.setHeader('Content-Type', 'application/json');
 				res.end(ws);
 			});