<commit_before>package resolve

import (
	"github.com/Aptomi/aptomi/pkg/lang"
	"strings"
)

// componentInstanceKeySeparator is a separator between strings in ComponentInstanceKey
const componentInstanceKeySeparator = "#"

// componentUnresolvedName is placeholder for unresolved entries
const componentUnresolvedName = "unknown"

// componentRootName is a name of component for service entry (which in turn consists of components)
const componentRootName = "root"

// ComponentInstanceKey is a key for component instance. During policy resolution every component instance gets
// assigned a unique string key. It's important to form those keys correctly, so that we can make actual comparison
// of actual state (components with their keys) and desired state (components with their keys).
//
// Currently, component keys are formed from multiple parameters as follows.
// Cluster gets included as a part of the key (components running on different clusters must have different keys).
// Namespace gets included as a part of the key (components from different namespaces must have different keys).
// Contract, Context (with allocation keys), Service get included as a part of the key (Service must be within the same namespace as Contract).
// ComponentName gets included as a part of the key. For service-level component instances, ComponentName is
// set to componentRootName, while for all component instances within a service an actual Component.Name is used.
type ComponentInstanceKey struct {
	// cached version of component key
	key string

	// required fields
	ClusterName         string // mandatory
	Namespace           string // determined from the contract
	ContractName        string // mandatory
	ContextName         string // mandatory
	KeysResolved        string // mandatory
	ContextNameWithKeys string // calculated
	ServiceName         string // determined from the context (included into key for readability)
	ComponentName       string // component name
}

// NewComponentInstanceKey creates a new ComponentInstanceKey
func NewComponentInstanceKey(cluster *lang.Cluster, contract *lang.Contract, context *lang.Context, allocationKeysResolved []string, service *lang.Service, component *lang.ServiceComponent) *ComponentInstanceKey {
	contextName := getContextNameUnsafe(context)
	keysResolved := strings.Join(allocationKeysResolved, componentInstanceKeySeparator)
	contextNameWithKeys := strings.Join([]string{contextName, keysResolved}, componentInstanceKeySeparator)
	return &ComponentInstanceKey{
		ClusterName:         getClusterNameUnsafe(cluster),
		Namespace:           getContractNamespaceUnsafe(contract),
		ContractName:        getContractNameUnsafe(contract),
		ContextName:         contextName,
		KeysResolved:        keysResolved,
		ContextNameWithKeys: contextNameWithKeys,
		ServiceName:         getServiceNameUnsafe(service),
		ComponentName:       getComponentNameUnsafe(component),
	}
}

// MakeCopy creates a copy of ComponentInstanceKey
func (cik *ComponentInstanceKey) MakeCopy() *ComponentInstanceKey {
	return &ComponentInstanceKey{
		ClusterName:         cik.ClusterName,
		Namespace:           cik.Namespace,
		ContractName:        cik.ContractName,
		ContextName:         cik.ContextName,
		KeysResolved:        cik.KeysResolved,
		ContextNameWithKeys: cik.ContextNameWithKeys,
		ComponentName:       cik.ComponentName,
	}
}

// IsService returns 'true' if it's a contract instance key and we can't go up anymore. And it will return 'false' if it's a component instance key
func (cik *ComponentInstanceKey) IsService() bool {<commit_msg>fixed component key generation (do not add revolved keys if they are empty)<commit_after>package resolve

import (
	"github.com/Aptomi/aptomi/pkg/lang"
	"strings"
)

// componentInstanceKeySeparator is a separator between strings in ComponentInstanceKey
const componentInstanceKeySeparator = "#"

// componentUnresolvedName is placeholder for unresolved entries
const componentUnresolvedName = "unknown"

// componentRootName is a name of component for service entry (which in turn consists of components)
const componentRootName = "root"

// ComponentInstanceKey is a key for component instance. During policy resolution every component instance gets
// assigned a unique string key. It's important to form those keys correctly, so that we can make actual comparison
// of actual state (components with their keys) and desired state (components with their keys).
//
// Currently, component keys are formed from multiple parameters as follows.
// Cluster gets included as a part of the key (components running on different clusters must have different keys).
// Namespace gets included as a part of the key (components from different namespaces must have different keys).
// Contract, Context (with allocation keys), Service get included as a part of the key (Service must be within the same namespace as Contract).
// ComponentName gets included as a part of the key. For service-level component instances, ComponentName is
// set to componentRootName, while for all component instances within a service an actual Component.Name is used.
type ComponentInstanceKey struct {
	// cached version of component key
	key string

	// required fields
	ClusterName         string // mandatory
	Namespace           string // determined from the contract
	ContractName        string // mandatory
	ContextName         string // mandatory
	KeysResolved        string // mandatory
	ContextNameWithKeys string // calculated
	ServiceName         string // determined from the context (included into key for readability)
	ComponentName       string // component name
}

// NewComponentInstanceKey creates a new ComponentInstanceKey
func NewComponentInstanceKey(cluster *lang.Cluster, contract *lang.Contract, context *lang.Context, allocationKeysResolved []string, service *lang.Service, component *lang.ServiceComponent) *ComponentInstanceKey {
	contextName := getContextNameUnsafe(context)
	keysResolved := strings.Join(allocationKeysResolved, componentInstanceKeySeparator)
	contextNameWithKeys := contextName
	if len(keysResolved) > 0 {
		contextNameWithKeys = strings.Join([]string{contextNameWithKeys, keysResolved}, componentInstanceKeySeparator)
	}
	return &ComponentInstanceKey{
		ClusterName:         getClusterNameUnsafe(cluster),
		Namespace:           getContractNamespaceUnsafe(contract),
		ContractName:        getContractNameUnsafe(contract),
		ContextName:         contextName,
		KeysResolved:        keysResolved,
		ContextNameWithKeys: contextNameWithKeys,
		ServiceName:         getServiceNameUnsafe(service),
		ComponentName:       getComponentNameUnsafe(component),
	}
}

// MakeCopy creates a copy of ComponentInstanceKey
func (cik *ComponentInstanceKey) MakeCopy() *ComponentInstanceKey {
	return &ComponentInstanceKey{
		ClusterName:         cik.ClusterName,
		Namespace:           cik.Namespace,
		ContractName:        cik.ContractName,
		ContextName:         cik.ContextName,
		KeysResolved:        cik.KeysResolved,
		ContextNameWithKeys: cik.ContextNameWithKeys,
		ComponentName:       cik.ComponentName,
	}
}

// IsService returns 'true' if it's a contract instance key and we can't go up anymore. And it will return 'false' if it's a component instance key
func (cik *ComponentInstanceKey) IsService() bool {
{'fraction_non_alphanumeric': 0.06404817298480908, 'fraction_numerical': 0.0001368550704803613, 'mean_word_length': 4.280346820809249, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, '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': '2630233', 'n_tokens_mistral': 1780, 'n_tokens_neox': 1736, 'n_words': 697}