text:
#include <pcl/apps/modeler/abstract_worker.h>

#include <pcl/apps/modeler/parameter_dialog.h>
#include <pcl/apps/modeler/cloud_mesh_item.h>

//////////////////////////////////////////////////////////////////////////////////////////////
pcl::modeler::AbstractWorker::AbstractWorker(const QList<CloudMeshItem*>& cloud_mesh_items, QWidget* parent) :
  cloud_mesh_items_(cloud_mesh_items),
  parameter_dialog_(new ParameterDialog(getName(), parent))
{
}

//////////////////////////////////////////////////////////////////////////////////////////////
pcl::modeler::AbstractWorker::~AbstractWorker()
{
  parameter_dialog_->deleteLater();
}

//////////////////////////////////////////////////////////////////////////////////////////////
int
pcl::modeler::AbstractWorker::exec()
{
  for (auto &cloud_mesh_item : cloud_mesh_items_)
    initParameters(cloud_mesh_item);

  setupParameters();

  return (parameter_dialog_->exec());
}

//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::modeler::AbstractWorker::process()
{
  for (auto &cloud_mesh_item : cloud_mesh_items_)
  {
    processImpl(cloud_mesh_item);
  }

  emit finished();

  return;
}

//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::modeler::AbstractWorker::emitDataUpdated(CloudMeshItem* cloud_mesh_item)
{
  emit dataUpdated(cloud_mesh_item);
}


text:
package policy

import (
	"fmt"
	"net"
	"reflect"
	"regexp"
	"strconv"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/osrg/gobgp/api"
	"github.com/osrg/gobgp/config"
	"github.com/osrg/gobgp/packet"
	"github.com/osrg/gobgp/table"
)

type RouteType int

const (
	ROUTE_TYPE_NONE RouteType = iota
	ROUTE_TYPE_ACCEPT
	ROUTE_TYPE_REJECT
)

type MaskLengthRangeType int

const (
	MASK_LENGTH_RANGE_MIN MaskLengthRangeType = iota
	MASK_LENGTH_RANGE_MAX
)

type AttributeComparison int

const (
	// "== comparison"
	ATTRIBUTE_EQ AttributeComparison = iota
	// ">= comparison"
	ATTRIBUTE_GE
	// "<= comparison"
	ATTRIBUTE_LE
)

type Policy struct {
	Name       string
	Statements []*Statement
}

func NewPolicy(pd config.PolicyDefinition, ds config.DefinedSets) *Policy {
	stmtList := pd.Statements.StatementList
	st := make([]*Statement, 0)
	p := &Policy{
		Name: pd.Name,
	}

	for _, statement := range stmtList {
		conditions := make([]Condition, 0)

		// prefix match
		pc := NewPrefixCondition(statement.Conditions.MatchPrefixSet, ds.PrefixSets.PrefixSetList)
		if pc != nil {
			conditions = append(conditions, pc)
		}

		// neighbor match
		nc := NewNeighborCondition(statement.Conditions.MatchNeighborSet, ds.NeighborSets.NeighborSetList)
		if nc != nil {
			conditions = append(conditions, nc)
		}

		// AsPathLengthCondition
		c := statement.Conditions.BgpConditions.AsPathLength
		ac := NewAsPathLengthCondition(c)
		if ac != nil {
			conditions = append(conditions, ac)
		}

		if statement.Conditions.BgpConditions.RpkiValidationResult != config.RPKI_VALIDATION_RESULT_TYPE_NONE {
			conditions = append(conditions, NewRPKIValidationCondition(statement.Conditions.BgpConditions.RpkiValidationResult))
		}

		bgpDefset := &ds.BgpDefinedSets
		bgpConditions := &statement.Conditions.BgpConditions
		// AsPathCondition
		asc := NewAsPathCondition(bgpConditions.MatchAsPathSet, bgpDefset.AsPathSets.AsPathSetList)
		if asc != nil {
			conditions = append(conditions, asc)
		}

		// CommunityCondition
		cc := NewCommunityCondition(bgpConditions.MatchCommunitySet, bgpDefset.CommunitySets.CommunitySetList)
		if cc != nil {
			conditions = append(conditions, cc)
		}

		// ExtendedCommunityCondition
		ecc := NewExtCommunityCondition(bgpConditions.MatchExtCommunitySet, bgpDefset.ExtCommunitySets.ExtCommunitySetList)
		if ecc != nil {
			conditions = append(conditions, ecc)
		}

		// routing action
		ra := NewRoutingAction(statement.Actions)

		// Community action
		mda := make([]Action, 0)
		com := NewCommunityAction(statement.Actions.BgpActions.SetCommunity)
		if com != nil {
			mda = append(mda, com)
		}

		ext := NewExtCommunityAction(statement.Actions.BgpActions.SetExtCommunity)
		if ext != nil {
			mda = append(mda, ext)
		}

		// Med Action
		med := NewMedAction(statement.Actions.BgpActions.SetMed)
		if med != nil {
			mda = append(mda, med)
		}

		//AsPathPrependAction
		ppa := NewAsPathPrependAction(statement.Actions.BgpActions.SetAsPathPrepend)
		if ppa != nil {
			mda = append(mda, ppa)
		}

		s := &Statement{
			Name:                statement.Name,
			Conditions:          conditions,
			routingAction:       ra,
			modificationActions: mda,
		}

		st = append(st, s)
	}
	p.Statements = st
	return p
}

type Statement struct {
	Name                string
	Conditions          []Condition
	routingAction       *RoutingAction
	modificationActions []Action
}

// evaluate each condition in the statement according to MatchSetOptions
func (s *Statement) evaluate(p *table.Path) bool {

	for _, condition := range s.Conditions {
		r := condition.evaluate(p)
		if !r {
			return false
		}
	}
	return true
}

type Condition interface {
	evaluate(*table.Path) bool
}

type DefaultCondition struct {
	CallPolicy string
}

func (c *DefaultCondition) evaluate(path *table.Path) bool {
	return false
}

type PrefixCondition struct {
	DefaultCondition
	PrefixConditionName string
	PrefixList          []Prefix
	MatchOption         config.MatchSetOptionsRestrictedType
}

func NewPrefixCondition(matchPref config.MatchPrefixSet, defPrefixList []config.PrefixSet) *PrefixCondition {

	prefixSetName := matchPref.PrefixSet
	options := matchPref.MatchSetOptions

	prefixList := make([]Prefix, 0)
	for _, ps := range defPrefixList {
		if ps.PrefixSetName == prefixSetName {
			for _, prefix := range ps.PrefixList {
				prefix, e := NewPrefix(prefix.IpPrefix, prefix.MasklengthRange)
				if e != nil {
					log.WithFields(log.Fields{
						"Topic":  "Policy",
						"prefix": prefix,
						"msg":    e,
					}).Error("failed to generate a NewPrefix from configration.")
				} else {
					prefixList = append(prefixList, prefix)
				}
			}
		}
	}

	if len(prefixList) == 0 {
		return nil
	}

	pc := &PrefixCondition{
		PrefixConditionName: prefixSetName,
		PrefixList:          prefixList,
		MatchOption:         options,
	}

	return pc
}

// compare prefixes in this condition and nlri of path and
// subsequent comparison is skipped if that matches the conditions.
// If PrefixList's length is zero, return true.
func (c *PrefixCondition) evaluate(path *table.Path) bool {

	if len(c.PrefixList) == 0 {
		log.Debug("PrefixList doesn't have elements")
		return true
	}

	result := false
	for _, cp := range c.PrefixList {
		if ipPrefixCalculate(path, cp) {
			result = true
			break
		}
	}
	if c.MatchOption == config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT {
		result = !result
	}

	log.WithFields(log.Fields{
		"Topic":     "Policy",
		"Condition": "prefix",
		"Path":      path,
		"Matched":   result,
	}).Debug("evaluate prefix")

	return result
}

type NeighborCondition struct {
	DefaultCondition
	NeighborConditionName string
	NeighborList          []net.IP
	MatchOption           config.MatchSetOptionsRestrictedType
}

func NewNeighborCondition(matchNeighborSet config.MatchNeighborSet, defNeighborSetList []config.NeighborSet) *NeighborCondition {

	neighborSetName := matchNeighborSet.NeighborSet
	options := matchNeighborSet.MatchSetOptions

	neighborList := make([]net.IP, 0)
	for _, neighborSet := range defNeighborSetList {
		if neighborSet.NeighborSetName == neighborSetName {
			for _, nl := range neighborSet.NeighborInfoList {
				neighborList = append(neighborList, nl.Address)
			}
		}
	}

	if len(neighborList) == 0 {
		return nil
	}

	nc := &NeighborCondition{
		NeighborConditionName: neighborSetName,
		NeighborList:          neighborList,
		MatchOption:           options,
	}

	return nc
}

// compare neighbor ipaddress of this condition and source address of path
// and, subsequent comparisons are skipped if that matches the conditions.
// If NeighborList's length is zero, return true.
func (c *NeighborCondition) evaluate(path *table.Path) bool {

	if len(c.NeighborList) == 0 {
		log.Debug("NeighborList doesn't have elements")
		return true
	}

	sAddr := path.GetSource().Address
	result := false
	for _, neighbor := range c.NeighborList {
		if sAddr.Equal(neighbor) {
			result = true
			break
		}
	}

	if c.MatchOption == config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT {
		result = !result
	}

	log.WithFields(log.Fields{
		"Topic":           "Policy",
		"Condition":       "neighbor",
		"NeighborAddress": sAddr.String(),
		"Matched":         result,
	}).Debug("evaluate neighbor")

	return result
}

type AsPathLengthCondition struct {
	DefaultCondition
	Value    uint32
	Operator AttributeComparison
}

// create AsPathLengthCondition object
func NewAsPathLengthCondition(defAsPathLength config.AsPathLength) *AsPathLengthCondition {

	value := defAsPathLength.Value
	var op AttributeComparison

	switch defAsPathLength.Operator {
	case "eq":
		op = ATTRIBUTE_EQ

	case "ge":
		op = ATTRIBUTE_GE

	case "le":
		op = ATTRIBUTE_LE
	default:
		return nil
	}

	ac := &AsPathLengthCondition{
		Value:    value,
		Operator: op,
	}

	return ac
}

// compare AS_PATH length in the message's AS_PATH attribute with
// the one in condition.
func (c *AsPathLengthCondition) evaluate(path *table.Path) bool {

	length := uint32(path.GetAsPathLen())
	result := false

	switch c.Operator {
	case ATTRIBUTE_EQ:
		result = c.Value == length

	case ATTRIBUTE_GE:
		result = c.Value <= length

	case ATTRIBUTE_LE:
		result = c.Value >= length
	default:
		result = false
	}

	log.WithFields(log.Fields{
		"Topic":     "Policy",
		"Condition": "aspath length",
		"Reason":    c.Operator,
		"Matched":   result,
	}).Debug("evaluate aspath length")

	return result
}

type AsPathCondition struct {
	DefaultCondition
	AsRegExpList []*regexp.Regexp
	MatchOption  config.MatchSetOptionsType
}

const (
	ASPATH_REGEXP_MAGIC = "(^|[,{}() ]|$)"
)

func NewAsPathCondition(matchSet config.MatchAsPathSet, defAsPathSetList []config.AsPathSet) *AsPathCondition {
	asPathSetName := matchSet.AsPathSet
	options := matchSet.MatchSetOptions

	asRegExpList := make([]*regexp.Regexp, 0)
	for _, asPathSet := range defAsPathSetList {
		if asPathSet.AsPathSetName == asPathSetName {
			for _, aspath := range asPathSet.AsPathList {
				a := aspath.AsPath
				if len(a) != 0 {
					r, err := regexp.Compile(strings.Replace(a, "_", ASPATH_REGEXP_MAGIC, -1))
					if err != nil {
						log.WithFields(log.Fields{
							"Topic": "Policy",
							"Type":  "AsPath Condition",
							"Value": aspath.AsPath,
							"Error": err,
						}).Error("can not comple AS_PATH values to Regular expressions.")
						return nil
					}

					asRegExpList = append(asRegExpList, r)
				} else {
					log.WithFields(log.Fields{
						"Topic": "Policy",
						"Type":  "AsPath Condition",
					}).Error("does not parse AS_PATH condition value.")
					return nil
				}
			}
			c := &AsPathCondition{
				AsRegExpList: asRegExpList,
				MatchOption:  options,
			}
			return c
		}
	}
	return nil
}

func (c *AsPathCondition) checkMembers(aspathStr string, checkAll bool) bool {
	for _, r := range c.AsRegExpList {
		if r.MatchString(aspathStr) {
			log.WithFields(log.Fields{
				"Topic":     "Policy",
				"Condition": "aspath length",
				"AS":        aspathStr,
				"ASN":       r,
			}).Debug("aspath condition matched")

			if !checkAll {
				return true
			}
		} else {
			if checkAll {
				return false
			}
		}
	}
	return checkAll
}

// compare AS_PATH in the message's AS_PATH attribute with
// the one in condition.
func (c *AsPathCondition) evaluate(path *table.Path) bool {

	aspathStr := path.GetAsString()

	result := false
	if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ALL {
		result = c.checkMembers(aspathStr, true)
	} else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ANY {
		result = c.checkMembers(aspathStr, false)
	} else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_INVERT {
		result = !c.checkMembers(aspathStr, false)
	}

	log.WithFields(log.Fields{
		"Topic":       "Policy",
		"Condition":   "aspath",
		"MatchOption": c.MatchOption,
		"Matched":     result,
	}).Debug("evaluate aspath")

	return result
}

