<commit_before>package manifest

import (
	"errors"
	"fmt"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"code.cloudfoundry.org/cli/plugin/models"
	"code.cloudfoundry.org/cli/utils/words/generator"
)

type Manifest struct {
	Path string
	Data map[string]interface{}
}

func T(input string, rest ...interface{}) string {
	return input
}

func NewEmptyManifest() (m *Manifest) {
	return &Manifest{Data: make(map[string]interface{})}
}

func (m Manifest) Applications(defaultDomain string) ([]plugin_models.GetAppModel, error) {
	fmt.Println("In Applications(), this is", m)
	rawData, err := expandProperties(m.Data, generator.NewWordGenerator())
	fmt.Println("rawdata is", rawData)
	data := rawData.(map[string]interface{})
	fmt.Println("now data is", data)

	if err != nil {
		fmt.Println("OOH BAD, ERROR")

		return []plugin_models.GetAppModel{}, err
	}

	appMaps, err := m.getAppMaps(data)
	if err != nil {
		return []plugin_models.GetAppModel{}, err
	}
	var apps []plugin_models.GetAppModel
	var mapToAppErrs []error
	for _, appMap := range appMaps {
		app, err := mapToAppParams(filepath.Dir(m.Path), appMap, defaultDomain)
		if err != nil {
			mapToAppErrs = append(mapToAppErrs, err)
			continue
		}

		apps = append(apps, app)
	}

	if len(mapToAppErrs) > 0 {
		fmt.Println("OOH BAD, ERROR")
		message := ""
		for i := range mapToAppErrs {
			message = message + fmt.Sprintf("%s\n", mapToAppErrs[i].Error())
		}
		return []plugin_models.GetAppModel{}, errors.New(message)
	}

	fmt.Println("returning applications() ", apps)
	return apps, nil
}

// TODO we should have a test for this
func cloneWithExclude(data map[string]interface{}, excludedKey string) map[string]interface{} {
	otherMap := make(map[string]interface{})
	for key, value := range data {
		if excludedKey != key {
			otherMap[key] = value
		}
	}
	return otherMap
}

func (m Manifest) getAppMaps(data map[string]interface{}) ([]map[string]interface{}, error) {
	fmt.Println("HELLO, data is", data)
	globalProperties := cloneWithExclude(data, "applications")
	fmt.Println("global properties is ", globalProperties)

	var apps []map[string]interface{}
	var errs []error
	fmt.Println("HELLO, data is still ", data)
	appMaps, ok := data["applications"].([]interface{})
	if ok {
		fmt.Println("app maps")
		fmt.Println(appMaps)

		if !ok {
			return []map[string]interface{}{}, errors.New(T("Expected applications to be a list"))
		}

		for _, appData := range appMaps {
			if !IsMappable(appData) {
				errs = append(errs, fmt.Errorf(T("Expected application to be a list of key/value pairs\nError occurred in manifest near:\n'{{.YmlSnippet}}'",
					map[string]interface{}{"YmlSnippet": appData})))
				continue
			}

			appMap := DeepMerge(globalProperties, Mappify(appData))
			apps = append(apps, appMap)
			fmt.Println(appData)
		}
	} else {
		fmt.Println("HOLLY no applications, doing empty append")
		apps = append(apps, globalProperties)
	}

	if len(errs) > 0 {
		message := ""
		for i := range errs {
			message = message + fmt.Sprintf("%s\n", errs[i].Error())
		}
		return []map[string]interface{}{}, errors.New(message)
	}
	fmt.Println("HOLLY return")
	fmt.Println(apps)

	return apps, nil
}

var propertyRegex = regexp.MustCompile(`\${[\w-]+}`)

