<commit_before>package main

import (
	"fmt"

	"github.com/infobloxopen/themis/pdp"

	log "github.com/Sirupsen/logrus"
	"gopkg.in/yaml.v2"
)

const (
	PatchOpAdd     = "add"
	PatchOpDelete  = "delete"
	PatchOpRefresh = "refresh"
)

type PatchItem struct {
	Op     string
	Path   []string
	Entity interface{}

	pathIndex int
}

func (pi *PatchItem) getID() string {
	if len(pi.Path) == 0 {
		return ""
	}
	return pi.Path[pi.pathIndex]
}

func (pi *PatchItem) nextID() bool {
	if len(pi.Path) <= pi.pathIndex+1 {
		return false
	}

	pi.pathIndex++
	return true
}

type policiesPatchCtx struct {
	// Current item in the original tree.
	ocur interface{}
	// Current item in the patched tree.
	cur interface{}
	// Parent (previous) item in the patched tree.
	prev interface{}

	pi *PatchItem
}

func (ctx *policiesPatchCtx) errorf(format string, args ...interface{}) error {
	msg := fmt.Sprintf(format, args...)
	return fmt.Errorf("Failed to apply [%s:%v]: %s", ctx.pi.Op, ctx.pi.Path, msg)
}

func (s *Server) untrackAffectedPolicies(path []string) {
	k := s.Ctx.PolicyIndexKey(path)
	delete(s.AffectedPolicies, k)
}

func copyAndUpdateAlg(e pdp.EvaluableType) {
	switch e := e.(type) {
	case *pdp.PolicySetType:
		if e.AlgParams != nil {
			m := e.AlgParams.(*pdp.MapperPCAParams)
			mcpy := *m
			pmap := make(map[string]pdp.EvaluableType)
			for _, p := range e.Policies {
				pmap[p.GetID()] = p
				if mcpy.DefaultPolicy != nil && mcpy.DefaultPolicy.GetID() == p.GetID() {
					mcpy.DefaultPolicy = p
				}
			}
			mcpy.PoliciesMap = pmap
			e.AlgParams = &mcpy
		}
	case *pdp.PolicyType:
		if e.AlgParams != nil {
			m := e.AlgParams.(*pdp.MapperRCAParams)
			mcpy := *m
			rmap := make(map[string]*pdp.RuleType)
			for _, r := range e.Rules {
				rmap[r.ID] = r
				if mcpy.DefaultRule != nil && mcpy.DefaultRule.ID == r.ID {
					mcpy.DefaultRule = r
				}
			}
			mcpy.RulesMap = rmap
			e.AlgParams = &mcpy
		}
	default:
		panic(fmt.Sprintf("Unsupported policies item type '%T'", e))
	}
}