type CommunityCondition struct {
	DefaultCondition
	CommunityList []*CommunityElement
	MatchOption   config.MatchSetOptionsType
}

const (
	COMMUNITY_INTERNET            string = "INTERNET"
	COMMUNITY_NO_EXPORT           string = "NO_EXPORT"
	COMMUNITY_NO_ADVERTISE        string = "NO_ADVERTISE"
	COMMUNITY_NO_EXPORT_SUBCONFED string = "NO_EXPORT_SUBCONFED"
)

const (
	COMMUNITY_INTERNET_VAL            uint32 = 0x00000000
	COMMUNITY_NO_EXPORT_VAL                  = 0xFFFFFF01
	COMMUNITY_NO_ADVERTISE_VAL               = 0xFFFFFF02
	COMMUNITY_NO_EXPORT_SUBCONFED_VAL        = 0xFFFFFF03
)

type CommunityElement struct {
	community       uint32
	communityStr    string
	isRegExp        bool
	communityRegExp *regexp.Regexp
}

// create CommunityCondition object
// CommunityCondition supports uint and string like 65000:100
// and also supports regular expressions that are available in golang.
// if GoBGP can't parse the regular expression, it return nil and an error message is logged.
func NewCommunityCondition(matchSet config.MatchCommunitySet, defCommunitySetList []config.CommunitySet) *CommunityCondition {

	communitySetName := matchSet.CommunitySet
	options := matchSet.MatchSetOptions

	communityList := make([]*CommunityElement, 0)
	for _, communitySet := range defCommunitySetList {
		if communitySet.CommunitySetName == communitySetName {
			for _, community := range communitySet.CommunityList {
				c := community.Community
				e := &CommunityElement{
					isRegExp:     false,
					communityStr: c,
				}

				if matched, v := getCommunityValue(c); matched {
					e.community = v
				} else {
					// specified by regular expression
					e.isRegExp = true
					reg, err := regexp.Compile(c)
					if err != nil {
						log.WithFields(log.Fields{
							"Topic": "Policy",
							"Type":  "Community Condition",
						}).Error("Regular expression can't be compiled.")
						return nil
					}
					e.communityRegExp = reg
				}
				communityList = append(communityList, e)
			}

			c := &CommunityCondition{
				CommunityList: communityList,
				MatchOption:   options,
			}
			return c
		}
	}
	return nil
}

// getCommunityValue returns uint32 community value converted from the string.
// if the string doesn't match a number or string like "65000:1000" or well known
// community name, it returns false and 0, otherwise returns true and its uint32 value.
func getCommunityValue(comStr string) (bool, uint32) {
	// community regexp
	regUint, _ := regexp.Compile("^([0-9]+)$")
	regString, _ := regexp.Compile("([0-9]+):([0-9]+)")
	regWellKnown, _ := regexp.Compile("^(" +
		COMMUNITY_INTERNET + "|" +
		COMMUNITY_NO_EXPORT + "|" +
		COMMUNITY_NO_ADVERTISE + "|" +
		COMMUNITY_NO_EXPORT_SUBCONFED + ")$")

	if regUint.MatchString(comStr) {
		// specified by Uint
		community, err := strconv.ParseUint(comStr, 10, 32)
		if err != nil {
			log.WithFields(log.Fields{
				"Topic": "Policy",
				"Type":  "Community Condition",
			}).Error("failed to parse the community value.")
		}
		return true, uint32(community)

	} else if regString.MatchString(comStr) {
		// specified by string containing ":"
		group := regString.FindStringSubmatch(comStr)
		asn, errAsn := strconv.ParseUint(group[1], 10, 16)
		val, errVal := strconv.ParseUint(group[2], 10, 16)

		if errAsn != nil || errVal != nil {
			log.WithFields(log.Fields{
				"Topic": "Policy",
				"Type":  "Community Condition",
			}).Error("failed to parser as number or community value.")
		}
		community := uint32(asn<<16 | val)
		return true, community

	} else if regWellKnown.MatchString(comStr) {
		// specified by well known community name
		var community uint32
		switch comStr {
		case COMMUNITY_INTERNET:
			community = COMMUNITY_INTERNET_VAL
		case COMMUNITY_NO_EXPORT:
			community = COMMUNITY_NO_EXPORT_VAL
		case COMMUNITY_NO_ADVERTISE:
			community = COMMUNITY_NO_ADVERTISE_VAL
		case COMMUNITY_NO_EXPORT_SUBCONFED:
			community = COMMUNITY_NO_EXPORT_SUBCONFED_VAL
		}
		return true, community
	}
	return false, 0
}

func (c *CommunityCondition) checkMembers(communities []uint32, checkAll bool) bool {

	result := false
	if checkAll {
		result = true
	}

	makeStr := func(c uint32) string {
		upper := strconv.FormatUint(uint64(c&0xFFFF0000>>16), 10)
		lower := strconv.FormatUint(uint64(c&0x0000FFFF), 10)
		return upper + ":" + lower
	}

	var strCommunities []string = nil
	matched := false
	idx := -1
	for _, member := range c.CommunityList {
		if member.isRegExp {

			if strCommunities == nil {
				// create community string.
				strCommunities = make([]string, len(communities))
				for i, c := range communities {
					strCommunities[i] = makeStr(c)
				}
			}

			for i, c := range strCommunities {
				if member.communityRegExp.MatchString(c) {
					matched = true
					idx = i
					log.WithFields(log.Fields{
						"Topic":  "Policy",
						"RegExp": member.communityRegExp.String(),
					}).Debug("community regexp used")
					break
				}
			}

		} else {
			for i, c := range communities {
				if c == member.community {
					matched = true
					idx = i
					break
				}
			}
		}

		if matched {
			log.WithFields(log.Fields{
				"Topic":     "Policy",
				"Condition": "Community",
				"Community": makeStr(communities[idx]),
			}).Debug("condition matched")

			if !checkAll {
				result = true
				break
			}

		} else {
			if checkAll {
				result = false
				break
			}
		}
	}

	return result

}

// compare community in the message's attribute with
// the one in the condition.
func (c *CommunityCondition) evaluate(path *table.Path) bool {

	communities := path.GetCommunities()

	if len(communities) == 0 {
		log.WithFields(log.Fields{
			"Topic":       "Policy",
			"Condition":   "community",
			"MatchOption": c.MatchOption,
			"Matched":     false,
		}).Debug("community length is zero")
		return false
	}

	result := false
	if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ALL {
		result = c.checkMembers(communities, true)
	} else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ANY {
		result = c.checkMembers(communities, false)
	} else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_INVERT {
		result = !c.checkMembers(communities, false)
	}

	log.WithFields(log.Fields{
		"Topic":       "Policy",
		"Condition":   "community",
		"MatchOption": c.MatchOption,
		"Matched":     result,
	}).Debug("evaluate community")

	return result
}

type ExtCommunityCondition struct {
	DefaultCondition
	ExtCommunityList []*ExtCommunityElement
	MatchOption      config.MatchSetOptionsType
}

type ExtCommunityElement struct {
	ecType      bgp.ExtendedCommunityAttrType
	ecSubType   bgp.ExtendedCommunityAttrSubType
	globalAdmin interface{}
	localAdmin  uint32
	comStr      string
	isRegExp    bool
	regExp      *regexp.Regexp
}

func NewExtCommunityCondition(matchSet config.MatchExtCommunitySet, defExtComSetList []config.ExtCommunitySet) *ExtCommunityCondition {

	extComSetName := matchSet.ExtCommunitySet
	option := matchSet.MatchSetOptions

	extCommunityElemList := make([]*ExtCommunityElement, 0)
	for _, extComSet := range defExtComSetList {
		if extComSet.ExtCommunitySetName == extComSetName {
			for _, ecommunity := range extComSet.ExtCommunityList {
				matchAll := false
				ec := ecommunity.ExtCommunity
				e := &ExtCommunityElement{
					isRegExp: false,
					comStr:   ec,
				}
				matchType, val := getECommunitySubType(ec)
				if !matchType {
					log.WithFields(log.Fields{
						"Topic": "Policy",
						"Type":  "Extended Community Condition",
					}).Error("failed to parse the sub type %s.", ec)
					return nil
				}
				switch val[1] {
				case "RT":
					e.ecSubType = bgp.EC_SUBTYPE_ROUTE_TARGET
				case "SoO":
					e.ecSubType = bgp.EC_SUBTYPE_ROUTE_ORIGIN
				default:
					e.ecSubType = bgp.ExtendedCommunityAttrSubType(0xFF)
				}

				if matchVal, elem := getECommunityValue(val[2]); matchVal {
					if matchElem, ecType, gAdmin := getECommunityElem(elem[1]); matchElem {
						e.ecType = ecType
						e.globalAdmin = gAdmin
						lAdmin, err := strconv.ParseUint(elem[2], 10, 32)
						if err != nil {
							log.WithFields(log.Fields{
								"Topic": "Policy",
								"Type":  "Extended Community Condition",
							}).Errorf("failed to parse the local administrator %d.", elem[2])
							return nil
						}
						e.localAdmin = uint32(lAdmin)
						matchAll = true
					}
				}
				if !matchAll {
					e.isRegExp = true
					reg, err := regexp.Compile(ec)
					if err != nil {
						log.WithFields(log.Fields{
							"Topic": "Policy",
							"Type":  "Extended Community Condition",
						}).Errorf("Regular expression can't be compiled %s.", val[2])
						return nil
					}
					e.regExp = reg
				}
				extCommunityElemList = append(extCommunityElemList, e)
			}
			ce := &ExtCommunityCondition{
				ExtCommunityList: extCommunityElemList,
				MatchOption:      option,
			}
			return ce
		}
	}
	return nil
}

func getECommunitySubType(eComStr string) (bool, []string) {
	regSubType, _ := regexp.Compile("^(RT|SoO):(.*)$")
	if regSubType.MatchString(eComStr) {
		eComVal := regSubType.FindStringSubmatch(eComStr)
		return true, eComVal
	}
	return false, nil
}

func getECommunityValue(eComVal string) (bool, []string) {
	regVal, _ := regexp.Compile("^([0-9\\.]+):([0-9]+)$")
	if regVal.MatchString(eComVal) {
		eComElem := regVal.FindStringSubmatch(eComVal)
		return true, eComElem
	}
	return false, nil
}

func getECommunityElem(gAdmin string) (bool, bgp.ExtendedCommunityAttrType, interface{}) {
	addr := net.ParseIP(gAdmin)
	if addr.To4() != nil {
		return true, bgp.EC_TYPE_TRANSITIVE_IP4_SPECIFIC, addr
	}
	regAs, _ := regexp.Compile("^([0-9]+)$")
	if regAs.MatchString(gAdmin) {
		as, err := strconv.ParseUint(gAdmin, 10, 16)
		if err != nil {
			log.WithFields(log.Fields{
				"Topic": "Policy",
				"Type":  "Extended Community Condition",
			}).Errorf("failed to parse the global administrator %d.", gAdmin)
		}
		return true, bgp.EC_TYPE_TRANSITIVE_TWO_OCTET_AS_SPECIFIC, uint16(as)
	}
	regAs4, _ := regexp.Compile("^([0-9]+).([0-9]+)$")
	if regAs4.MatchString(gAdmin) {
		as4Elem := regAs4.FindStringSubmatch(gAdmin)
		highAs, errHigh := strconv.ParseUint(as4Elem[1], 10, 16)
		lowAs, errLow := strconv.ParseUint(as4Elem[2], 10, 16)
		if errHigh != nil || errLow != nil {
			log.WithFields(log.Fields{
				"Topic": "Policy",
				"Type":  "Extended Community Condition",
			}).Errorf("failed to parse the global administrator %d.", gAdmin)
		}
		return true, bgp.EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC, uint32(highAs<<16 | lowAs)
	}
	return false, bgp.ExtendedCommunityAttrType(0xFF), nil
}

