func (p *PolicyLine) FilterPolicies(predicate PolicyPredicate) []*Policy {
	var policies []*Policy
	if p.PPolicy != nil && predicate(p.PPolicy) {
		policies = append(policies, p.PPolicy)
	}
	if p.LArg != nil {
		policies = append(policies, p.LArg.FilterPolicies(predicate)...)
	}
	if p.RArg != nil {
		policies = append(policies, p.RArg.FilterPolicies(predicate)...)
	}
	return policies
}
FilterPolicies filters the policies in the current PolicyLine that satisfy the given predicate
package policy
import (
	"fmt"
	"log"
	"os"
	"strings"
	"time"
)
var logger = log.New(os.Stdout, "", log.Lshortfile)
type Rule struct {
	Layer    string `json:"layer"`
	LType    string `json:"layer_type"`
	Pattern  string `json:"pattern"`
	disabled bool
}
var AllowedOperators = []string{"=", ">", "<", "in", "!=", ">=", "<="}
type Expression struct {
	Field string
	Value string
	Op    string
}
func (r *Rule) Match(r1 *Rule) (bool, bool) {
	if strings.Compare(r.Layer, r1.Layer) == 0 &&
		strings.Compare(r.LType, r1.LType) == 0 {
		return true, strings.Compare(r.Pattern, r1.Pattern) == 0
	}
	return false, false
}
func (r *Rule) Expression() Expression {
	var expr Expression
	for _, op := range AllowedOperators {
		if idx := strings.Index(r.Pattern, op); idx != -1 {
			expr = Expression{
				Op:    op,
				Field: r.Pattern[:idx],
				Value: r.Pattern[idx+len(op):],
			}
		}
	}
	return expr
}
func (r *Rule) String() string {
	return fmt.Sprintf("Rule: %v/%v/%v", r.Layer, r.LType, r.Pattern)
}
type Operator int
const (
	AND = Operator(iota)
	OR
	NONE
)
type RuleSet struct {
	OOperator Operator
	RRule     *Rule
	LArg      *RuleSet
	RArg      *RuleSet
}
func (rs *RuleSet) MatchRule(r *Rule) (bool, bool) {
	if r.disabled {
		return true, true
	}
	if rs.OOperator == NONE {
		return rs.RRule.Match(r)
	}
	if rs.OOperator == AND {
		lAccept, lMatch := rs.LArg.MatchRule(r)
		rAccept, rMatch := rs.RArg.MatchRule(r)
		if rAccept && lAccept {
			return true, rMatch && lMatch
		}
		return lAccept || rAccept, lMatch || rMatch
	}
	if rs.OOperator == OR {
		lAccept, lMatch := rs.LArg.MatchRule(r)
		if lAccept && lMatch {
			return true, true
		}
		rAccept, rMatch := rs.RArg.MatchRule(r)
		if rAccept && rMatch {
			return true, true
		}
		if lAccept || rAccept {
			return true, false
		}
	}
	return false, false
}
func (rs *RuleSet) Match(rs1 *RuleSet) (bool, bool) {
	if rs1.OOperator == NONE {
		return rs.MatchRule(rs1.RRule)
	}
	if rs1.OOperator == AND {
		lAccept, lMatch := rs.Match(rs1.LArg)
		if !lAccept {
			return false, false
		}
		rAccept, rMatch := rs.Match(rs1.RArg)
		if !rAccept {
			return false, false
		}
		return true, lMatch && rMatch
	}
	if rs1.OOperator == OR {
		lAccept, lMatch := rs.Match(rs1.LArg)
		if lAccept && lMatch {
			return true, true
		}
		rAccept, rMatch := rs.Match(rs1.RArg)
		if rAccept && rMatch {
			return true, true
		}
		if lAccept || rAccept {
			return true, false
		}
	}
	return false, false
}
func (rs *RuleSet) And(rs1 *RuleSet) *RuleSet {
	var ruleSet = RuleSet{OOperator: AND, RRule: nil, LArg: rs, RArg: rs1}
	return &ruleSet
}
func (rs *RuleSet) Or(rs1 *RuleSet) *RuleSet {
	var ruleSet = RuleSet{OOperator: OR, RRule: nil, LArg: rs, RArg: rs1}
	return &ruleSet
}
func (rs *RuleSet) Map(function func(*Rule) Rule) *RuleSet {
	var rule Rule
	var left, right *RuleSet
	if rs.RRule != nil {
		rule = function(rs.RRule)
	}
	if rs.LArg != nil {
		left = rs.LArg.Map(function)
	}
	if rs.RArg != nil {
		right = rs.RArg.Map(function)
	}
	return &RuleSet{OOperator: rs.OOperator, RRule: &rule, LArg: left, RArg: right}
}
func (rs *RuleSet) Foreach(function func(*Rule)) {
	if rs.RRule != nil {
		function(rs.RRule)
	}
	if rs.LArg != nil {
		rs.LArg.Foreach(function)
	}
	if rs.RArg != nil {
		rs.RArg.Foreach(function)
	}
}
func (rs *RuleSet) String() string {
	if rs.OOperator == NONE {
		return rs.RRule.String()
	}
	if rs.OOperator == AND {
		return fmt.Sprintf("(%v AND %v)", rs.LArg.String(), rs.RArg.String())
	}
	return fmt.Sprintf("(%v OR %v)", rs.LArg.String(), rs.RArg.String())
}
type Credential struct {
	Name  string `json:"name"`
	Value string `json:"value"`
}
func (c *Credential) Accept(c1 *Credential) bool {
	return strings.Compare(c.Name, c1.Name) == 0 &&
		strings.Compare(c.Value, c1.Value) == 0
}
func (c *Credential) String() string {
	return fmt.Sprintf("Credential: %v/%v", c.Name, c.Value)
}
type Resource struct {
	Name         *RuleSet    `json:"rules"`
	IdentifiedBy *Credential `json:"identified_by"`
	fieldsToMatch []string
}
func getRulesToMatch(fieldsToMatch []string, input *Resource) *RuleSet {
	return input.Name.Map(func(rule *Rule) Rule {
		expr := rule.Expression()
		r := Rule{
			LType:    rule.LType,
			Layer:    rule.Layer,
			Pattern:  rule.Pattern,
			disabled: true,
		}
		for _, f := range fieldsToMatch {
			if f == expr.Field {
				r.disabled = false
			}
		}
		return r
	})
}
func processRuleFields(r *Resource) {
	if len(r.fieldsToMatch) == 0 {
		r.Name.Foreach(func(rule *Rule) {
			r.fieldsToMatch = append(r.fieldsToMatch, rule.Expression().Field)
		})
	}
}
func (r *Resource) Match(r1 *Resource) (bool, bool) {
	processRuleFields(r)
	rulesToMatch := getRulesToMatch(r.fieldsToMatch, r1)
	accept, match := r.Name.Match(rulesToMatch)
	if !accept {
		return false, false
	}
	if match {
		if r.IdentifiedBy.Accept(r1.IdentifiedBy) {
			return true, true
		}
		return true, false
	}
	return true, false
}
func (r *Resource) String() string {
	return fmt.Sprintf("Resource: %v id by %v", r.Name.String(), r.IdentifiedBy.String())
}
type Duration struct {
	Start time.Time `json:"start"`
	End   time.Time `json:"end"`
}
func (d *Duration) String() string {
	return fmt.Sprintf("%v to %v", d.Start, d.End)
}
type Location struct {
	Name string `json:"name"`
}
func (l *Location) Match(l1 *Location) bool {
	if strings.Compare(l.Name, l1.Name) == 0 {
		return true
	}
	return false
}
func (l *Location) String() string {
	return fmt.Sprintf("%v", l.Name)
}
type Contents struct {
	PluginID string
	Blob     []byte
}
type PolicyBase interface {
	Match(source *Resource, target *Resource, when time.Time, where *Location) (bool, bool, bool)
	String() string
}
const PolicyFormatVersion uint64 = 0
type Policy struct {
	UUID          string      `json:"uuid"`
	FormatVersion uint64      `json:"format_version"`
	PolicyVersion uint64      `json:"policy_version"`
	Description   string      `json:"description"`
	Target        Resource    `json:"target"`
	Allowed       []*Resource `json:"allowed"`
	Disallowed    []*Resource `json:"disallowed"`
	Timeline      Duration    `json:"timeline"`
	Rate          uint64      `json:"rate"`
	LLocation     Location    `json:"location"`
	CContents     []*Contents `json:"contents,omitempty"`
	Signature     string      `json:"signature"`
}
func (p *Policy) Match(source *Resource, target *Resource, when time.Time, where *Location) (bool, bool, bool) {
	if when.Before(p.Timeline.Start) || when.After(p.Timeline.End) {
		return false, false, false
	}
	if !p.LLocation.Match(where) {
		return true, false, false
	}
	_, match := p.Target.Match(target)
	if match == true {
		for _, element := range p.Disallowed {
			if element == nil {
				continue
			}
			_, matchElement := element.Match(source)
			if matchElement == true {
				return true, true, false
			}
		}
		for _, element := range p.Allowed {
			if element == nil {
				continue
			}
			_, matchElement := element.Match(source)
			if matchElement == true {
				return true, true, true
			}
		}
		return true, true, false
	}
	return true, false, false
}
func (p *Policy) String() string {
	return fmt.Sprintf("%v:%v:%v\n\ttarget: %v",
		p.FormatVersion,
		p.PolicyVersion,
		p.Description,
		p.Target.String())
}
type PolicyLine struct {
	OOperator Operator
	PPolicy   *Policy
	LArg      *PolicyLine
	RArg      *PolicyLine
}
func (p *PolicyLine) Match(source *Resource, target *Resource, when time.Time, where *Location) (bool, bool, bool) {
	if p.OOperator == NONE {
		return p.PPolicy.Match(source, target, when, where)
	}
	if p.OOperator == AND {
		lValid, lAccept, lMatch := p.LArg.Match(source, target, when, where)
		if !lValid {
			return false, false, false
		}
		rValid, rAccept, rMatch := p.RArg.Match(source, target, when, where)
		if !rValid {
			return false, false, false
		}
		return true, lAccept && rAccept, lMatch && rMatch
	}
	if p.OOperator == OR {
		lValid, lAccept, lMatch := p.LArg.Match(source, target, when, where)
		if lValid && lAccept && lMatch {
			return true, true, true
		}
		rValid, rAccept, rMatch := p.RArg.Match(source, target, when, where)
		return lValid || rValid, lAccept || rAccept, lMatch || rMatch
	}
	return false, false, false
}
func (p *PolicyLine) String() string {
	if p.OOperator == NONE {
		return p.PPolicy.String()
	} else if p.OOperator == AND {
		return fmt.Sprintf("(%v AND %v)", p.LArg.String(), p.RArg.String())
	} else {  
		return fmt.Sprintf("(%v OR %v)", p.LArg.String(), p.RArg.String())
	}
}