func copyPoliciesItem(item interface{}, parent interface{}, i int) interface{} {
	switch item := item.(type) {
	case *pdp.PolicySetType:
		cpy := *item
		cpy.Policies = make([]pdp.EvaluableType, len(item.Policies), len(item.Policies))
		copy(cpy.Policies, item.Policies)
		if parent != nil {
			ppset := parent.(*pdp.PolicySetType)
			ppset.Policies[i] = &cpy
			copyAndUpdateAlg(ppset)
		}
		return &cpy
	case *pdp.PolicyType:
		cpy := *item
		cpy.Rules = make([]*pdp.RuleType, len(item.Rules), len(item.Rules))
		copy(cpy.Rules, item.Rules)
		if parent != nil {
			ppset := parent.(*pdp.PolicySetType)
			ppset.Policies[i] = &cpy
			copyAndUpdateAlg(ppset)
		}
		return &cpy<commit_msg>Fix 'error policy' handling for PDP incremental update (#49)<commit_after>package main

import (
	"fmt"

	"github.com/infobloxopen/themis/pdp"

	log "github.com/Sirupsen/logrus"
	"gopkg.in/yaml.v2"
)

const (
	PatchOpAdd     = "add"
	PatchOpDelete  = "delete"
	PatchOpRefresh = "refresh"
)

type PatchItem struct {
	Op     string
	Path   []string
	Entity interface{}

	pathIndex int
}

func (pi *PatchItem) getID() string {
	if len(pi.Path) == 0 {
		return ""
	}
	return pi.Path[pi.pathIndex]
}

func (pi *PatchItem) nextID() bool {
	if len(pi.Path) <= pi.pathIndex+1 {
		return false
	}

	pi.pathIndex++
	return true
}

type policiesPatchCtx struct {
	// Current item in the original tree.
	ocur interface{}
	// Current item in the patched tree.
	cur interface{}
	// Parent (previous) item in the patched tree.
	prev interface{}

	pi *PatchItem
}

func (ctx *policiesPatchCtx) errorf(format string, args ...interface{}) error {
	msg := fmt.Sprintf(format, args...)
	return fmt.Errorf("Failed to apply [%s:%v]: %s", ctx.pi.Op, ctx.pi.Path, msg)
}

func (s *Server) untrackAffectedPolicies(path []string) {
	k := s.Ctx.PolicyIndexKey(path)
	delete(s.AffectedPolicies, k)
}

func copyAndUpdateAlg(e pdp.EvaluableType) {
	switch e := e.(type) {
	case *pdp.PolicySetType:
		if e.AlgParams != nil {
			m := e.AlgParams.(*pdp.MapperPCAParams)
			mcpy := *m
			pmap := make(map[string]pdp.EvaluableType)
			for _, p := range e.Policies {
				pmap[p.GetID()] = p
				if mcpy.DefaultPolicy != nil && mcpy.DefaultPolicy.GetID() == p.GetID() {
					mcpy.DefaultPolicy = p
				}
				if mcpy.ErrorPolicy != nil && mcpy.ErrorPolicy.GetID() == p.GetID() {
					mcpy.ErrorPolicy = p
				}
			}
			mcpy.PoliciesMap = pmap
			e.AlgParams = &mcpy
		}
	case *pdp.PolicyType:
		if e.AlgParams != nil {
			m := e.AlgParams.(*pdp.MapperRCAParams)
			mcpy := *m
			rmap := make(map[string]*pdp.RuleType)
			for _, r := range e.Rules {
				rmap[r.ID] = r
				if mcpy.DefaultRule != nil && mcpy.DefaultRule.ID == r.ID {
					mcpy.DefaultRule = r
				}
				if mcpy.ErrorRule != nil && mcpy.ErrorRule.ID == r.ID {
					mcpy.ErrorRule = r
				}
			}
			mcpy.RulesMap = rmap
			e.AlgParams = &mcpy
		}
	default:
		panic(fmt.Sprintf("Unsupported policies item type '%T'", e))
	}
}

func copyPoliciesItem(item interface{}, parent interface{}, i int) interface{} {
	switch item := item.(type) {
	case *pdp.PolicySetType:
		cpy := *item
		cpy.Policies = make([]pdp.EvaluableType, len(item.Policies), len(item.Policies))
		copy(cpy.Policies, item.Policies)
		if parent != nil {
			ppset := parent.(*pdp.PolicySetType)
			ppset.Policies[i] = &cpy
			copyAndUpdateAlg(ppset)
		}
		return &cpy
	case *pdp.PolicyType:
		cpy := *item
		cpy.Rules = make([]*pdp.RuleType, len(item.Rules), len(item.Rules))
		copy(cpy.Rules, item.Rules)
		if parent != nil {
			ppset := parent.(*pdp.PolicySetType)
			ppset.Policies[i] = &cpy
			copyAndUpdateAlg(ppset)
		}
		return &cpy
{'fraction_non_alphanumeric': 0.15202281233291748, 'fraction_numerical': 0.0014257708073427196, 'mean_word_length': 3.3605283605283605, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, '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': '5366731', 'n_tokens_mistral': 2367, 'n_tokens_neox': 2188, 'n_words': 479}