func (c *ExtCommunityCondition) checkMembers(eCommunities []bgp.ExtendedCommunityInterface, checkAll bool) bool {

	result := false
	if checkAll {
		result = true
	}

	makeAs4Str := func(ec *ExtCommunityElement) string {
		t := ec.ecType
		str := fmt.Sprintf("%d", ec.localAdmin)
		switch t {
		case bgp.EC_TYPE_TRANSITIVE_TWO_OCTET_AS_SPECIFIC:
			str = fmt.Sprintf("%d:%s", ec.globalAdmin.(uint16), str)
		case bgp.EC_TYPE_TRANSITIVE_IP4_SPECIFIC:
			str = fmt.Sprintf("%s:%s", ec.globalAdmin.(net.IP).String(), str)
		case bgp.EC_TYPE_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC:
			ga := ec.globalAdmin.(uint32)
			upper := strconv.FormatUint(uint64(ga&0xFFFF0000>>16), 10)
			lower := strconv.FormatUint(uint64(ga&0x0000FFFF), 10)
			str = fmt.Sprintf("%s.%s:%s", upper, lower, str)
		}
		return str
	}

	makeTypeSubStr := func(st bgp.ExtendedCommunityAttrSubType) string {
		subStr := ""
		switch st {
		case bgp.EC_SUBTYPE_ROUTE_TARGET:
			subStr = "RT"
		case bgp.EC_SUBTYPE_ROUTE_ORIGIN:
			subStr = "SoO"
		}
		return subStr
	}

	matched := false
	matchStr := ""
	for _, member := range c.ExtCommunityList {
		for _, ec := range eCommunities {
			t, st := ec.GetTypes()
			if member.isRegExp {
				ecString := fmt.Sprintf("%s:%s", makeTypeSubStr(st), ec.String())
				if member.regExp.MatchString(ecString) {
					matched = true
					log.WithFields(log.Fields{
						"Topic":  "Policy",
						"RegExp": member.regExp.String(),
					}).Debug("extended community regexp used")
					matchStr = ec.String()
					break
				}
			} else if member.ecType == t && member.ecSubType == st {
				if makeAs4Str(member) == ec.String() {
					matched = true
					matchStr = ec.String()
					break
				}

			}
		}
		if matched {
			log.WithFields(log.Fields{
				"Topic":              "Policy",
				"Condition":          "Extended Community",
				"Extended Community": matchStr,
			}).Debug("condition matched")

			if !checkAll {
				result = true
				break
			}

		} else {
			if checkAll {
				result = false
				break
			}
		}
	}
	return result
}

// compare extended community in the message's attribute with
// the one in the condition.
func (c *ExtCommunityCondition) evaluate(path *table.Path) bool {

	eCommunities := path.GetExtCommunities()
	if len(eCommunities) == 0 {
		log.WithFields(log.Fields{
			"Topic":     "Policy",
			"Condition": "extended community",
			"Matched":   false,
			"Path":      path,
		}).Debug("extended community length is zero")
		return false
	}

	result := false
	if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ALL {
		result = c.checkMembers(eCommunities, true)
	} else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_ANY {
		result = c.checkMembers(eCommunities, false)
	} else if c.MatchOption == config.MATCH_SET_OPTIONS_TYPE_INVERT {
		result = !c.checkMembers(eCommunities, false)
	}

	log.WithFields(log.Fields{
		"Topic":       "Policy",
		"Condition":   "extended community",
		"MatchOption": c.MatchOption,
		"Matched":     result,
		"Path":        path,
	}).Debug("evaluate extended community")

	return result
}

type RPKIValidationCondition struct {
	result config.RpkiValidationResultType
}

func NewRPKIValidationCondition(result config.RpkiValidationResultType) *RPKIValidationCondition {
	return &RPKIValidationCondition{
		result: result,
	}
}

func (c *RPKIValidationCondition) evaluate(path *table.Path) bool {
	return c.result == path.Validation
}

type Action interface {
	apply(*table.Path) *table.Path
}

type DefaultAction struct {
}

func (a *DefaultAction) apply(path *table.Path) *table.Path {
	return path
}

type RoutingAction struct {
	DefaultAction
	AcceptRoute bool
}

func NewRoutingAction(action config.Actions) *RoutingAction {
	r := &RoutingAction{
		AcceptRoute: action.RouteDisposition.AcceptRoute,
	}
	return r
}

func (r *RoutingAction) apply(path *table.Path) *table.Path {
	if r.AcceptRoute {
		return path
	} else {
		return nil
	}
}

type CommunityAction struct {
	DefaultAction
	Values []uint32
	ext    []byte
	action config.BgpSetCommunityOptionType
}

const (
	COMMUNITY_ACTION_ADD     string = "ADD"
	COMMUNITY_ACTION_REPLACE        = "REPLACE"
	COMMUNITY_ACTION_REMOVE         = "REMOVE"
	COMMUNITY_ACTION_NULL           = "NULL"
)

// NewCommunityAction creates CommunityAction object.
// If it cannot parse community string, then return nil.
// Similarly, if option string is invalid, return nil.
func NewCommunityAction(action config.SetCommunity) *CommunityAction {

	m := &CommunityAction{}
	communities := action.SetCommunityMethod.Communities
	if len(communities) == 0 && action.Options != COMMUNITY_ACTION_REPLACE {
		return nil
	}

	values := make([]uint32, len(communities))
	for i, com := range communities {
		matched, value := getCommunityValue(com)
		if matched {
			values[i] = value
		} else {
			log.WithFields(log.Fields{
				"Topic": "Policy",
				"Type":  "Community Action",
			}).Error("community string invalid.")
			return nil
		}
	}
	m.Values = values

	switch action.Options {
	case COMMUNITY_ACTION_ADD:
		m.action = config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD
	case COMMUNITY_ACTION_REMOVE:
		m.action = config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE
	case COMMUNITY_ACTION_REPLACE:
		m.action = config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE
	default:
		log.WithFields(log.Fields{
			"Topic": "Policy",
			"Type":  "Community Action",
		}).Error("action string should be ADD or REMOVE or REPLACE or NULL.")
		return nil
	}
	return m
}

func (a *CommunityAction) apply(path *table.Path) *table.Path {
	if len(a.ext) > 0 {
		return a.extApply(path)
	}
	list := a.Values
	switch a.action {
	case config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD:
		path.SetCommunities(list, false)
	case config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE:
		path.RemoveCommunities(list)
	case config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE:
		path.SetCommunities(list, true)
	}

	log.WithFields(log.Fields{
		"Topic":  "Policy",
		"Action": "community",
		"Values": list,
		"Method": a.action,
	}).Debug("community action applied")

	return path
}

func (a *CommunityAction) extApply(path *table.Path) *table.Path {
	path.SetExtCommunities(a.ext, false)

	log.WithFields(log.Fields{
		"Topic":  "Policy",
		"Action": "extended community",
		"Values": a.ext,
		"Method": a.action,
	}).Debug("extended community action applied")

	return path
}

func NewExtCommunityAction(action config.SetExtCommunity) *CommunityAction {
	communities := action.SetExtCommunityMethod.Communities
	if len(communities) == 0 {
		return nil
	}

	b := make([]byte, len(communities)*8)
	for i, c := range communities {
		l := strings.Split(c, ":")
		if len(l) != 8 {
			goto E
		}
		for j, v := range l {
			v, err := strconv.ParseInt(v, 0, 32)
			if err != nil {
				goto E
			}
			b[j+i*8] = uint8(v)
		}
	}
	return &CommunityAction{
		ext: b,
	}
E:
	log.WithFields(log.Fields{
		"Topic":  "Policy",
		"Action": "ExtCommunity",
		"Values": communities,
	}).Error("invalid extended community action")
	return nil
}

type ActionType int

type MedAction struct {
	DefaultAction
	Value  int64
	action ActionType
}

const (
	MED_ACTION_NONE ActionType = iota
	MED_ACTION_REPLACE
	MED_ACTION_ADD
	MED_ACTION_SUB
)

// NewMedAction creates MedAction object.
// If it cannot parse med string, then return nil.
func NewMedAction(med config.BgpSetMedType) *MedAction {

	if med == "" {
		return nil
	}

	m := &MedAction{}

	matched, value, action := getMedValue(fmt.Sprintf("%s", med))
	if !matched {
		log.WithFields(log.Fields{
			"Topic": "Policy",
			"Type":  "Med Action",
		}).Error("med string invalid.")
		return nil
	}
	m.Value = value
	m.action = action
	return m
}

// getMedValue returns uint32 med value and action type (+ or -).
// if the string doesn't match a number or operator,
// it returns false and 0.
func getMedValue(medStr string) (bool, int64, ActionType) {
	regMed, _ := regexp.Compile("^(\\+|\\-)?([0-9]+)$")
	if regMed.MatchString(medStr) {
		group := regMed.FindStringSubmatch(medStr)
		action := MED_ACTION_REPLACE
		if group[1] == "+" {
			action = MED_ACTION_ADD
		} else if group[1] == "-" {
			action = MED_ACTION_SUB
		}
		val, err := strconv.ParseInt(medStr, 10, 64)
		if err != nil {
			log.WithFields(log.Fields{
				"Topic": "Policy",
				"Type":  "Med Action",
			}).Error("failed to parser as number or med value.")
		}
		return true, int64(val), action
	}
	return false, int64(0), MED_ACTION_NONE
}
func (a *MedAction) apply(path *table.Path) *table.Path {

	var err error
	switch a.action {
	case MED_ACTION_REPLACE:
		err = path.SetMed(a.Value, true)
	case MED_ACTION_ADD:
		err = path.SetMed(a.Value, false)
	case MED_ACTION_SUB:
		err = path.SetMed(a.Value, false)
	}
	if err != nil {
		log.WithFields(log.Fields{
			"Topic": "Policy",
			"Type":  "Med Action",
		}).Warn(err)
	} else {
		log.WithFields(log.Fields{
			"Topic":      "Policy",
			"Action":     "med",
			"Value":      a.Value,
			"ActionType": a.action,
		}).Debug("med action applied")
	}

	return path
}

type AsPathPrependAction struct {
	DefaultAction
	asn         uint32
	useLeftMost bool
	repeat      uint8
}

// NewAsPathPrependAction creates AsPathPrependAction object.
// If ASN cannot be parsed, nil will be returned.
func NewAsPathPrependAction(action config.SetAsPathPrepend) *AsPathPrependAction {

	a := &AsPathPrependAction{}

	if action.As == "" {
		return nil
	}

	if action.As == "last-as" {
		a.useLeftMost = true
	} else {
		asn, err := strconv.ParseUint(action.As, 10, 32)
		if err != nil {
			log.WithFields(log.Fields{
				"Topic": "Policy",
				"Type":  "AsPathPrepend Action",
				"Value": action.As,
			}).Error("As number string invalid.")
			return nil
		}
		a.asn = uint32(asn)
	}
	a.repeat = action.RepeatN

	return a
}

func (a *AsPathPrependAction) apply(path *table.Path) *table.Path {

	var asn uint32
	if a.useLeftMost {
		asns := path.GetAsSeqList()
		if len(asns) == 0 {
			log.WithFields(log.Fields{
				"Topic": "Policy",
				"Type":  "AsPathPrepend Action",
			}).Error("aspath length is zero.")
			return path
		}
		asn = asns[0]
		log.WithFields(log.Fields{
			"Topic":  "Policy",
			"Type":   "AsPathPrepend Action",
			"LastAs": asn,
			"Repeat": a.repeat,
		}).Debug("use last AS.")
	} else {
		asn = a.asn
	}

	path.PrependAsn(asn, a.repeat)

	log.WithFields(log.Fields{
		"Topic":  "Policy",
		"Action": "aspath prepend",
		"ASN":    asn,
		"Repeat": a.repeat,
	}).Debug("aspath prepend action applied")

	return path
}

type Prefix struct {
	Address         net.IP
	AddressFamily   bgp.RouteFamily
	Masklength      uint8
	MasklengthRange map[MaskLengthRangeType]uint8
}

func NewPrefix(prefixStr string, maskRange string) (Prefix, error) {
	p := Prefix{}
	mlr := make(map[MaskLengthRangeType]uint8)
	addr, ipPref, e := net.ParseCIDR(prefixStr)

	if e != nil {
		return p, e
	}
	maskLength, _ := ipPref.Mask.Size()
	p.Address = addr
	p.Masklength = uint8(maskLength)

	if ipv4Family := addr.To4(); ipv4Family != nil {
		p.AddressFamily, _ = bgp.GetRouteFamily("ipv4-unicast")
	} else if ipv6Family := addr.To16(); ipv6Family != nil {
		p.AddressFamily, _ = bgp.GetRouteFamily("ipv6-unicast")
	} else {
		return p, fmt.Errorf("can not determine the address family.")
	}

	// TODO: validate mask length by using regexp

	idx := strings.Index(maskRange, "..")
	if idx == -1 {
		log.WithFields(log.Fields{
			"Topic":           "Policy",
			"Type":            "Prefix",
			"MaskRangeFormat": maskRange,
		}).Warn("mask length range format is invalid. mask range was skipped.")
		return p, nil
	}

	if idx != 0 {
		min, e := strconv.ParseUint(maskRange[:idx], 10, 8)
		if e != nil {
			return p, e
		}
		mlr[MASK_LENGTH_RANGE_MIN] = uint8(min)
	}
	if idx != len(maskRange)-1 {
		max, e := strconv.ParseUint(maskRange[idx+2:], 10, 8)
		if e != nil {
			return p, e
		}
		mlr[MASK_LENGTH_RANGE_MAX] = uint8(max)
	}
	p.MasklengthRange = mlr
	return p, nil
}

// Compare path with a policy's condition in stored order in the policy.
// If a condition match, then this function stops evaluation and
// subsequent conditions are skipped.
func (p *Policy) Apply(path *table.Path) (bool, RouteType, *table.Path) {
	for _, statement := range p.Statements {

		result := statement.evaluate(path)
		log.WithFields(log.Fields{
			"Topic":      "Policy",
			"Path":       path,
			"PolicyName": p.Name,
		}).Debug("statement evaluate : ", result)

		var p *table.Path
		if result {
			//Routing action
			p = statement.routingAction.apply(path)
			if p != nil {
				// apply all modification actions
				cloned := path.Clone(p.IsWithdraw)
				for _, action := range statement.modificationActions {
					cloned = action.apply(cloned)
				}
				return true, ROUTE_TYPE_ACCEPT, cloned
			} else {
				return true, ROUTE_TYPE_REJECT, nil
			}
		}
	}
	return false, ROUTE_TYPE_NONE, nil
}