func expandProperties(input interface{}, babbler generator.WordGenerator) (interface{}, error) {
	var errs []error
	var output interface{}

	switch input := input.(type) {
	case string:
		match := propertyRegex.FindStringSubmatch(input)
		if match != nil {
			if match[0] == "${random-word}" {
				output = strings.Replace(input, "${random-word}", strings.ToLower(babbler.Babble()), -1)
			} else {
				err := fmt.Errorf(T("Property '{{.PropertyName}}' found in manifest. This feature is no longer supported. Please remove it and try again.",
					map[string]interface{}{"PropertyName": match[0]}))
				errs = append(errs, err)
			}
		} else {
			output = input
		}
	case []interface{}:
		outputSlice := make([]interface{}, len(input))
		for index, item := range input {
			itemOutput, itemErr := expandProperties(item, babbler)
			if itemErr != nil {
				errs = append(errs, itemErr)
				break
			}
			outputSlice[index] = itemOutput
		}
		output = outputSlice
	case map[interface{}]interface{}:
		fmt.Println("EXPANDING INTERFACEKEY MAP")

		outputMap := make(map[interface{}]interface{})
		for key, value := range input {
			itemOutput, itemErr := expandProperties(value, babbler)
			if itemErr != nil {
				errs = append(errs, itemErr)
				break
			}
			outputMap[key] = itemOutput
		}
		output = outputMap
	case map[string]interface{}:
		fmt.Println("EXPANDING STRINGKEY MAP")
		fmt.Println(input)
		fmt.Println("that was the map")
		outputMap := make(map[string]interface{})
		for key, value := range input {
			fmt.Println(key)
			fmt.Println(value)
			itemOutput, itemErr := expandProperties(value, babbler)
			if itemErr != nil {
				errs = append(errs, itemErr)
				break
			}
			outputMap[key] = itemOutput
		}
		output = outputMap
	default:
		output = input
	}

	if len(errs) > 0 {
		message := ""
		for _, err := range errs {
			message = message + fmt.Sprintf("%s\n", err.Error())
		}
		return nil, errors.New(message)
	}

	fmt.Println("expand properties returning")
	fmt.Println(output)
	return output, nil
}
<commit_msg>Eliminate cf cli word generator dependency<commit_after>package manifest

import (
	"errors"
	"fmt"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"code.cloudfoundry.org/cli/plugin/models"
	"github.com/Pallinder/go-randomdata"
)

type Manifest struct {
	Path string
	Data map[string]interface{}
}

func T(input string, rest ...interface{}) string {
	return input
}

func NewEmptyManifest() (m *Manifest) {
	return &Manifest{Data: make(map[string]interface{})}
}

func (m Manifest) Applications(defaultDomain string) ([]plugin_models.GetAppModel, error) {
	fmt.Println("In Applications(), this is", m)
	rawData, err := expandProperties(m.Data)
	fmt.Println("rawdata is", rawData)
	data := rawData.(map[string]interface{})
	fmt.Println("now data is", data)

	if err != nil {
		fmt.Println("OOH BAD, ERROR")

		return []plugin_models.GetAppModel{}, err
	}

	appMaps, err := m.getAppMaps(data)
	if err != nil {
		return []plugin_models.GetAppModel{}, err
	}
	var apps []plugin_models.GetAppModel
	var mapToAppErrs []error
	for _, appMap := range appMaps {
		app, err := mapToAppParams(filepath.Dir(m.Path), appMap, defaultDomain)
		if err != nil {
			mapToAppErrs = append(mapToAppErrs, err)
			continue
		}

		apps = append(apps, app)
	}

	if len(mapToAppErrs) > 0 {
		fmt.Println("OOH BAD, ERROR")
		message := ""
		for i := range mapToAppErrs {
			message = message + fmt.Sprintf("%s\n", mapToAppErrs[i].Error())
		}
		return []plugin_models.GetAppModel{}, errors.New(message)
	}

	fmt.Println("returning applications() ", apps)
	return apps, nil
}

// TODO we should have a test for this
func cloneWithExclude(data map[string]interface{}, excludedKey string) map[string]interface{} {
	otherMap := make(map[string]interface{})
	for key, value := range data {
		if excludedKey != key {
			otherMap[key] = value
		}
	}
	return otherMap
}

