func (e HasElementData) HasRemote() bool {
	return e.remoteSet
}
HasRemote implements Element.HasRemote
package apply
import (
	"fmt"
)
type Element interface {
	FieldMeta
	Merge(Strategy) (Result, error)
	HasRecorded() bool
	GetRecorded() interface{}
	HasLocal() bool
	GetLocal() interface{}
	HasRemote() bool
	GetRemote() interface{}
}
type FieldMeta interface {
	GetFieldMergeType() string
	GetFieldMergeKeys() MergeKeys
	GetFieldType() string
}
type FieldMetaImpl struct {
	MergeType string
	MergeKeys MergeKeys
	Type string
	Name string
}
func (s FieldMetaImpl) GetFieldMergeType() string {
	return s.MergeType
}
func (s FieldMetaImpl) GetFieldMergeKeys() MergeKeys {
	return s.MergeKeys
}
func (s FieldMetaImpl) GetFieldType() string {
	return s.Type
}
type MergeKeyValue map[string]string
func (v MergeKeyValue) Equal(o MergeKeyValue) bool {
	if len(v) != len(o) {
		return false
	}
	for key, v1 := range v {
		if v2, found := o[key]; !found || v1 != v2 {
			return false
		}
	}
	return true
}
type MergeKeys []string
func (mk MergeKeys) GetMergeKeyValue(i interface{}) (MergeKeyValue, error) {
	result := MergeKeyValue{}
	if len(mk) <= 0 {
		return result, fmt.Errorf("merge key must have at least 1 value to merge")
	}
	m, ok := i.(map[string]interface{})
	if !ok {
		return result, fmt.Errorf("cannot use mergekey %v for primitive item in list %v", mk, i)
	}
	for _, field := range mk {
		if value, found := m[field]; !found {
			result[field] = ""
		} else {
			result[field] = fmt.Sprintf("%v", value)
		}
	}
	return result, nil
}
type CombinedPrimitiveSlice struct {
	Items []*PrimitiveListItem
}
type PrimitiveListItem struct {
	Value interface{}
	RawElementData
}
func (s *CombinedPrimitiveSlice) lookup(l interface{}) *PrimitiveListItem {
	val := fmt.Sprintf("%v", l)
	for _, i := range s.Items {
		if fmt.Sprintf("%v", i.Value) == val {
			return i
		}
	}
	return nil
}
func (s *CombinedPrimitiveSlice) upsert(l interface{}) *PrimitiveListItem {
	if item := s.lookup(l); item != nil {
		return item
	}
	item := &PrimitiveListItem{
		Value: l,
	}
	s.Items = append(s.Items, item)
	return item
}
func (s *CombinedPrimitiveSlice) UpsertRecorded(l interface{}) {
	v := s.upsert(l)
	v.recorded = l
	v.recordedSet = true
}
func (s *CombinedPrimitiveSlice) UpsertLocal(l interface{}) {
	v := s.upsert(l)
	v.local = l
	v.localSet = true
}
func (s *CombinedPrimitiveSlice) UpsertRemote(l interface{}) {
	v := s.upsert(l)
	v.remote = l
	v.remoteSet = true
}
type ListItem struct {
	KeyValue MergeKeyValue
	RawElementData
}
type CombinedMapSlice struct {
	Items []*ListItem
}
func (s *CombinedMapSlice) lookup(v MergeKeyValue) *ListItem {
	for _, i := range s.Items {
		if i.KeyValue.Equal(v) {
			return i
		}
	}
	return nil
}
func (s *CombinedMapSlice) upsert(key MergeKeys, l interface{}) (*ListItem, error) {
	val, err := key.GetMergeKeyValue(l)
	if err != nil {
		return nil, err
	}
	if item := s.lookup(val); item != nil {
		return item, nil
	}
	item := &ListItem{
		KeyValue: val,
	}
	s.Items = append(s.Items, item)
	return item, nil
}
func (s *CombinedMapSlice) UpsertRecorded(key MergeKeys, l interface{}) error {
	item, err := s.upsert(key, l)
	if err != nil {
		return err
	}
	item.SetRecorded(l)
	return nil
}
func (s *CombinedMapSlice) UpsertLocal(key MergeKeys, l interface{}) error {
	item, err := s.upsert(key, l)
	if err != nil {
		return err
	}
	item.SetLocal(l)
	return nil
}
func (s *CombinedMapSlice) UpsertRemote(key MergeKeys, l interface{}) error {
	item, err := s.upsert(key, l)
	if err != nil {
		return err
	}
	item.SetRemote(l)
	return nil
}
func IsDrop(e Element) bool {
	removed := e.HasRecorded() && !e.HasLocal()
	setToNil := e.HasLocal() && e.GetLocal() == nil
	return removed || setToNil
}
func IsAdd(e Element) bool {
	return e.HasLocal() && !e.HasRemote()
}
func NewRawElementData(recorded, local, remote interface{}) RawElementData {
	data := RawElementData{}
	if recorded != nil {
		data.SetRecorded(recorded)
	}
	if local != nil {
		data.SetLocal(local)
	}
	if remote != nil {
		data.SetRemote(remote)
	}
	return data
}
type RawElementData struct {
	HasElementData
	recorded interface{}
	local    interface{}
	remote   interface{}
}
func (b *RawElementData) SetRecorded(value interface{}) {
	b.recorded = value
	b.recordedSet = true
}
func (b *RawElementData) SetLocal(value interface{}) {
	b.local = value
	b.localSet = true
}
func (b *RawElementData) SetRemote(value interface{}) {
	b.remote = value
	b.remoteSet = true
}
func (b RawElementData) GetRecorded() interface{} {
	if b.recorded == nil {
		return nil
	}
	return b.recorded
}
func (b RawElementData) GetLocal() interface{} {
	if b.local == nil {
		return nil
	}
	return b.local
}
func (b RawElementData) GetRemote() interface{} {
	if b.remote == nil {
		return nil
	}
	return b.remote
}
type HasElementData struct {
	recordedSet bool
	localSet    bool
	remoteSet   bool
}
func (e HasElementData) HasRecorded() bool {
	return e.recordedSet
}
func (e HasElementData) HasLocal() bool {
	return e.localSet
}