func ipPrefixCalculate(path *table.Path, cPrefix Prefix) bool {
	rf := path.GetRouteFamily()
	log.Debug("path routefamily : ", rf.String())
	var pAddr net.IP
	var pMasklen uint8

	if rf != cPrefix.AddressFamily {
		return false
	}

	switch rf {
	case bgp.RF_IPv4_UC:
		pAddr = path.GetNlri().(*bgp.IPAddrPrefix).Prefix
		pMasklen = path.GetNlri().(*bgp.IPAddrPrefix).Length
	case bgp.RF_IPv6_UC:
		pAddr = path.GetNlri().(*bgp.IPv6AddrPrefix).Prefix
		pMasklen = path.GetNlri().(*bgp.IPv6AddrPrefix).Length
	default:
		return false
	}

	cp := fmt.Sprintf("%s/%d", cPrefix.Address, cPrefix.Masklength)
	rMin, okMin := cPrefix.MasklengthRange[MASK_LENGTH_RANGE_MIN]
	rMax, okMax := cPrefix.MasklengthRange[MASK_LENGTH_RANGE_MAX]
	if !okMin && !okMax {
		if pAddr.Equal(cPrefix.Address) && pMasklen == cPrefix.Masklength {
			return true
		} else {
			return false
		}
	}

	_, ipNet, e := net.ParseCIDR(cp)
	if e != nil {
		log.WithFields(log.Fields{
			"Topic":  "Policy",
			"Prefix": ipNet,
			"Error":  e,
		}).Error("failed to parse the prefix of condition")
		return false
	}
	if ipNet.Contains(pAddr) && (rMin <= pMasklen && pMasklen <= rMax) {
		return true
	}
	return false
}

const (
	ROUTE_ACCEPT string = "ACCEPT"
	ROUTE_REJECT        = "REJECT"
)

const (
	OPTIONS_ANY    string = "ANY"
	OPTIONS_ALL           = "ALL"
	OPTIONS_INVERT        = "INVERT"
)

func MatchSetOptionToString(option config.MatchSetOptionsType) string {
	op := OPTIONS_ANY
	switch option {
	case config.MATCH_SET_OPTIONS_TYPE_ALL:
		op = OPTIONS_ALL
	case config.MATCH_SET_OPTIONS_TYPE_INVERT:
		op = OPTIONS_INVERT
	}
	return op
}

func MatchSetOptionsRestrictedToString(option config.MatchSetOptionsRestrictedType) string {
	op := OPTIONS_ANY
	if option == config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT {
		op = OPTIONS_INVERT
	}
	return op
}

func MatchSetOptionsToType(option string) config.MatchSetOptionsType {
	op := config.MATCH_SET_OPTIONS_TYPE_ANY
	switch option {
	case OPTIONS_ALL:
		op = config.MATCH_SET_OPTIONS_TYPE_ALL
	case OPTIONS_INVERT:
		op = config.MATCH_SET_OPTIONS_TYPE_INVERT
	}
	return op
}

func MatchSetOptionsRestrictedToType(option string) config.MatchSetOptionsRestrictedType {
	op := config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY
	if option == OPTIONS_INVERT {
		op = config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT
	}
	return op
}

// find index PrefixSet of request from PrefixSet of configuration file.
// Return the idxPrefixSet of the location where the name of PrefixSet matches,
// and idxPrefix of the location where element of PrefixSet matches
func IndexOfPrefixSet(conPrefixSetList []config.PrefixSet, reqPrefixSet config.PrefixSet) (int, int) {
	idxPrefixSet := -1
	idxPrefix := -1
	for i, conPrefixSet := range conPrefixSetList {
		if conPrefixSet.PrefixSetName == reqPrefixSet.PrefixSetName {
			idxPrefixSet = i
			if reqPrefixSet.PrefixList == nil {
				return idxPrefixSet, idxPrefix
			}
			for j, conPrefix := range conPrefixSet.PrefixList {
				if reflect.DeepEqual(conPrefix.IpPrefix, reqPrefixSet.PrefixList[0].IpPrefix) &&
					conPrefix.MasklengthRange == reqPrefixSet.PrefixList[0].MasklengthRange {
					idxPrefix = j
					return idxPrefixSet, idxPrefix
				}
			}
		}
	}
	return idxPrefixSet, idxPrefix
}

// find index NeighborSet of request from NeighborSet of configuration file.
// Return the idxNeighborSet of the location where the name of NeighborSet matches,
// and idxNeighbor of the location where element of NeighborSet matches
func IndexOfNeighborSet(conNeighborSetList []config.NeighborSet, reqNeighborSet config.NeighborSet) (int, int) {
	idxNeighborSet := -1
	idxNeighbor := -1
	for i, conNeighborSet := range conNeighborSetList {
		if conNeighborSet.NeighborSetName == reqNeighborSet.NeighborSetName {
			idxNeighborSet = i
			if reqNeighborSet.NeighborInfoList == nil {
				return idxNeighborSet, idxNeighbor
			}
			for j, conNeighbor := range conNeighborSet.NeighborInfoList {
				if reflect.DeepEqual(conNeighbor.Address, reqNeighborSet.NeighborInfoList[0].Address) {
					idxNeighbor = j
					return idxNeighborSet, idxNeighbor
				}
			}
		}
	}
	return idxNeighborSet, idxNeighbor
}

// find index AsPathSet of request from AsPathSet of configuration file.
// Return the idxAsPathSet of the location where the name of AsPathSet matches,
// and idxAsPath of the location where element of AsPathSet matches
func IndexOfAsPathSet(conAsPathSetList []config.AsPathSet, reqAsPathSet config.AsPathSet) (int, int) {
	idxAsPathSet := -1
	idxAsPath := -1
	for i, conAsPathSet := range conAsPathSetList {
		if conAsPathSet.AsPathSetName == reqAsPathSet.AsPathSetName {
			idxAsPathSet = i
			if len(reqAsPathSet.AsPathList) == 0 {
				return idxAsPathSet, idxAsPath
			}
			for j, conAsPath := range conAsPathSet.AsPathList {
				if conAsPath == reqAsPathSet.AsPathList[0] {
					idxAsPath = j
					return idxAsPathSet, idxAsPath
				}
			}
		}
	}
	return idxAsPathSet, idxAsPath
}

// find index CommunitySet of request from CommunitySet of configuration file.
// Return the idxCommunitySet of the location where the name of CommunitySet matches,
// and idxCommunity of the location where element of CommunitySet matches
func IndexOfCommunitySet(conCommunitySetList []config.CommunitySet, reqCommunitySet config.CommunitySet) (int, int) {
	idxCommunitySet := -1
	idxCommunity := -1
	for i, conCommunitySet := range conCommunitySetList {
		if conCommunitySet.CommunitySetName == reqCommunitySet.CommunitySetName {
			idxCommunitySet = i
			if len(reqCommunitySet.CommunityList) == 0 {
				return idxCommunitySet, idxCommunity
			}
			for j, conCommunity := range conCommunitySet.CommunityList {
				if conCommunity == reqCommunitySet.CommunityList[0] {
					idxCommunity = j
					return idxCommunitySet, idxCommunity
				}
			}
		}
	}
	return idxCommunitySet, idxCommunity
}

// find index ExtCommunitySet of request from ExtCommunitySet of configuration file.
// Return the idxExtCommunitySet of the location where the name of ExtCommunitySet matches,
// and idxExtCommunity of the location where element of ExtCommunitySet matches
func IndexOfExtCommunitySet(conExtCommunitySetList []config.ExtCommunitySet, reqExtCommunitySet config.ExtCommunitySet) (int, int) {
	idxExtCommunitySet := -1
	idxExtCommunity := -1
	for i, conExtCommunitySet := range conExtCommunitySetList {
		if conExtCommunitySet.ExtCommunitySetName == reqExtCommunitySet.ExtCommunitySetName {
			idxExtCommunitySet = i
			if len(reqExtCommunitySet.ExtCommunityList) == 0 {
				return idxExtCommunitySet, idxExtCommunity
			}
			for j, conExtCommunity := range conExtCommunitySet.ExtCommunityList {
				if conExtCommunity == reqExtCommunitySet.ExtCommunityList[0] {
					idxExtCommunity = j
					return idxExtCommunitySet, idxExtCommunity
				}
			}
		}
	}
	return idxExtCommunitySet, idxExtCommunity
}

// find index PolicyDefinition of request from PolicyDefinition of configuration file.
// Return the idxPolicyDefinition of the location where the name of PolicyDefinition matches,
// and idxStatement of the location where Statement of PolicyDefinition matches
func IndexOfPolicyDefinition(conPolicyList []config.PolicyDefinition, reqPolicy config.PolicyDefinition) (int, int) {
	idxPolicyDefinition := -1
	idxStatement := -1
	for i, conPolicy := range conPolicyList {
		if conPolicy.Name == reqPolicy.Name {
			idxPolicyDefinition = i
			if reqPolicy.Statements.StatementList == nil {
				return idxPolicyDefinition, idxStatement
			}
			for j, conStatement := range conPolicy.Statements.StatementList {
				if conStatement.Name == reqPolicy.Statements.StatementList[0].Name {
					idxStatement = j
					return idxPolicyDefinition, idxStatement
				}
			}
		}
	}
	return idxPolicyDefinition, idxStatement
}

func PrefixSetToApiStruct(ps config.PrefixSet) *gobgpapi.PrefixSet {
	resPrefixList := make([]*gobgpapi.Prefix, 0)
	for _, p := range ps.PrefixList {
		resPrefix := &gobgpapi.Prefix{
			IpPrefix:        p.IpPrefix,
			MaskLengthRange: p.MasklengthRange,
		}
		resPrefixList = append(resPrefixList, resPrefix)
	}
	resPrefixSet := &gobgpapi.PrefixSet{
		PrefixSetName: ps.PrefixSetName,
		PrefixList:    resPrefixList,
	}

	return resPrefixSet
}

func PrefixSetToConfigStruct(reqPrefixSet *gobgpapi.PrefixSet) (bool, config.PrefixSet) {
	var prefix config.Prefix
	var prefixSet config.PrefixSet
	isReqPrefixSet := true
	if reqPrefixSet.PrefixList != nil {
		prefix = config.Prefix{
			IpPrefix:        reqPrefixSet.PrefixList[0].IpPrefix,
			MasklengthRange: reqPrefixSet.PrefixList[0].MaskLengthRange,
		}
		prefixList := []config.Prefix{prefix}

		prefixSet = config.PrefixSet{
			PrefixSetName: reqPrefixSet.PrefixSetName,
			PrefixList:    prefixList,
		}
	} else {
		isReqPrefixSet = false
		prefixSet = config.PrefixSet{
			PrefixSetName: reqPrefixSet.PrefixSetName,
			PrefixList:    nil,
		}
	}
	return isReqPrefixSet, prefixSet
}

func NeighborSetToApiStruct(ns config.NeighborSet) *gobgpapi.NeighborSet {
	resNeighborList := make([]*gobgpapi.Neighbor, 0)
	for _, n := range ns.NeighborInfoList {
		resNeighbor := &gobgpapi.Neighbor{
			Address: n.Address.String(),
		}
		resNeighborList = append(resNeighborList, resNeighbor)
	}
	resNeighborSet := &gobgpapi.NeighborSet{
		NeighborSetName: ns.NeighborSetName,
		NeighborList:    resNeighborList,
	}
	return resNeighborSet
}

func NeighborSetToConfigStruct(reqNeighborSet *gobgpapi.NeighborSet) (bool, config.NeighborSet) {
	var neighbor config.NeighborInfo
	var neighborSet config.NeighborSet
	isReqNeighborSet := true
	if reqNeighborSet.NeighborList != nil {
		neighbor = config.NeighborInfo{
			Address: net.ParseIP(reqNeighborSet.NeighborList[0].Address),
		}
		neighborList := []config.NeighborInfo{neighbor}

		neighborSet = config.NeighborSet{
			NeighborSetName:  reqNeighborSet.NeighborSetName,
			NeighborInfoList: neighborList,
		}
	} else {
		isReqNeighborSet = false
		neighborSet = config.NeighborSet{
			NeighborSetName:  reqNeighborSet.NeighborSetName,
			NeighborInfoList: nil,
		}
	}
	return isReqNeighborSet, neighborSet
}

func AsPathSetToApiStruct(as config.AsPathSet) *gobgpapi.AsPathSet {
	resAsPathMembers := make([]string, 0)
	for _, a := range as.AsPathList {
		resAsPathMembers = append(resAsPathMembers, a.AsPath)
	}
	resAsPathSet := &gobgpapi.AsPathSet{
		AsPathSetName: as.AsPathSetName,
		AsPathMembers: resAsPathMembers,
	}
	return resAsPathSet
}

