func()

in src/go/util/httppattern/sort_impl.go [139:222]


func (hn *httpPatternTrieNode) traverse(result *MethodSlice) {
	appendMethodOnCurrentNode := func() {

		// Sort the method in alphabet order to generate deterministic sequence for better unit testing.
		var sortedKeys []string
		// Put the wildcard method in the end.
		var wildMethodResult *lookupResult
		for key, val := range hn.ResultMap {
			if key == HttpMethodWildCard {
				wildMethodResult = val
				continue
			}
			sortedKeys = append(sortedKeys, key)
		}
		sort.Strings(sortedKeys)

		for _, key := range sortedKeys {
			if val, ok := hn.ResultMap[key]; ok {
				result.AppendMethod(val.data.Method)
			}
		}

		// Put the wildcard method in the end.
		if wildMethodResult != nil {
			result.AppendMethod(wildMethodResult.data.Method)
		}

	}

	traverseChildren := func() {
		var singleParameterChild *httpPatternTrieNode
		var singleWildCardChild *httpPatternTrieNode
		var doubleWildCardChild *httpPatternTrieNode
		var exactMatchChildKeys []string
		for key, child := range hn.Children {
			switch key {
			case SingleParameterKey:
				singleParameterChild = child
			case SingleWildCardKey:
				singleWildCardChild = child
			case DoubleWildCardKey:
				doubleWildCardChild = child
			default:
				exactMatchChildKeys = append(exactMatchChildKeys, key)
			}
		}

		// Visit exact match children first.
		// Sort the child keys to generate deterministic sequence for better unit testing.
		sort.Strings(exactMatchChildKeys)
		for _, key := range exactMatchChildKeys {
			if child, ok := hn.Children[key]; ok {
				child.traverse(result)
			}
		}

		// Visit vague match children after.
		for _, child := range []*httpPatternTrieNode{singleParameterChild, singleWildCardChild, doubleWildCardChild} {
			if child != nil {
				child.traverse(result)
			}
		}
	}

	// If the current node is wildcard(**), its children has higher priority.
	// For the wildcard case, it is necessary to traverse children then collect
	// the current node.
	// ex. /**/a
	//     /**
	//
	// For the non-wildcard, it is necessary to collect the current node then
	// traver children.
	// ex. /a
	//     /a/b
	if hn.WildCard {
		// Pre-order traverse.
		traverseChildren()
		// Post-order traverse.
		appendMethodOnCurrentNode()
	} else {
		appendMethodOnCurrentNode()
		traverseChildren()
	}
}