import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
final String regex = "function\\(([^)]*)\\) \\{\\s+(?:return )?([^;\\v]+);\\s+\\}";
final String string = "goog.provide('smb.controllers.SearchboxForDashboards');\n\n"
+ "goog.require('goog.array');\n"
+ "goog.require('goog.functions');\n"
+ "goog.require('goog.iter');\n"
+ "goog.require('goog.object');\n"
+ "goog.require('goog.string.format');\n"
+ "goog.require('smb.model.Dashboard');\n"
+ "goog.require('smb.model.User');\n\n"
+ "goog.scope(function() {\n\n\n\n"
+ "var User = smb.model.User;\n\n"
+ "/**\n"
+ " * @param {!angular.Scope} $scope Injected Angular scope.\n"
+ " * @param {!angular.Route} $route Injected angular route.\n"
+ " * @param {!angular.Location} $location Injected angular location.\n"
+ " * @param {!angular.Resource} $resource Injected angular resource.\n"
+ " * @param {!smb.services.navigation} navigationService The navigationService.\n"
+ " * @constructor\n"
+ " */\n"
+ "smb.controllers.SearchboxForDashboards = function($scope, $route, $location,\n"
+ " $resource, navigationService) {\n"
+ " /** @private {!angular.Scope} */\n"
+ " this.scope_ = $scope;\n\n"
+ " /** @private {!smb.services.navigation} */\n"
+ " this.navigationService_ = navigationService;\n\n"
+ " /** @private {!angular.Route} */\n"
+ " this.route_ = $route;\n\n"
+ " /** @private {!angular.Location} */\n"
+ " this.location_ = $location;\n\n"
+ " /** @private {!angular.Resource} */\n"
+ " this.resource_ = $resource;\n\n"
+ " /** @private */\n"
+ " this.active_ = this.scope_.active;\n\n"
+ " /**\n"
+ " * Current search string.\n"
+ " * @export {string}\n"
+ " */\n"
+ " this.search = '';\n\n"
+ " /**\n"
+ " * The list of current search results.\n"
+ " * @export {!Array<!SearchboxForDashboards.SearchResultStruct>}\n"
+ " */\n"
+ " this.searchResults = [];\n"
+ "};\n\n"
+ "var SearchboxForDashboards = smb.controllers.SearchboxForDashboards;\n\n"
+ "/**\n"
+ " * @return {boolean} Whether there are no search results.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.hasNoSearchResults_ = function() {\n"
+ " return this.searchResults.length == 0;\n"
+ "};\n\n"
+ "/**\n"
+ " * Types of component contained in a search result.\n"
+ " * @enum {string}\n"
+ " */\n"
+ "SearchboxForDashboards.ComponentType = {\n"
+ " TAG: 'tag',\n"
+ " TITLE: 'title',\n"
+ " DESCRIPTION: 'description'\n"
+ "};\n\n"
+ "/**\n"
+ " * FIRST_SUBSEARCH is a multiplier applied for matches starting at the beginning\n"
+ " * of the text as a whole. STARTING_MATCH is applies for matches at the\n"
+ " * beginning of any word.\n"
+ " * @typedef {{\n"
+ " * FIRST_SUBSEARCH: number,\n"
+ " * STARTING_MATCH: number\n"
+ " * }}\n"
+ " */\n"
+ "SearchboxForDashboards.ComponentWeight;\n\n"
+ "/**\n"
+ " * Weight settings for the various components, can be tweaked to change results.\n"
+ " * @const {!Object<!SearchboxForDashboards.ComponentType,\n"
+ " * !SearchboxForDashboards.ComponentWeight>}\n"
+ " */\n"
+ "SearchboxForDashboards.WEIGHTS = goog.object.create(\n"
+ " SearchboxForDashboards.ComponentType.TAG, {\n"
+ " FIRST_SUBSEARCH: 1,\n"
+ " STARTING_MATCH: 2\n"
+ " },\n"
+ " SearchboxForDashboards.ComponentType.TITLE, {\n"
+ " FIRST_SUBSEARCH: 10,\n"
+ " STARTING_MATCH: 10\n"
+ " },\n"
+ " SearchboxForDashboards.ComponentType.DESCRIPTION, {\n"
+ " FIRST_SUBSEARCH: 10,\n"
+ " STARTING_MATCH: 10\n"
+ " }\n"
+ ");\n\n"
+ "/**\n"
+ " * One feature of the search result.\n"
+ " * @typedef {{\n"
+ " * type: !SearchboxForDashboards.ComponentType,\n"
+ " * match: string,\n"
+ " * tag: (string|undefined),\n"
+ " * title: (string|undefined),\n"
+ " * score: number,\n"
+ " * }}\n"
+ " */\n"
+ "SearchboxForDashboards.SearchResultComponent;\n\n"
+ "/**\n"
+ " * Search result with scoring information.\n"
+ " * @typedef {{\n"
+ " * dashboard: !smb.model.Dashboard,\n"
+ " * components: !Array<!SearchResultComponent>,\n"
+ " * bestTitleMatch: ?string,\n"
+ " * bestDescriptionMatch: ?string,\n"
+ " * score: number,\n"
+ " * }}\n"
+ "*/\n"
+ "SearchboxForDashboards.SearchResultStruct;\n\n\n"
+ "/**\n"
+ " * Gives a match score for a dashboard.\n"
+ " * TODO(b/27602041) Do more in-depth research into whether there are feasible\n"
+ " * alternatives to writing custom search logic that still give us fine\n"
+ " * control over ranking.\n"
+ " * @param {string} search The text to search.\n"
+ " * @param {!smb.model.Dashboard} dashboard The dashboard to which to apply the\n"
+ " * search.\n"
+ " * @param {boolean=} opt_recur Whether to recursively perform subsearches\n"
+ " * for the different words in the search, i.e \"word1 word2 word3\" would\n"
+ " * do \"word1 word2\" and \"word2 word3\", and then the same recursively.\n"
+ " * @param {boolean=} opt_isFirstSearch Whether this is should be treated as\n"
+ " * matching at the beginning of a search.\n"
+ " * @return {!SearchResultStruct} The result of the search.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.doDashboardSearch_ =\n"
+ " function(search, dashboard, opt_recur, opt_isFirstSearch) {\n"
+ " var isFirstSearch = opt_isFirstSearch;\n"
+ " var struct = {dashboard: dashboard, components: []};\n\n"
+ " var titleSearchComponent =\n"
+ " this.doTitleSearch_(search, dashboard, isFirstSearch);\n"
+ " if (titleSearchComponent != null) {\n"
+ " struct.components.push(titleSearchComponent);\n"
+ " }\n\n"
+ " var descriptionSearchComponent =\n"
+ " this.doDescriptionSearch_(search, dashboard, isFirstSearch);\n"
+ " if (descriptionSearchComponent != null) {\n"
+ " struct.components.push(descriptionSearchComponent);\n"
+ " }\n\n"
+ " var tagSearchComponent = this.doTagSearch_(search, dashboard);\n"
+ " if (tagSearchComponent != null) {\n"
+ " struct.components.push(tagSearchComponent);\n"
+ " }\n\n"
+ " // now we search for all the n-gram substrings\n"
+ " if (opt_recur) {\n"
+ " var re = /\\s+/;\n"
+ " var tokens = search.split(re);\n"
+ " var len = tokens.length;\n"
+ " for (var runLength = len - 1; runLength > 0; runLength--) {\n"
+ " for (var start = 0; start <= len - runLength; start++) {\n"
+ " var subArr = tokens.slice(start, start + runLength);\n"
+ " var newSearch = subArr.join(' ');\n"
+ " var isFirstSearch = start == 0;\n"
+ " var subStruct =\n"
+ " this.doDashboardSearch_(newSearch, dashboard, false, isFirstSearch);\n"
+ " struct.components = struct.components.concat(subStruct.components);\n"
+ " }\n"
+ " }\n"
+ " }\n\n"
+ " struct.components = struct.components.sort(function(a, b) {\n"
+ " return b.score - a.score;\n"
+ " });\n\n"
+ " var bestTitleMatch = goog.array.find(struct.components, function(component) {\n"
+ " return component.type == SearchboxForDashboards.TITLE;\n"
+ " });\n"
+ " if (bestTitleMatch) {\n"
+ " struct.bestTitleMatch = bestTitleMatch.title;\n"
+ " }\n\n"
+ " var bestDescriptionMatch = goog.array.find(struct.components,\n"
+ " function(component) {\n"
+ " return component.type == SearchboxForDashboards.DESCRIPTION;\n"
+ " });\n"
+ " if (bestDescriptionMatch) {\n"
+ " struct.bestDescriptionMatch = bestDescriptionMatch.description;\n"
+ " }\n\n"
+ " this.computeAndSetSearchResultScore_(struct);\n"
+ " return struct;\n"
+ "};\n\n"
+ "/**\n"
+ " * Computes score for the search result and sets score for the search result.\n"
+ " * @param {!SearchResultStruct} searchResult The search result to operate on.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.computeAndSetSearchResultScore_ =\n"
+ " function(searchResult) {\n"
+ " searchResult.score = searchResult.components.map(function(component) {\n"
+ " return component.score;\n"
+ " }).reduce(function(a, b) { return a + b; }, 0);\n"
+ " };\n\n"
+ "/**\n"
+ " * Performs search on dashboard title.\n"
+ " * @param {string} search The text to search.\n"
+ " * @param {!smb.model.Dashboard} dashboard The dashboard to perform search on.\n"
+ " * @param {boolean} isFirstSearch Whether to treat this as matching at the\n"
+ " * beginning of a search.\n"
+ " * @return {?SearchboxForDashboards.SearchResultComponent} The search match\n"
+ " * component.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.doTitleSearch_ =\n"
+ " function(search, dashboard, isFirstSearch) {\n"
+ " var title = dashboard.titleDisplayText || dashboard.menuDisplayText;\n"
+ " return this.doTextSearch_(search, title, isFirstSearch,\n"
+ " SearchboxForDashboards.ComponentType.TITLE);\n"
+ "};\n\n"
+ "/**\n"
+ " * Performs search on dashboard description.\n"
+ " * @param {string} search The text to search.\n"
+ " * @param {!smb.model.Dashboard} dashboard The dashboard to perform search on.\n"
+ " * @param {boolean} isFirstSearch Whether to treat this as matching at the\n"
+ " * beginning of a search.\n"
+ " * @return {?SearchboxForDashboards.SearchResultComponent} The search match\n"
+ " * component.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.doDescriptionSearch_ =\n"
+ " function(search, dashboard, isFirstSearch) {\n"
+ " var title = dashboard.titleDisplayText || dashboard.menuDisplayText;\n"
+ " return this.doTextSearch_(search, title, isFirstSearch,\n"
+ " SearchboxForDashboards.ComponentType.DESCRIPTION);\n"
+ "};\n\n"
+ "/**\n"
+ " * Searches the text.\n"
+ " * @param {string} search\n"
+ " * @param {string} text\n"
+ " * @param {boolean} isFirstSearch\n"
+ " * @param {smb.controllers.SearchboxForDashboards.ComponentType} type\n"
+ " * @return {?SearchboxForDashboards.SearchResultComponent} The search match\n"
+ " * component.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.doTextSearch_ = function(search, text,\n"
+ " isFirstSearch, type) {\n"
+ " var score = 0;\n"
+ " var searchRegex = new RegExp(search, 'i');\n"
+ " var match = text.match(searchRegex);\n"
+ " if (!match) {\n"
+ " return null;\n"
+ " }\n\n"
+ " score = match[0].length;\n"
+ " var weight = SearchboxForDashboards.WEIGHTS[type];\n"
+ " if (text.toLowerCase().startsWith(match[0].toLowerCase())) {\n"
+ " score *= weight.STARTING_MATCH;\n"
+ " if (isFirstSearch) {\n"
+ " score *= weight.FIRST_SUBSEARCH;\n"
+ " }\n"
+ " }\n\n"
+ " return goog.object.create(\n"
+ " type, match[0],\n"
+ " 'score', score,\n"
+ " 'type', type,\n"
+ " 'match', search\n"
+ " );\n"
+ "};\n\n"
+ "/**\n"
+ " * Perform search on dashboard tags.\n"
+ " * @param {string} search The text to search.\n"
+ " * @param {!smb.model.Dashboard} dashboard The dashboard to perform search on.\n"
+ " * @param {boolean} isFirstSearch\n"
+ " * @return {?SearchboxForDashboards.SearchResultComponent} The search match\n"
+ " * component.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.doTagSearch_ = function(search, dashboard,\n"
+ " isFirstSearch) {\n"
+ " if (!('tags' in dashboard)) {\n"
+ " return null;\n"
+ " }\n"
+ " var tagMatches = dashboard.tags.map(function(tag) {\n"
+ " return this.doTextSearch_(search, tag, isFirstSearch,\n"
+ " SearchboxForDashboards.ComponentType.TAG);\n"
+ " }, this);\n\n"
+ " var tagMatches = [];\n"
+ " var groups = goog.iter.groupBy(tagMatches,\n"
+ " function(tagMatch) { return tagMatch.match; });\n\n"
+ " var scores = [];\n"
+ " var score = 0;\n"
+ " var iterLeft = true;\n"
+ " while (iterLeft) {\n"
+ " try {\n"
+ " var matchTup = groups.next();\n"
+ " var key = matchTup[0];\n"
+ " var matches = matchTup[1];\n"
+ " var numMatches = matches.length;\n"
+ " var scores = matches.map(function(match) { return match.score; })\n"
+ " .reduce(function(a, b) { return a + b; }, 0);\n"
+ " var average = scores / numMatches;\n"
+ " // numMatches + 1 because the score for one should not be zero\n"
+ " // have to do log because too many dups for sqrt to make sense\n"
+ " score += (average * Math.log(numMatches + 1));\n"
+ " } catch (e) {\n"
+ " // goog.iter throws exception at the end rather than having a flag\n"
+ " // to check\n"
+ " iterLeft = false;\n"
+ " }\n"
+ " }\n\n"
+ " return {\n"
+ " score: score,\n"
+ " type: SearchboxForDashboards.ComponentType.TAG,\n"
+ " match: search\n"
+ " };\n"
+ "};\n\n"
+ "/**\n"
+ " * @param {string} search The text to search for.\n"
+ " * @param {!Array<!smb.model.Dashboard>} dashboards The dashboards to search\n"
+ " * over.\n"
+ " * @return {!Array<!SearchResultStruct>} The results, sorted.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.doSearch_ = function(search, dashboards) {\n"
+ " var scoreStructs = dashboards.map(function(dashboard) {\n"
+ " return this.doDashboardSearch_(search, dashboard, true, true);\n"
+ " }, this);\n"
+ " return scoreStructs\n"
+ " .filter(function(struct) { return struct.score > 0; }, this)\n"
+ " .sort(function(aStruct, bStruct) {\n"
+ " return bStruct.score - aStruct.score;\n"
+ " });\n"
+ "};\n\n"
+ "/**\n"
+ " * Updates the autocomplete results, showing the appropriate amount for the\n"
+ " * current search text.\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.updateAutoComplete = function() {\n"
+ " var dashboards = this.navigationService_.getSearchableDashboards();\n"
+ " if (!dashboards) return;\n"
+ " var searchResults = this.doSearch_(this.search, dashboards);\n"
+ " var searchResultsShow = searchResults.length > 0;\n\n"
+ " this.searchResults = searchResults;\n"
+ " this.saveAutoCompleteEvent_();\n"
+ "};\n\n"
+ "/**\n"
+ " * Logs autocomplete search.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.saveAutoCompleteEvent_ = function() {\n"
+ " var urlQuery = this.location_.url();\n"
+ " // @see onlinesales.revenueprograms.sas.discovery.server.services.UserEventProvider\n"
+ " var endpoint = this.getUserEventResource_('persist');\n"
+ " var evnt = {\n"
+ " type: User.Event.SEARCH,\n"
+ " urlQuery: urlQuery,\n"
+ " search: this.search,\n"
+ " session: smbuser.session\n"
+ " };\n"
+ " endpoint.save(evnt);\n"
+ "};\n\n"
+ "/**\n"
+ " * Logs search result click.\n"
+ " * @param {number} dashboardId the id of the relavant dashboard\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.saveSearchResultClick_ = function(dashboardId) {\n"
+ " var urlQuery = this.location_.url();\n"
+ " // @see onlinesales.revenueprograms.sas.discovery.server.services.UserEventProvider\n"
+ " var endpoint = this.getUserEventResource_('persist');\n"
+ " var evnt = {\n"
+ " dashboardId: dashboardId,\n"
+ " type: User.Event.SEARCH_CLICK,\n"
+ " urlQuery: urlQuery,\n"
+ " search: this.search,\n"
+ " session: smbuser.session\n"
+ " };\n"
+ " endpoint.save(evnt);\n"
+ "};\n\n"
+ "/**\n"
+ " * @param {string} action The action path for which to get endpoint.\n"
+ " * @return {!ngResource} Angular resource for the action on user events.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.getUserEventResource_ = function(action) {\n"
+ " return this.resource_(\n"
+ " goog.string.format('%s/%s', User.EVENT_ENDPOINT, action));\n"
+ "};\n\n"
+ "/**\n"
+ " * Currently returns the arguments, here because of past and potentially\n"
+ " * future formatting.\n"
+ " * @param {string} tag The tag string.\n"
+ " * @return {string} the tag display text\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.getTagDisplayText = goog.functions.identity;\n\n"
+ "/**\n"
+ " * Gets the class for the given tag.\n"
+ " * @param {string} tag The tag.\n"
+ " * @return {string} The class name.\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.getTagDisplayClass = function(tag) {\n"
+ " if (tag) {\n"
+ " var strArr = tag.split(':');\n"
+ " if (strArr.length == 2) {\n"
+ " return goog.string.format('tags-style-%s', strArr[0]);\n"
+ " } else {\n"
+ " return '';\n"
+ " }\n"
+ " }\n"
+ " return '';\n"
+ "};\n\n"
+ "/**\n"
+ " * Goes to the search results page, if that feature is enabled.\n"
+ " *\n"
+ " * @param {!jQuery.Event|!JQLite.Event} evt The fired event on keypress.\n"
+ " *\n"
+ " * @export\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.searchBoxKeypressed = function(evt) {\n"
+ "};\n\n"
+ "/**\n"
+ " * Handler for clicking search result item. Navigates to the dashboard.\n"
+ " * @param {!smb.model.Dashboard} dashboard The dashboard selection clicked.\n"
+ " * @param {!jQuery.Event|!JQLite.Event} $event The event for the click.\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.resultItemClicked = function(dashboard, $event) {\n"
+ " $event.stopPropagation();\n"
+ " this.saveSearchResultClick_(dashboard.id);\n"
+ " this.navigateToDashboard_(dashboard);\n"
+ "};\n\n"
+ "/**\n"
+ " * Navigates to the given dashboard.\n"
+ " * @param {!smb.model.Dashboard} dashboard The dashboard to navigate to.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.navigateToDashboard_ = function(dashboard) {\n"
+ " this.reset_();\n"
+ " this.location_.search({});\n"
+ " this.location_.path(dashboard.navigationURLPath);\n"
+ " this.route_.reload();\n"
+ "};\n\n"
+ "/**\n"
+ " * @param {!SearchboxForDashboards.SearchResultStruct} resultObj Representation of the\n"
+ " * search result.\n"
+ " * @return {?string} The title text for the search result, if there is any.\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.getTitleText = function(resultObj) {\n"
+ " var dash = resultObj.dashboard;\n"
+ " return dash.titleDisplayText || dash.menuDisplayText;\n"
+ "};\n\n"
+ "/**\n"
+ " * @param {!SearchboxForDashboards.SearchResultStruct} resultObj Representation of the\n"
+ " * search result.\n"
+ " * @return {string} The description text for the search result.\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.getDescriptionText = function(resultObj) {\n"
+ " return resultObj.dashboard.flatDescription;\n"
+ "};\n\n"
+ "/**\n"
+ " * @return {boolean} Whether to show the search box on this page.\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.shouldShowResultBox = function() {\n"
+ " // Shows when it is active, there are results, and there is a search\n"
+ " return this.scope_.active && !this.hasNoSearchResults_() &&\n"
+ " this.search.length > 0;\n"
+ "};\n\n"
+ "/**\n"
+ " * Sets the search text to the empty string.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.clearSearchBoxText_ = function() {\n"
+ " this.search = '';\n"
+ "};\n\n"
+ "/**\n"
+ " * Sets the search results to an empty array.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.clearSearchResults_ = function() {\n"
+ " this.searchResults = [];\n"
+ "};\n\n"
+ "/**\n"
+ " * Reverts to initial state.\n"
+ " * @private\n"
+ " */\n"
+ "SearchboxForDashboards.prototype.reset_ = function() {\n"
+ " this.clearSearchBoxText_();\n"
+ " this.clearSearchResults_();\n"
+ "};\n\n"
+ "}); // goog.scope\n";
final String subst = "($1) => $2";
final Pattern pattern = Pattern.compile(regex);
final Matcher matcher = pattern.matcher(string);
// The substituted value will be contained in the result variable
final String result = matcher.replaceAll(subst);
System.out.println("Substitution result: " + result);
}
}
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Java, please visit: https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html