func AsPathSetToConfigStruct(reqAsPathSet *gobgpapi.AsPathSet) (bool, config.AsPathSet) {
	isAsPathSetSet := true
	if len(reqAsPathSet.AsPathMembers) == 0 {
		isAsPathSetSet = false
	}
	asPathList := make([]config.AsPath, 0)
	for _, a := range reqAsPathSet.AsPathMembers {
		asPathList = append(asPathList, config.AsPath{AsPath: a})
	}
	asPathSet := config.AsPathSet{
		AsPathSetName: reqAsPathSet.AsPathSetName,
		AsPathList:    asPathList,
	}
	return isAsPathSetSet, asPathSet
}

func CommunitySetToApiStruct(cs config.CommunitySet) *gobgpapi.CommunitySet {
	resCommunityMembers := make([]string, 0)
	for _, c := range cs.CommunityList {
		resCommunityMembers = append(resCommunityMembers, c.Community)
	}
	resCommunitySet := &gobgpapi.CommunitySet{
		CommunitySetName: cs.CommunitySetName,
		CommunityMembers: resCommunityMembers,
	}
	return resCommunitySet
}

func CommunitySetToConfigStruct(reqCommunitySet *gobgpapi.CommunitySet) (bool, config.CommunitySet) {
	isCommunitySet := true
	if len(reqCommunitySet.CommunityMembers) == 0 {
		isCommunitySet = false
	}
	communityList := make([]config.Community, 0)
	for _, c := range reqCommunitySet.CommunityMembers {
		communityList = append(communityList, config.Community{Community: c})
	}
	communitySet := config.CommunitySet{
		CommunitySetName: reqCommunitySet.CommunitySetName,
		CommunityList:    communityList,
	}
	return isCommunitySet, communitySet
}

func ExtCommunitySetToApiStruct(es config.ExtCommunitySet) *gobgpapi.ExtCommunitySet {
	resExtCommunityMembers := make([]string, 0)
	for _, ec := range es.ExtCommunityList {
		resExtCommunityMembers = append(resExtCommunityMembers, ec.ExtCommunity)
	}
	resExtCommunitySet := &gobgpapi.ExtCommunitySet{
		ExtCommunitySetName: es.ExtCommunitySetName,
		ExtCommunityMembers: resExtCommunityMembers,
	}
	return resExtCommunitySet
}

func ExtCommunitySetToConfigStruct(reqExtCommunitySet *gobgpapi.ExtCommunitySet) (bool, config.ExtCommunitySet) {
	isExtCommunitySet := true
	if len(reqExtCommunitySet.ExtCommunityMembers) == 0 {
		isExtCommunitySet = false
	}
	extCommunityList := make([]config.ExtCommunity, 0)
	for _, ec := range reqExtCommunitySet.ExtCommunityMembers {
		extCommunityList = append(extCommunityList, config.ExtCommunity{ExtCommunity: ec})
	}
	ExtCommunitySet := config.ExtCommunitySet{
		ExtCommunitySetName: reqExtCommunitySet.ExtCommunitySetName,
		ExtCommunityList:    extCommunityList,
	}
	return isExtCommunitySet, ExtCommunitySet
}

func AsPathLengthToApiStruct(asPathLength config.AsPathLength) *gobgpapi.AsPathLength {
	value := ""
	if asPathLength.Operator != "" {
		value = fmt.Sprintf("%d", asPathLength.Value)
	}
	resAsPathLength := &gobgpapi.AsPathLength{
		Value:    value,
		Operator: asPathLength.Operator,
	}
	return resAsPathLength
}

func AsPathLengthToConfigStruct(reqAsPathLength *gobgpapi.AsPathLength) config.AsPathLength {
	operator := reqAsPathLength.Operator
	value := reqAsPathLength.Value
	valueUint, _ := strconv.ParseUint(value, 10, 32)
	asPathLength := config.AsPathLength{
		Operator: operator,
		Value:    uint32(valueUint),
	}
	return asPathLength
}

func ConditionsToConfigStruct(reqConditions *gobgpapi.Conditions) config.Conditions {
	conditions := config.Conditions{}
	if reqConditions == nil {
		return conditions
	}
	if reqConditions.MatchPrefixSet != nil {
		conditions.MatchPrefixSet.PrefixSet = reqConditions.MatchPrefixSet.PrefixSetName
		conditions.MatchPrefixSet.MatchSetOptions =
			MatchSetOptionsRestrictedToType(reqConditions.MatchPrefixSet.MatchSetOptions)
	}
	if reqConditions.MatchNeighborSet != nil {
		conditions.MatchNeighborSet.NeighborSet = reqConditions.MatchNeighborSet.NeighborSetName
		conditions.MatchNeighborSet.MatchSetOptions =
			MatchSetOptionsRestrictedToType(reqConditions.MatchNeighborSet.MatchSetOptions)
	}
	if reqConditions.MatchAsPathSet != nil {
		conditions.BgpConditions.MatchAsPathSet.AsPathSet = reqConditions.MatchAsPathSet.AsPathSetName
		conditions.BgpConditions.MatchAsPathSet.MatchSetOptions =
			MatchSetOptionsToType(reqConditions.MatchAsPathSet.MatchSetOptions)
	}
	if reqConditions.MatchCommunitySet != nil {
		conditions.BgpConditions.MatchCommunitySet.CommunitySet = reqConditions.MatchCommunitySet.CommunitySetName
		conditions.BgpConditions.MatchCommunitySet.MatchSetOptions =
			MatchSetOptionsToType(reqConditions.MatchCommunitySet.MatchSetOptions)
	}
	if reqConditions.MatchExtCommunitySet != nil {
		conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet = reqConditions.MatchExtCommunitySet.ExtCommunitySetName
		conditions.BgpConditions.MatchExtCommunitySet.MatchSetOptions =
			MatchSetOptionsToType(reqConditions.MatchExtCommunitySet.MatchSetOptions)
	}
	if reqConditions.MatchAsPathLength != nil {
		conditions.BgpConditions.AsPathLength =
			AsPathLengthToConfigStruct(reqConditions.MatchAsPathLength)
	}
	return conditions
}

func ActionsToApiStruct(conActions config.Actions) *gobgpapi.Actions {
	action := ROUTE_REJECT
	if conActions.RouteDisposition.AcceptRoute {
		action = ROUTE_ACCEPT
	}

	//TODO: support CommunitySetRef
	communityAction := &gobgpapi.CommunityAction{
		Communities: conActions.BgpActions.SetCommunity.SetCommunityMethod.Communities,
		Options:     conActions.BgpActions.SetCommunity.Options,
	}
	medAction := fmt.Sprintf("%s", conActions.BgpActions.SetMed)
	asprependAction := &gobgpapi.AsPrependAction{
		conActions.BgpActions.SetAsPathPrepend.As,
		uint32(conActions.BgpActions.SetAsPathPrepend.RepeatN),
	}
	extCommunityAction := &gobgpapi.CommunityAction{
		Communities: conActions.BgpActions.SetExtCommunity.SetExtCommunityMethod.Communities,
		Options:     conActions.BgpActions.SetExtCommunity.Options,
	}

	resActions := &gobgpapi.Actions{
		RouteAction:  action,
		Community:    communityAction,
		Med:          medAction,
		AsPrepend:    asprependAction,
		ExtCommunity: extCommunityAction,
	}
	return resActions
}

func ActionsToConfigStruct(reqActions *gobgpapi.Actions) config.Actions {
	actions := config.Actions{}
	if reqActions == nil {
		return actions
	}
	if reqActions.Community != nil {
		actions.BgpActions.SetCommunity.SetCommunityMethod.Communities = reqActions.Community.Communities
		actions.BgpActions.SetCommunity.Options = reqActions.Community.Options
	}
	if reqActions.Med != "" {
		actions.BgpActions.SetMed = config.BgpSetMedType(reqActions.Med)
	}
	if reqActions.AsPrepend != nil {
		actions.BgpActions.SetAsPathPrepend.As = reqActions.AsPrepend.As
		actions.BgpActions.SetAsPathPrepend.RepeatN = uint8(reqActions.AsPrepend.Repeatn)
	}

	switch reqActions.RouteAction {
	case ROUTE_ACCEPT:
		actions.RouteDisposition.AcceptRoute = true
	case ROUTE_REJECT:
		actions.RouteDisposition.RejectRoute = true
	}
	return actions
}

func StatementToConfigStruct(reqStatement *gobgpapi.Statement) config.Statement {
	statement := config.Statement{
		Name:       reqStatement.StatementNeme,
		Conditions: ConditionsToConfigStruct(reqStatement.Conditions),
		Actions:    ActionsToConfigStruct(reqStatement.Actions),
	}
	return statement
}

func PolicyDefinitionToConfigStruct(reqPolicy *gobgpapi.PolicyDefinition) (bool, config.PolicyDefinition) {
	isReqStatement := true
	policy := config.PolicyDefinition{
		Name: reqPolicy.PolicyDefinitionName,
	}
	if reqPolicy.StatementList != nil {
		statement := StatementToConfigStruct(reqPolicy.StatementList[0])
		policy.Statements.StatementList = []config.Statement{statement}
	} else {
		isReqStatement = false
	}
	return isReqStatement, policy
}

func PolicyDefinitionToApiStruct(pd config.PolicyDefinition, df config.DefinedSets) *gobgpapi.PolicyDefinition {
	conPrefixSetList := df.PrefixSets.PrefixSetList
	conNeighborSetList := df.NeighborSets.NeighborSetList
	conAsPathSetList := df.BgpDefinedSets.AsPathSets.AsPathSetList
	conCommunitySetList := df.BgpDefinedSets.CommunitySets.CommunitySetList
	conExtCommunitySetList := df.BgpDefinedSets.ExtCommunitySets.ExtCommunitySetList
	resStatementList := make([]*gobgpapi.Statement, 0)
	for _, st := range pd.Statements.StatementList {
		co := st.Conditions
		bco := co.BgpConditions
		ac := st.Actions

		prefixSet := &gobgpapi.PrefixSet{PrefixSetName: co.MatchPrefixSet.PrefixSet}
		conPrefixSet := config.PrefixSet{PrefixSetName: co.MatchPrefixSet.PrefixSet}
		idxPrefixSet, _ := IndexOfPrefixSet(conPrefixSetList, conPrefixSet)
		if idxPrefixSet != -1 {
			prefixSet = PrefixSetToApiStruct(conPrefixSetList[idxPrefixSet])
			prefixSet.MatchSetOptions = MatchSetOptionsRestrictedToString(st.Conditions.MatchPrefixSet.MatchSetOptions)
		}
		neighborSet := &gobgpapi.NeighborSet{NeighborSetName: co.MatchNeighborSet.NeighborSet}
		conNeighborSet := config.NeighborSet{NeighborSetName: co.MatchNeighborSet.NeighborSet}
		idxNeighborSet, _ := IndexOfNeighborSet(conNeighborSetList, conNeighborSet)
		if idxNeighborSet != -1 {
			neighborSet = NeighborSetToApiStruct(conNeighborSetList[idxNeighborSet])
			neighborSet.MatchSetOptions = MatchSetOptionsRestrictedToString(st.Conditions.MatchNeighborSet.MatchSetOptions)
		}

		asPathSet := &gobgpapi.AsPathSet{AsPathSetName: bco.MatchAsPathSet.AsPathSet}
		conAsPathSet := config.AsPathSet{AsPathSetName: bco.MatchAsPathSet.AsPathSet}
		idxAsPathSet, _ := IndexOfAsPathSet(conAsPathSetList, conAsPathSet)
		if idxAsPathSet != -1 {
			asPathSet = AsPathSetToApiStruct(conAsPathSetList[idxAsPathSet])
			asPathSet.MatchSetOptions = MatchSetOptionToString(bco.MatchAsPathSet.MatchSetOptions)
		}

		communitySet := &gobgpapi.CommunitySet{CommunitySetName: bco.MatchCommunitySet.CommunitySet}
		conCommunitySet := config.CommunitySet{CommunitySetName: bco.MatchCommunitySet.CommunitySet}
		idxCommunitySet, _ := IndexOfCommunitySet(conCommunitySetList, conCommunitySet)
		if idxCommunitySet != -1 {
			communitySet = CommunitySetToApiStruct(conCommunitySetList[idxCommunitySet])
			communitySet.MatchSetOptions = MatchSetOptionToString(bco.MatchCommunitySet.MatchSetOptions)
		}

		extCommunitySet := &gobgpapi.ExtCommunitySet{ExtCommunitySetName: bco.MatchExtCommunitySet.ExtCommunitySet}
		conExtCommunitySet := config.ExtCommunitySet{ExtCommunitySetName: bco.MatchExtCommunitySet.ExtCommunitySet}
		idxExtCommunitySet, _ := IndexOfExtCommunitySet(conExtCommunitySetList, conExtCommunitySet)
		if idxExtCommunitySet != -1 {
			extCommunitySet = ExtCommunitySetToApiStruct(conExtCommunitySetList[idxExtCommunitySet])
			extCommunitySet.MatchSetOptions = MatchSetOptionToString(bco.MatchExtCommunitySet.MatchSetOptions)
		}

		resConditions := &gobgpapi.Conditions{
			MatchPrefixSet:       prefixSet,
			MatchNeighborSet:     neighborSet,
			MatchAsPathSet:       asPathSet,
			MatchCommunitySet:    communitySet,
			MatchExtCommunitySet: extCommunitySet,
			MatchAsPathLength:    AsPathLengthToApiStruct(st.Conditions.BgpConditions.AsPathLength),
		}
		resActions := ActionsToApiStruct(ac)
		resStatement := &gobgpapi.Statement{
			StatementNeme: st.Name,
			Conditions:    resConditions,
			Actions:       resActions,
		}
		resStatementList = append(resStatementList, resStatement)
	}
	resPolicyDefinition := &gobgpapi.PolicyDefinition{
		PolicyDefinitionName: pd.Name,
		StatementList:        resStatementList,
	}
	return resPolicyDefinition
}