func (m Manifest) getAppMaps(data map[string]interface{}) ([]map[string]interface{}, error) {
	fmt.Println("HELLO, data is", data)
	globalProperties := cloneWithExclude(data, "applications")
	fmt.Println("global properties is ", globalProperties)

	var apps []map[string]interface{}
	var errs []error
	fmt.Println("HELLO, data is still ", data)
	appMaps, ok := data["applications"].([]interface{})
	if ok {
		fmt.Println("app maps")
		fmt.Println(appMaps)

		if !ok {
			return []map[string]interface{}{}, errors.New(T("Expected applications to be a list"))
		}

		for _, appData := range appMaps {
			if !IsMappable(appData) {
				errs = append(errs, fmt.Errorf(T("Expected application to be a list of key/value pairs\nError occurred in manifest near:\n'{{.YmlSnippet}}'",
					map[string]interface{}{"YmlSnippet": appData})))
				continue
			}

			appMap := DeepMerge(globalProperties, Mappify(appData))
			apps = append(apps, appMap)
			fmt.Println(appData)
		}
	} else {
		fmt.Println("HOLLY no applications, doing empty append")
		apps = append(apps, globalProperties)
	}

	if len(errs) > 0 {
		message := ""
		for i := range errs {
			message = message + fmt.Sprintf("%s\n", errs[i].Error())
		}
		return []map[string]interface{}{}, errors.New(message)
	}
	fmt.Println("HOLLY return")
	fmt.Println(apps)

	return apps, nil
}

var propertyRegex = regexp.MustCompile(`\${[\w-]+}`)

func expandProperties(input interface{}) (interface{}, error) {
	var errs []error
	var output interface{}

	switch input := input.(type) {
	case string:
		match := propertyRegex.FindStringSubmatch(input)
		if match != nil {
			if match[0] == "${random-word}" {
				// TODO we need a test for a manifest with ${random-word}
				output = strings.Replace(input, "${random-word}", strings.ToLower(randomdata.SillyName()), -1)
			} else {
				err := fmt.Errorf(T("Property '{{.PropertyName}}' found in manifest. This feature is no longer supported. Please remove it and try again.",
					map[string]interface{}{"PropertyName": match[0]}))
				errs = append(errs, err)
			}
		} else {
			output = input
		}
	case []interface{}:
		outputSlice := make([]interface{}, len(input))
		for index, item := range input {
			itemOutput, itemErr := expandProperties(item)
			if itemErr != nil {
				errs = append(errs, itemErr)
				break
			}
			outputSlice[index] = itemOutput
		}
		output = outputSlice
	case map[interface{}]interface{}:
		fmt.Println("EXPANDING INTERFACEKEY MAP")

		outputMap := make(map[interface{}]interface{})
		for key, value := range input {
			itemOutput, itemErr := expandProperties(value)
			if itemErr != nil {
				errs = append(errs, itemErr)
				break
			}
			outputMap[key] = itemOutput
		}
		output = outputMap
	case map[string]interface{}:
		fmt.Println("EXPANDING STRINGKEY MAP")
		fmt.Println(input)
		fmt.Println("that was the map")
		outputMap := make(map[string]interface{})
		for key, value := range input {
			fmt.Println(key)
			fmt.Println(value)
			itemOutput, itemErr := expandProperties(value)
			if itemErr != nil {
				errs = append(errs, itemErr)
				break
			}
			outputMap[key] = itemOutput
		}
		output = outputMap
	default:
		output = input
	}

	if len(errs) > 0 {
		message := ""
		for _, err := range errs {
			message = message + fmt.Sprintf("%s\n", err.Error())
		}
		return nil, errors.New(message)
	}

	fmt.Println("expand properties returning")
	fmt.Println(output)
	return output, nil
}

{'fraction_non_alphanumeric': 0.14892605968447065, 'fraction_numerical': 0.0011404675917126021, 'mean_word_length': 4.193978282329714, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5698955', 'n_tokens_mistral': 3923, 'n_tokens_neox': 3561, 'n_words': 877}