func PoliciesToString(reqPolicies []*gobgpapi.PolicyDefinition) []string {
	policies := make([]string, 0)
	for _, reqPolicy := range reqPolicies {
		policies = append(policies, reqPolicy.PolicyDefinitionName)
	}
	return policies
}

func CanImportToVrf(v *table.Vrf, path *table.Path) bool {
	f := func(arg []bgp.ExtendedCommunityInterface) []config.ExtCommunity {
		ret := make([]config.ExtCommunity, 0, len(arg))
		for _, a := range arg {
			ret = append(ret, config.ExtCommunity{
				ExtCommunity: fmt.Sprintf("RT:%s", a.String()),
			})
		}
		return ret
	}
	set := config.ExtCommunitySet{
		ExtCommunitySetName: v.Name,
		ExtCommunityList:    f(v.ImportRt),
	}
	matchSet := config.MatchExtCommunitySet{
		ExtCommunitySet: v.Name,
		MatchSetOptions: config.MATCH_SET_OPTIONS_TYPE_ANY,
	}
	return NewExtCommunityCondition(matchSet, []config.ExtCommunitySet{set}).evaluate(path)
}

redpajama_set_name: RedPajamaGithub


text:
\SetAPI{J-C}
\section{CompositeIdBehavior}
\label{feature:CompositeIdBehavior}
\ClearAPI
Allows to create objects at runtime where their equals() hashcode() toString() methods behave like a composite id (unique identifier). This way it is possible for \AMBETH{} to pass composite id information via the Member-API as a single argument / response. At runtime the created object has public fields which are named like the mapped primitive members forming the composite id (unique identifier)

\begin{lstlisting}[style=Java,caption={Example usage to receive an instance of a composite id (Java)}]
@Autowired
protected ICompositeIdFactory compositeIdFactory;

@Autowired
protected IEntityMetaDataProvider entityMetaDataProvider;

public Object extractCompositeId(Object myObject)
{
	IEntityMetaData metaData = entityMetaDataProvider.getMetaData(myObject.getClass());
	return compositeIdFactory.createCompositeId(metaData, metaData.getIdMember(), myObject.getId1(), myObject.getId2());
}
\end{lstlisting}
\begin{lstlisting}[style=Csharp,caption={Example usage to receive an instance of a composite id (C\#)}]
[Autowired]
public ICompositeIdFactory CompositeIdFactory { protected get; set; }

[Autowired]
public IEntityMetaDataProvider EntityMetaDataProvider { protected get; set; }

public Object ExtractCompositeId(Object myObject)
{
	IEntityMetaData metaData = EntityMetaDataProvider.GetMetaData(myObject.GetType());
	return CompositeIdFactory.CreateCompositeId(metaData, metaData.IdMember, myObject.Id1, myObject.Id2);
}
\end{lstlisting}


text:
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
const Crypto = require("crypto");
const U = require("./utils");
/*********************************************************
 * Class Decorators
 *********************************************************/
/**
 *  Registers a fixture of tests with the global test runner.
 *  @param {string} humanReadableName - The human readable name for the fixture
 */
function Fixture(humanReadableName) {
    return (ctr) => {
        let fixture = exports.globalKTState.getOrInsertFixture(ctr);
        fixture.humanReadableName = typeof (humanReadableName) === "string" ? humanReadableName : ctr.name;
        fixture.explicitlyDeclared = true;
    };
}
exports.Fixture = Fixture;
/*********************************************************
 * Method Decorators
 *********************************************************/
/**
 *  Register a new test. If the test throws it fails, otherwise it passes.
 *  @param {string} humanReadableName - The human readable name for this test.
 */
function Test(humanReadableName) {
    return function (target, propertyKey, descriptor) {
        let f = exports.globalKTState.getOrInsertFixture(target.constructor);
        let t = f.getOrInsertTest(propertyKey);
        t.humanReadableName = humanReadableName;
        t.explicitlyDeclared = true;
    };
}
exports.Test = Test;
/**
 *  Method to run before any of the tests.
 */
function Before() {
    return function (target, propertyKey, descriptor) {
        exports.globalKTState.getOrInsertFixture(target.constructor).runBeforeMethods.push(propertyKey);
    };
}
exports.Before = Before;
/**
 *  Method to run after any of the tests.
 */
function After() {
    return function (target, propertyKey, descriptor) {
        exports.globalKTState.getOrInsertFixture(target.constructor).runAfterMethods.push(propertyKey);
    };
}
exports.After = After;
/*********************************************************
 * Tests
 *********************************************************/
class KwyjiboTest {
    constructor() {
        this.explicitlyDeclared = false;
    }
}
exports.KwyjiboTest = KwyjiboTest;
class KwyjiboFixture {
    constructor() {
        this.runBeforeMethods = [];
        this.runAfterMethods = [];
        this.tests = {};
        this.explicitlyDeclared = false;
    }
    getOrInsertTest(key) {
        if (this.tests[key] == undefined) {
            this.tests[key] = new KwyjiboTest();
        }
        return this.tests[key];
    }
}
exports.KwyjiboFixture = KwyjiboFixture;
class KwyjiboTestResult {
}
exports.KwyjiboTestResult = KwyjiboTestResult;
class KwyjiboTestsState {
    constructor() {
        this.fixtures = {};
    }
    getOrInsertFixture(ctr) {
        let key = ctr.toString();
        if (this.fixtures[key] == undefined) {
            this.fixtures[key] = new KwyjiboFixture();
            this.fixtures[key].ctr = ctr;
        }
        return this.fixtures[key];
    }
    generateCompleteFixtureMetadata() {
        let metadata = {};
        for (let fxk in this.fixtures) {
            let fixture = this.fixtures[fxk];
            let fxkHash = KwyjiboTestsState.getFixtureHashId(fixture);
            metadata[fxkHash] = {};
            for (let tk in fixture.tests) {
                metadata[fxkHash][tk] = true;
            }
        }
        return metadata;
    }
    static getFixtureHashId(fixture) {
        let hasher = Crypto.createHash("sha256");
        hasher.update(fixture.ctr.toString());
        return fixture.ctr.name + "_" + hasher.digest("hex").substr(0, 8);
    }
    generateRainbowTables() {
        let rt = {};
        for (let fxk in this.fixtures) {
            let fixture = this.fixtures[fxk];
            let fxkHash = KwyjiboTestsState.getFixtureHashId(fixture);
            rt[fxkHash] = fixture;
        }
        return rt;
    }
    run(testsToRun) {
        return __awaiter(this, void 0, void 0, function* () {
            if (testsToRun == undefined) {
                testsToRun = this.generateCompleteFixtureMetadata();
            }
            let testResults = [];
            let rainbowTables = this.generateRainbowTables();
            for (let fxk in testsToRun) {
                let fixture = rainbowTables[fxk];
                let fi = Reflect.construct(fixture.ctr, []);
                for (let mn of fixture.runBeforeMethods) {
                    let r = fi[mn]();
                    if (r instanceof Promise) {
                        yield r;
                    }
                }
                for (let mn in testsToRun[fxk]) {
                    if (testsToRun[fxk][mn] === true && fixture.tests[mn] != undefined && fi[mn] != undefined) {
                        let result = new KwyjiboTestResult();
                        result.fixtureKey = fxk;
                        result.fixtureDesc = fixture.humanReadableName;
                        result.testKey = mn;
                        result.testDesc = fixture.tests[mn].humanReadableName;
                        try {
                            let r = fi[mn]();
                            if (r instanceof Promise) {
                                yield r;
                            }
                            result.passed = true;
                            result.message = "";
                        }
                        catch (err) {
                            result.passed = false;
                            if (err instanceof Error) {
                                result.message = JSON.stringify({ name: err.name, message: err.message, stack: err.stack });
                            }
                            else if (err instanceof Object) {
                                result.message = JSON.stringify(err);
                            }
                            else if (typeof (err) === "string") {
                                result.message = err;
                            }
                            else {
                                result.message = err.toString();
                            }
                        }
                        testResults.push(result);
                    }
                }
                for (let mn of fixture.runAfterMethods) {
                    let r = fi[mn]();
                    if (r instanceof Promise) {
                        yield r;
                    }
                }
            }
            return testResults;
        });
    }
}
exports.KwyjiboTestsState = KwyjiboTestsState;
exports.globalKTState = new KwyjiboTestsState();
const defaultCSS = `
    body {
        font-family:verdana;
    }

    tr {
        padding:5px;
    }

    tr a {
        color:#000000;
    }

    tr.header {
        background-color:#AAAAAA;
    }

    tr.header-allpassed {
       background-color:#00AA00;
    }

    tr.header-somefailed {
       background-color:#AA0000;
    }
    tr.header-somefailed a{
       color:#FFFFFF;
    }

    button#runButton {
        width:100%;
        font-size:18px;
        font-weight:bold;
    }

    .flex-container {
        display: flex;
        flex-direction: column;
        flex-wrap: nowrap;
        justify-content: flex-start;
        align-content: stretch;
        align-items: center;
    }

    .flex-item {
        order: 0;
        flex: 0 1 auto;
        align-self: auto;
    }
`;
function generateInteractiveTestRunnerMiddleware(useFixture) {
    return (req, res) => {
        let content = `

 Interactive Tests Runner

        `;
        let useFixtureHash = undefined;
        if (useFixture == undefined) {
            content += `
                    To run all the tests programatically use: /all

                    To run some of the tests programatically send a JSON payload via POST to: /some

                    (You can see how the JSON payload should look at /metadata)

                    `;
        }
        else {
            content += `
                    To run all the tests programatically use: /all

                    To run some of the tests programatically, see tests home

                    `;
            useFixtureHash = KwyjiboTestsState.getFixtureHashId(useFixture);
        }
        content += `<table>`;
        for (let fxk in exports.globalKTState.fixtures) {
            let fixture = exports.globalKTState.fixtures[fxk];
            let fxkHash = KwyjiboTestsState.getFixtureHashId(fixture);
            if (useFixtureHash != undefined && fxkHash !== useFixtureHash) {
                continue;
            }
            content += `

                       <input class="runner" id="${fxkHash}" type="checkbox" checked />
                       ${fixture.humanReadableName}
`;
            for (let tk in fixture.tests) {
                let test = fixture.tests[tk];
                content += `
<input class="${fxkHash}" id="${tk}" type="checkbox" checked />
                                ${test.humanReadableName}
`;
            }
        }
        content += `<tr><td colspan="3"></td></tr><tr><td colspan="3"><button id="runButton">Run Tests</button></td></tr>`;
        content += "
";
        content += "
";
        res.send(content);
    };
}
function runSetOfTestsAndFillResponse(testsToRun, res) {
    return __awaiter(this, void 0, void 0, function* () {
        let results = yield exports.globalKTState.run(testsToRun);
        let failed = false;
        for (let result of results) {
            if (result.passed === false) {
                failed = true;
            }
        }
        res.statusCode = failed ? 418 : 200;
        res.json(results);
    });
}
function injectTestRunnerMiddleware(controller) {
    /*
        Available endpoints:
            - /: interactive shell

            - /all: run all tests unattended
            - /metadata: get json metadata for available tests.
            - /some: post a json to run only a subset of tests.

            - /fixture/[FixtureName]: link to all tests in fixture (interactive shell)
            - /fixture/[FixtureName]/all
    */
    controller.router.get("/all", (req, res) => __awaiter(this, void 0, void 0, function* () {
        yield runSetOfTestsAndFillResponse(undefined, res);
    }));
    controller.router.post("/some", (req, res) => __awaiter(this, void 0, void 0, function* () {
        yield runSetOfTestsAndFillResponse(req.body, res);
    }));
    controller.router.get("/metadata", (req, res) => {
        res.json(exports.globalKTState.generateCompleteFixtureMetadata());
    });
    for (let fxk in exports.globalKTState.fixtures) {
        let fixture = exports.globalKTState.fixtures[fxk];
        let fxkHash = KwyjiboTestsState.getFixtureHashId(fixture);
        controller.router.get(U.UrlJoin("/fixture/", fxkHash, "/"), generateInteractiveTestRunnerMiddleware(fixture));
        controller.router.get(U.UrlJoin("/fixture/", fxkHash, "/all"), (req, res) => __awaiter(this, void 0, void 0, function* () {
            let metadata = exports.globalKTState.generateCompleteFixtureMetadata();
            let thisFixtureSet = {};
            for (let mk in metadata) {
                if (mk === fxkHash) {
                    thisFixtureSet[mk] = metadata[mk];
                }
            }
            yield runSetOfTestsAndFillResponse(thisFixtureSet, res);
        }));
    }
    controller.router.get("/", generateInteractiveTestRunnerMiddleware());
}
exports.injectTestRunnerMiddleware = injectTestRunnerMiddleware;
//# sourceMappingURL=testing.js.map


text:
AWS CloudWatch Event based account monitoring for security relevant events.

# Deploy:
```
workon gitlamb
mkdir libs
pip install -t $( pwd )/libs -r requirements.txt
python <pathto>/gitlamb.py deploy sec_alerts.yaml
```

# Configure:
```
python <pathto>/gitlamb.py execute sec_alerts.yaml "{\"action\": \"configure\"}"
```


text:
<mods xmlns="http://www.loc.gov/mods/v3" xmlns:exslt="http://exslt.org/common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd" version="3.3" ID="P0b002ee181721681">
<name type="corporate">
 <namePart>United States Government Printing Office</namePart>
 <role>
  <roleTerm type="text" authority="marcrelator">printer</roleTerm>
  <roleTerm type="code" authority="marcrelator">prt</roleTerm>
</role>
 <role>
  <roleTerm type="text" authority="marcrelator">distributor</roleTerm>
  <roleTerm type="code" authority="marcrelator">dst</roleTerm>
</role>
</name>
<name type="corporate">
 <namePart>United States</namePart>
 <namePart>United States Court of Appeals for the Eighth Circuit</namePart>
 <role>
  <roleTerm type="text" authority="marcrelator">author</roleTerm>
  <roleTerm type="code" authority="marcrelator">aut</roleTerm>
</role>
 <description>Government Organization</description>
</name>
<typeOfResource>text</typeOfResource>
<genre authority="marcgt">government publication</genre>
<language>
 <languageTerm authority="iso639-2b" type="code">eng</languageTerm>
</language>
<extension>
 <collectionCode>USCOURTS</collectionCode>
 <category>Judicial Publications</category>
 <branch>judicial</branch>
 <dateIngested>2012-01-12</dateIngested>
</extension>
<originInfo>
 <publisher>Administrative Office of the United States Courts</publisher>
 <dateIssued encoding="w3cdtf">2012-01-11</dateIssued>
 <issuance>monographic</issuance>
</originInfo>
<physicalDescription>
 <note type="source content type">deposited</note>
 <digitalOrigin>born digital</digitalOrigin>
</physicalDescription>
<classification authority="sudocs">JU 2.11</classification>
<identifier type="uri">http://www.gpo.gov/fdsys/pkg/USCOURTS-ca8-11-01745</identifier>
<identifier type="local">P0b002ee181721681</identifier>
<recordInfo>
 <recordContentSource authority="marcorg">DGPO</recordContentSource>
 <recordCreationDate encoding="w3cdtf">2012-01-12</recordCreationDate>
 <recordChangeDate encoding="w3cdtf">2012-01-12</recordChangeDate>
 <recordIdentifier source="DGPO">USCOURTS-ca8-11-01745</recordIdentifier>
 <recordOrigin>machine generated</recordOrigin>
 <languageOfCataloging>
  <languageTerm authority="iso639-2b" type="code">eng</languageTerm>
</languageOfCataloging>
</recordInfo>
<accessCondition type="GPO scope determination">fdlp</accessCondition>
<extension>
 <docClass>USCOURTS</docClass>
 <accessId>USCOURTS-ca8-11-01745</accessId>
 <courtType>Appellate</courtType>
 <courtCode>ca8</courtCode>
 <courtCircuit>8th</courtCircuit>
 <courtSortOrder>1080</courtSortOrder>
 <caseNumber>11-01745</caseNumber>
 <natureSuitCode>890</natureSuitCode>
 <natureSuit>Other Statutory Actions</natureSuit>
 <party firstName="Michael" fullName="Michael Black" lastName="Black" role="Appellee"></party>
 <party fullName="City of Sisseton" lastName="City of Sisseton" role="Appellant"></party>
 <party fullName="County of Roberts" lastName="County of Roberts" role="Appellant"></party>
 <party firstName="Larry" fullName="Larry Echo Hawk" lastName="Echo Hawk" role="Appellee"></party>
 <party firstName="Russell" fullName="Russell Hawkins" lastName="Hawkins" role="Appellee"></party>
 <party fullName="Sisseton School District No. 54-2" lastName="Sisseton School District No. 54-2" role="Appellant"></party>
 <party fullName="Sisseton-Wahpeton Oyate of the Lake Traverse Reservation" lastName="Sisseton-Wahpeton Oyate of the Lake Traverse Reservation" role="Amicus on Behalf of Appellee"></party>
 <party fullName="State of South Dakota" lastName="State of South Dakota" role="Appellant"></party>
 <party fullName="United States Department of Interior" lastName="United States Department of Interior" role="Appellee"></party>
 <party fullName="Wilmont School District No. 54-7" lastName="Wilmont School District No. 54-7" role="Appellant"></party>
</extension>
<titleInfo>
 <title>State of South Dakota, et al v. U.S. Department of Interior, et al</title>
 <partNumber>11-01745</partNumber>
</titleInfo>
<location>
 <url access="object in context" displayLabel="Content Detail">http://www.gpo.gov/fdsys/pkg/USCOURTS-ca8-11-01745/content-detail.html</url>
</location>
<classification authority="sudocs">JU 2.11</classification>
<identifier type="preferred citation">11-01745;11-1745</identifier>
<name type="corporate">
 <namePart>United States Court of Appeals for the Eighth Circuit</namePart>
 <namePart>8th Circuit</namePart>
 <namePart></namePart>
 <affiliation>U.S. Courts</affiliation>
 <role>
  <roleTerm authority="marcrelator" type="text">author</roleTerm>
  <roleTerm authority="marcrelator" type="code">aut</roleTerm>
</role>
</name>
<name type="personal">
 <displayForm>Michael Black</displayForm>
 <namePart type="family">Black</namePart>
 <namePart type="given">Michael</namePart>
 <namePart type="termsOfAddress"></namePart>
 <description>Appellee</description>
</name>
<name type="personal">
 <displayForm>City of Sisseton</displayForm>
 <namePart type="family">City of Sisseton</namePart>
 <namePart type="given"></namePart>
 <namePart type="termsOfAddress"></namePart>
 <description>Appellant</description>
</name>
<name type="personal">
 <displayForm>County of Roberts</displayForm>
 <namePart type="family">County of Roberts</namePart>
 <namePart type="given"></namePart>
 <namePart type="termsOfAddress"></namePart>
 <description>Appellant</description>
</name>
<name type="personal">
 <displayForm>Larry Echo Hawk</displayForm>
 <namePart type="family">Echo Hawk</namePart>
 <namePart type="given">Larry</namePart>
 <namePart type="termsOfAddress"></namePart>
 <description>Appellee</description>
</name>
<name type="personal">
 <displayForm>Russell Hawkins</displayForm>
 <namePart type="family">Hawkins</namePart>
 <namePart type="given">Russell</namePart>
 <namePart type="termsOfAddress"></namePart>
 <description>Appellee</description>
</name>
<name type="personal">
 <displayForm>Sisseton School District No. 54-2</displayForm>
 <namePart type="family">Sisseton School District No. 54-2</namePart>
 <namePart type="given"></namePart>
 <namePart type="termsOfAddress"></namePart>
 <description>Appellant</description>
</name>
<name type="personal">
 <displayForm>Sisseton-Wahpeton Oyate of the Lake Traverse Reservation</displayForm>
 <namePart type="family">Sisseton-Wahpeton Oyate of the Lake Traverse Reservation</namePart>
 <namePart type="given"></namePart>
 <namePart type="termsOfAddress"></namePart>
 <description>Amicus on Behalf of Appellee</description>
</name>
<name type="personal">
 <displayForm>State of South Dakota</displayForm>
 <namePart type="family">State of South Dakota</namePart>
 <namePart type="given"></namePart>
 <namePart type="termsOfAddress"></namePart>
 <description>Appellant</description>
</name>
<name type="personal">
 <displayForm>United States Department of Interior</displayForm>
 <namePart type="family">United States Department of Interior</namePart>
 <namePart type="given"></namePart>
 <namePart type="termsOfAddress"></namePart>
 <description>Appellee</description>
</name>
<name type="personal">
 <displayForm>Wilmont School District No. 54-7</displayForm>
 <namePart type="family">Wilmont School District No. 54-7</namePart>
 <namePart type="given"></namePart>
 <namePart type="termsOfAddress"></namePart>
 <description>Appellant</description>
</name>
<extension>
 <docClass>USCOURTS</docClass>
 <accessId>USCOURTS-ca8-11-01745</accessId>
 <courtType>Appellate</courtType>
 <courtCode>ca8</courtCode>
 <courtCircuit>8th</courtCircuit>
 <courtSortOrder>1080</courtSortOrder>
 <caseNumber>11-01745</caseNumber>
 <natureSuitCode>890</natureSuitCode>
 <natureSuit>Other Statutory Actions</natureSuit>
 <party firstName="Michael" fullName="Michael Black" lastName="Black" role="Appellee"></party>
 <party fullName="City of Sisseton" lastName="City of Sisseton" role="Appellant"></party>
 <party fullName="County of Roberts" lastName="County of Roberts" role="Appellant"></party>
 <party firstName="Larry" fullName="Larry Echo Hawk" lastName="Echo Hawk" role="Appellee"></party>
 <party firstName="Russell" fullName="Russell Hawkins" lastName="Hawkins" role="Appellee"></party>
 <party fullName="Sisseton School District No. 54-2" lastName="Sisseton School District No. 54-2" role="Appellant"></party>
 <party fullName="Sisseton-Wahpeton Oyate of the Lake Traverse Reservation" lastName="Sisseton-Wahpeton Oyate of the Lake Traverse Reservation" role="Amicus on Behalf of Appellee"></party>
 <party fullName="State of South Dakota" lastName="State of South Dakota" role="Appellant"></party>
 <party fullName="United States Department of Interior" lastName="United States Department of Interior" role="Appellee"></party>
 <party fullName="Wilmont School District No. 54-7" lastName="Wilmont School District No. 54-7" role="Appellant"></party>
</extension>
<relatedItem type="constituent" ID="id-USCOURTS-ca8-11-01745-0" xlink:href="http://www.gpo.gov/fdsys/granule/USCOURTS-ca8-11-01745/USCOURTS-ca8-11-01745-0/mods.xml">
 <titleInfo>
  <title>State of South Dakota, et al v. U.S. Department of Interior, et al</title>
  <subTitle>OPINION FILED - THE COURT: WILLIAM JAY RILEY, ROGER L. WOLLMAN and C. ARLEN BEAM. William Jay Riley, Authoring Judge (PUBLISHED) [3867802] [11-1745]</subTitle>
  <partNumber>0</partNumber>
</titleInfo>
 <originInfo>
  <dateIssued>2012-01-11</dateIssued>
</originInfo>
 <relatedItem xlink:href="http://www.gpo.gov/fdsys/pkg/pdf/USCOURTS-ca8-11-01745-0.pdf" type="otherFormat">
  <identifier type="FDsys Unique ID">D09002ee18172250b</identifier>
</relatedItem>
 <identifier type="uri">http://www.gpo.gov/fdsys/granule/USCOURTS-ca8-11-01745/USCOURTS-ca8-11-01745-0</identifier>
 <identifier type="former granule identifier">ca8-11-01745_0.pdf</identifier>
 <location>
  <url access="object in context" displayLabel="Content Detail">http://www.gpo.gov/fdsys/granule/USCOURTS-ca8-11-01745/USCOURTS-ca8-11-01745-0/content-detail.html</url>
  <url access="raw object" displayLabel="PDF rendition">http://www.gpo.gov/fdsys/pkg/USCOURTS-ca8-11-01745/pdf/USCOURTS-ca8-11-01745-0.pdf</url>
</location>
 <extension>
  <searchTitle>USCOURTS 11-01745; State of South Dakota, et al v. U.S. Department of Interior, et al; </searchTitle>
  <courtName>United States Court of Appeals for the Eighth Circuit</courtName>
  <accessId>USCOURTS-ca8-11-01745-0</accessId>
  <sequenceNumber>0</sequenceNumber>
  <dateIssued>2012-01-11</dateIssued>
  <docketText>OPINION FILED - THE COURT: WILLIAM JAY RILEY, ROGER L. WOLLMAN and C. ARLEN BEAM. William Jay Riley, Authoring Judge (PUBLISHED) [3867802] [11-1745]</docketText>
</extension>
</relatedItem>
</mods>


text:
//!  Copyright [2017] <João Vicente Souto>
#ifndef STRUCTURES_BINARY_TREE_H
#define STRUCTURES_BINARY_TREE_H

#include <cstdint>  // std::size_t
#include <stdexcept>  // C++ exceptions
#include "array_list.h"

namespace structures {

//! Classe Árvore binária
/*! Implementação de uma árvore binária de busca.
 *  \author João Vicente Souto.
 *  \since 13/05/17
 *  \version 1.0
 */
template<typename T>
class BinaryTree {
 public:
    BinaryTree();
    ~BinaryTree();

    void insert(const T& data);
    void remove(const T& data);
    bool contains(const T& data) const;

    bool empty() const;
    std::size_t size() const;

    ArrayList<T> pre_order() const;
    ArrayList<T> in_order() const;
    ArrayList<T> post_order() const;

 private:
    struct Node {
        //! Construtor padrão
        /*! Inicializado com o dado.
         *  \param data dado que será armazenado.
         *  \sa ~Node()
         */
        explicit Node(const T& data) :
        data_{data}
        {}

        //! Destrutor
        /*! Destruindo os filhos, deve ser recursivo.
         *  \sa Node(const T& data)
         */
        ~Node() {
            delete left_;
            delete right_;
        }

        T data_;  //! Dado
        Node* left_{nullptr};  //! Filho da esquerda
        Node* right_{nullptr};  //! Filho da direita

        //! Inserir
        /*! Insere o dado na árvore seguindo ordem de grandeza
         *  \param data Dado à ser inserido.
         */
        void insert(const T& data) {
            if (data < data_) {
                if (left_ == nullptr) {
                    left_ = new Node(data);
                    if (left_ == nullptr)
                        throw std::out_of_range("Full tree!");
                } else {
                    left_->insert(data);
                }
            } else {
                if (right_ == nullptr) {
                    right_ = new Node(data);
                    if (right_ == nullptr)
                        throw std::out_of_range("Full tree!");
                } else {
                    right_->insert(data);
                }
            }
        }

        //! Remover padrão
        /*! Comportamento inicial de remoção, uso auxiliar de outra função.
         *  \param data Dado à ser removido.
         *  \return bool verdadeiro se foi removido com sucesso.
         *  \sa remove(const T& data, Node* arv, bool deleted)
         */
        bool remove(const T& data) {
            bool deleted = false;
            if (data < data_ && left_ != nullptr) {
                left_ = remove(data, left_, deleted);
            } else if (data > data_ && right_ != nullptr) {
                right_ = remove(data, right_, deleted);
            } else {
                if (right_ != nullptr && left_ != nullptr) {
                    Node* temp = right_->minimum();
                    data_ = temp->data_;
                    right_ = remove(data_, right_, deleted);
                } else if (right_ != nullptr) {
                    Node* temp = right_;
                    data_ = temp->data_;
                    right_ = temp->right_;
                    left_ = temp->left_;
                    temp->right_ = temp->left_ = nullptr;
                    delete temp;
                    deleted = true;
                } else if (left_ != nullptr) {
                    Node* temp = left_;
                    data_ = temp->data_;
                    right_ = temp->right_;
                    left_ = temp->left_;
                    temp->right_ = temp->left_ = nullptr;
                    delete temp;
                    deleted = true;
                }
            }
            return deleted;
        }

        //! Contém dado
        /*! Verifica se contém algum dado
         *  \param data Dado à ser procurado.
         *  \return bool verdadeiro se encontrou o dado.
         */
        bool contains(const T& data) const {
            if (data < data_)
                return left_ == nullptr? false : left_->contains(data);
            else if (data > data_)
                return right_ == nullptr? false : right_->contains(data);
            else
                return true;
        }

        //! Pré-ordem
        /*! Busca os dados em pré-ordem
         *  \param v ArrayList<T> para inserção dos dados.
         *  \sa in_order(), post_order()
         */
        void pre_order(ArrayList<T>& v) const {
            v.push_back(data_);
            if (left_ != nullptr)
                left_->pre_order(v);
            if (right_ != nullptr)
                right_->pre_order(v);
        }

        //! Em-ordem
        /*! Busca os dados em em-ordem
         *  \param v ArrayList<T> para inserção dos dados.
         *  \sa pre_order(), post_order()
         */
        void in_order(ArrayList<T>& v) const {
            if (left_ != nullptr)
                left_->in_order(v);
            v.push_back(data_);
            if (right_ != nullptr)
                right_->in_order(v);
        }

        //! Pós-ordem
        /*! Busca os dados em pós-ordem
         *  \param v ArrayList<T> para inserção dos dados.
         *  \sa in_order(), pre_order()
         */
        void post_order(ArrayList<T>& v) const {
            if (left_ != nullptr)
                left_->post_order(v);
            if (right_ != nullptr)
                right_->post_order(v);
            v.push_back(data_);
        }

     private:
        //! Complemento da funcão remover
        /*! Comportamento complementar ao remover
         *  \param data Dado à ser removido.
         *  \return Node* Node que vai ocupar lugar do antigo.
         *  \sa remove()
         */
        Node* remove(const T& data, Node* arv, bool& deleted) {
            deleted = false;
            if (arv == nullptr)
                return arv;
            // Go to left
            if (data < arv->data_) {
                arv->left_ = remove(data, arv->left_, deleted);
                return arv;
            }
            // Go to right
            if (data > arv->data_) {
                arv->right_ = remove(data, arv->right_, deleted);
                return arv;
            }
            // I found
            // Two sons
            if (arv->right_ != nullptr && arv->left_ != nullptr) {
                Node* temp = arv->right_->minimum();
                arv->data_ = temp->data_;
                arv->right_ = remove(data, arv->right_, deleted);
                return arv;
            }
            // One son or leaf
            Node* temp = nullptr;
            if (arv->right_ != nullptr)
                temp = arv->right_;
            else
                temp = arv->left_;

            arv->right_ = arv->left_ = nullptr;
            delete arv;
            deleted = true;
            return temp;
        }

        //! Encontra o menor node
        /*! Encontra o node com menor valor em data
         *  \return Node* Node com menor valor em data
         */
        Node* minimum() {
            if (left_ == nullptr)
                return this;
            return left_->minimum();
        }
    };

    Node* root_{nullptr};  //!< Raiz
    std::size_t size_{0};  //!< Tamanho
};

//! Construtor
/*! Construtor padrão
 *  \sa ~BinaryTree()
 */
template<typename T>
BinaryTree<T>::BinaryTree()
{}

//! Destrutor
/*! Destruindo a raiz, e por recursividade, os filhos;
 *  \sa BinaryTree()
 */
template<typename T>
BinaryTree<T>::~BinaryTree() {
    delete root_;
}

//! Inserir
/*! Insere o dado na árvore seguindo ordem de grandeza
 *  \param data Dado à ser inserido.
 */
template<typename T>
void BinaryTree<T>::insert(const T& data) {
    if (empty()) {
        root_ = new Node(data);
        if (root_ == nullptr)
            throw std::out_of_range("Full tree!");
    } else {
        root_->insert(data);
    }
    ++size_;
}

//! Remove
/*! Remove um dado da árvore
 *  \param data Dado à ser removido.
 */
template<typename T>
void BinaryTree<T>::remove(const T& data) {
    if (empty())
        throw std::out_of_range("Empty tree!");

    if (size() != 1u) {
        if (root_->remove(data))
            --size_;
    } else {
        // If the root to delete and no sons
        if (root_->data_ == data) {
            delete root_;
            root_ = nullptr;
            --size_;
        }
    }
}

//! Contém dado
/*! Verifica se contém algum dado
 *  \param data Dado à ser procurado.
 *  \return bool verdadeiro se encontrou o dado.
 */
template<typename T>
bool BinaryTree<T>::contains(const T& data) const {
    if (empty())
        return false;
    return root_->contains(data);
}

//! Árvore vazia
/*! Verifica se a árvore esta vazia
 *  \return bool verdadeiro se estiver vazia
 */
template<typename T>
bool BinaryTree<T>::empty() const {
    return size() == 0;
}

//! Tamanho da Árvore
/*! Retorna a quantidade de dados na árvore
 *  \return size_t quantidade de dados.
 */
template<typename T>
std::size_t BinaryTree<T>::size() const {
    return size_;
}

//! Pré-ordem
/*! Busca os dados em pré-ordem
 *  \return ArrayList<T> dados em pré-ordem
 *  \sa in_order(), post_order()
*/
template<typename T>
ArrayList<T> BinaryTree<T>::pre_order() const {
    ArrayList<T> v{size()};
    if (!empty())
        root_->pre_order(v);
    return v;
}

//! Em-ordem
/*! Busca os dados em em-ordem
 *  \return ArrayList<T> dados em-ordem
 *  \sa pre_order(), post_order()
 */
template<typename T>
ArrayList<T> BinaryTree<T>::in_order() const {
    ArrayList<T> v{size_};
    if (!empty())
        root_->in_order(v);
    return v;
}

//! Pós-ordem
/*! Busca os dados em pós-ordem
 *  \return ArrayList<T> dados em pós-ordem
 *  \sa in_order(), pre_order()
 */
template<typename T>
ArrayList<T> BinaryTree<T>::post_order() const {
    ArrayList<T> v{size_};
    if (!empty())
        root_->post_order(v);
    return v;
}

}  // namespace structures

#endif


text:
{% load staticfiles %}
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}{% endblock %}</title>
    {% block css %}{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
<!-- jQuery -->
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
{% block js %}{% endblock %}
<script>
    window.fbAsyncInit = function () {
        FB.init({
            appId: '172511599870594',
            xfbml: true,
            version: 'v2.6'
        });
    };

    (function (d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {
            return;
        }
        js = d.createElement(s);
        js.id = id;
        js.src = "//connect.facebook.net/en_US/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
</script>
</body>
</html>


text:
using System;
using System.Collections.Generic;
using System.Linq;
using AutoAdapter.Fody.DTOs;
using AutoAdapter.Fody.Interfaces;
using Mono.Cecil;
using Mono.Cecil.Cil;

namespace AutoAdapter.Fody
{
    public class CreatorOfInsturctionsForArgument : ICreatorOfInsturctionsForArgument
    {
        public Instruction[] CreateInstructionsForArgument(
            SourceAndTargetParameters parameters,
            ILProcessor ilProcessor,
            Maybe<FieldDefinition> extraParametersField)
        {
            if (parameters.TargetParameter.HasValue)
                return CreateInstructionsForArgumentUsingTargetParameter(parameters, ilProcessor);

            if (extraParametersField.HasValue)
            {
                var instructions =
                    CreateInsturctionsForArgumentUsingExtraParametersObject(
                        parameters,
                        ilProcessor,
                        extraParametersField.GetValue());

                if (instructions.HasValue)
                    return instructions.GetValue();
            }

            if (parameters.SourceParameter.IsOptional &&
                parameters.SourceParameter.HasDefault &&
                parameters.SourceParameter.HasConstant)
            {
                return CreateInsturctionsArgumentUsingDefaultConstantValueOfSourceParameter(parameters, ilProcessor);
            }

            throw new Exception(
                $"Source parameter {parameters.SourceParameter.Name} is not optional with a default constant value and parameter value is not supplied in request");
        }

        private Instruction[] CreateInstructionsForArgumentUsingTargetParameter(
            SourceAndTargetParameters parameters,
            ILProcessor ilProcessor)
        {
            return new[]
            {
                ilProcessor.Create(OpCodes.Ldarg, parameters.TargetParameter.GetValue().Index + 1)
            };
        }

        private Instruction[] CreateInsturctionsArgumentUsingDefaultConstantValueOfSourceParameter(
            SourceAndTargetParameters parameters,
            ILProcessor ilProcessor)
        {
            switch (parameters.SourceParameter.ParameterType.FullName)
            {
                case "System.Int32":
                    return new[]
                    {
                        ilProcessor.Create(
                            OpCodes.Ldc_I4,
                            (int) parameters.SourceParameter.Constant)
                    };
                case "System.Int64":
                    return new[]
                    {
                        ilProcessor.Create(
                            OpCodes.Ldc_I8,
                            (long) parameters.SourceParameter.Constant)
                    };
                case "System.String":
                    return new[]
                    {
                        ilProcessor.Create(
                            OpCodes.Ldstr,
                            (string) parameters.SourceParameter.Constant)
                    };
                case "System.Single":
                    return new[]
                    {
                        ilProcessor.Create(
                            OpCodes.Ldc_R4,
                            (float) parameters.SourceParameter.Constant)
                    };
                case "System.Double":
                    return new[]
                    {
                        ilProcessor.Create(
                            OpCodes.Ldc_R8,
                            (double) parameters.SourceParameter.Constant)
                    };
            }
            throw new Exception("Unsupported optional parameter constant type");
        }

        public Maybe<Instruction[]> CreateInsturctionsForArgumentUsingExtraParametersObject(
            SourceAndTargetParameters parameters,
            ILProcessor ilProcessor,
            FieldDefinition extraParametersField)
        {
            var resolvedExtraParametersObjectType = extraParametersField.FieldType.Resolve();

            var instructions = new List<Instruction>();

            instructions.Add(ilProcessor.Create(OpCodes.Ldarg_0));

            instructions.Add(ilProcessor.Create(OpCodes.Ldfld, extraParametersField));

            var propertyOnExtraParametersObject =
                resolvedExtraParametersObjectType.Properties
                    .FirstOrDefault(p => p.Name == parameters.SourceParameter.Name);

            if (propertyOnExtraParametersObject == null)
                return Maybe<Instruction[]>.NoValue();

            var propertyGetMethod = propertyOnExtraParametersObject.GetMethod;

            var propertyReturnType = propertyGetMethod.MethodReturnType.ReturnType;

            var propertyGetMethodReference =
                new MethodReference(
                        propertyGetMethod.Name,
                        propertyReturnType,
                        extraParametersField.FieldType)
                    { HasThis = true };

            instructions.Add(ilProcessor.Create(OpCodes.Callvirt, propertyGetMethodReference));

            return instructions.ToArray();
        }
    }
}