func (obj *AbstractEntity) SetVersion(version int) {
	obj.setVersion(version)
}
SetVersion sets the version of the Entity
package impl
import (
	"bytes"
	"encoding/gob"
	"fmt"
	"reflect"
	"strings"
	"sync/atomic"
	"tgdb"
)
type AbstractEntity struct {
	EntityId           int64
	EntityKind         tgdb.TGEntityKind
	EntityType         tgdb.TGEntityType
	isDeleted          bool
	isInitialized      bool
	isNew              bool
	Version            int
	VirtualId          int64
	graphMetadata      *GraphMetadata
	Attributes         map[string]tgdb.TGAttribute
	ModifiedAttributes []tgdb.TGAttribute
}
var EntitySequencer int64
func DefaultAbstractEntity() *AbstractEntity {
	gob.Register(AbstractEntity{})
	newAbstractEntity := AbstractEntity{
		EntityId: -1,
		isDeleted:          false,
		isNew:              true,
		isInitialized:      true,
		Version:            0,
		Attributes:         make(map[string]tgdb.TGAttribute, 0),
		ModifiedAttributes: make([]tgdb.TGAttribute, 0),
	}
	newAbstractEntity.VirtualId = atomic.AddInt64(&EntitySequencer, -1)
	newAbstractEntity.EntityType = DefaultEntityType()
	return &newAbstractEntity
}
func NewAbstractEntity(gmd *GraphMetadata) *AbstractEntity {
	newAbstractEntity := DefaultAbstractEntity()
	newAbstractEntity.graphMetadata = gmd
	return newAbstractEntity
}
func (obj *AbstractEntity) entityToString() string {
	var buffer bytes.Buffer
	buffer.WriteString("AbstractEntity:{")
	buffer.WriteString(fmt.Sprintf("EntityId: %+v", obj.EntityId))
	buffer.WriteString(fmt.Sprintf(", EntityKind: %d", obj.EntityKind))
	buffer.WriteString(fmt.Sprintf(", EntityType: %+v", obj.EntityType))
	buffer.WriteString(fmt.Sprintf(", IsDeleted: %+v", obj.isDeleted))
	buffer.WriteString(fmt.Sprintf(", IsInitialized: %+v", obj.isInitialized))
	buffer.WriteString(fmt.Sprintf(", IsNew: %+v", obj.isNew))
	buffer.WriteString(fmt.Sprintf(", Version: %d", obj.Version))
	buffer.WriteString(fmt.Sprintf(", virtualId: %d", obj.VirtualId))
	buffer.WriteString(fmt.Sprintf(", Attributes: %+v", obj.Attributes))
	buffer.WriteString(fmt.Sprintf(", ModifiedAttributes: %+v", obj.ModifiedAttributes))
	buffer.WriteString("}")
	return buffer.String()
}
func (obj *AbstractEntity) getAttribute(name string) tgdb.TGAttribute {
	attr := obj.Attributes[name]
	return attr
}
func (obj *AbstractEntity) getAttributes() ([]tgdb.TGAttribute, tgdb.TGError) {
	if obj.Attributes == nil {
		if logger.IsDebug() {
					logger.Debug(fmt.Sprint("ERROR: Returning AbstractEntity:getAttributes as there are NO Attributes associated"))
		}
		errMsg := "This entity does not have any Attributes associated"
		return nil, GetErrorByType(TGErrorIOException, INTERNAL_SERVER_ERROR, errMsg, "")
	}
	attrList := make([]tgdb.TGAttribute, 0)
	for attrName, attr := range obj.Attributes {
		if len(attrName) != 0 {
			if attr.GetAttributeDescriptor().GetName() != "" && strings.ToLower(attr.GetAttributeDescriptor().GetName()) != "@Name" {
				attrList = append(attrList, attr)
			}
		}
	}
	return attrList, nil
}
func (obj *AbstractEntity) getEntityKind() tgdb.TGEntityKind {
	return obj.EntityKind
}
func (obj *AbstractEntity) getEntityType() tgdb.TGEntityType {
	return obj.EntityType
}
func (obj *AbstractEntity) getGraphMetadata() *GraphMetadata {
	return obj.graphMetadata
}
func (obj *AbstractEntity) getModifiedAttributes() []tgdb.TGAttribute {
	return obj.ModifiedAttributes
}
func (obj *AbstractEntity) getVersion() int {
	return obj.Version
}
func (obj *AbstractEntity) getVirtualId() int64 {
	if obj.getIsNew() {
		return obj.VirtualId
	}
	return obj.EntityId
}
func (obj *AbstractEntity) isAttributeSet(name string) bool {
	attr := obj.Attributes[name]
	if !attr.IsNull() {
		return true
	}
	return false
}
func (obj *AbstractEntity) getIsDeleted() bool {
	return obj.isDeleted
}
func (obj *AbstractEntity) getIsInitialized() bool {
	return obj.isInitialized
}
func (obj *AbstractEntity) getIsNew() bool {
	return obj.isNew
}
func (obj *AbstractEntity) resetModifiedAttributes() {
	for _, attr := range obj.ModifiedAttributes {
		attr.ResetIsModified()
	}
	obj.ModifiedAttributes = make([]tgdb.TGAttribute, 0)
}
func (obj *AbstractEntity) setAttributes(attrs map[string]tgdb.TGAttribute) {
	obj.Attributes = attrs
}
func (obj *AbstractEntity) setEntityId(id int64) {
	if obj.getIsNew() {
		obj.VirtualId = id
	} else {
		obj.VirtualId = 0
	}
	obj.EntityId = id
}
func (obj *AbstractEntity) setEntityKind(kind tgdb.TGEntityKind) {
	obj.EntityKind = kind
}
func (obj *AbstractEntity) setEntityType(eType tgdb.TGEntityType) {
	obj.EntityType = eType
}
func (obj *AbstractEntity) setIsDeleted(flag bool) {
	obj.isDeleted = flag
}
func (obj *AbstractEntity) setIsInitialized(flag bool) {
	obj.isInitialized = flag
}
func (obj *AbstractEntity) setIsNew(flag bool) {
	obj.isNew = flag
}
func (obj *AbstractEntity) setModifiedAttributes(mAttrs []tgdb.TGAttribute) {
	obj.ModifiedAttributes = mAttrs
}
func (obj *AbstractEntity) setVersion(version int) {
	obj.Version = version
}
func (obj *AbstractEntity) setAttribute(attr tgdb.TGAttribute) tgdb.TGError {
	attrDesc := attr.GetAttributeDescriptor()
	if attrDesc == nil {
		if logger.IsDebug() {
					logger.Debug(fmt.Sprint("ERROR: Returning AbstractEntity:setAttribute as AttrDesc is EMPTY"))
		}
		errMsg := fmt.Sprintf("Attribute Descriptor cannot be null")
		return GetErrorByType(TGErrorGeneralException, INTERNAL_SERVER_ERROR, errMsg, "")
	}
	attrDescName := attrDesc.GetName()
	if attrDescName == "" {
		if logger.IsDebug() {
					logger.Debug(fmt.Sprint("ERROR: Returning AbstractEntity:setAttribute as attrDescName is EMPTY"))
		}
		errMsg := fmt.Sprintf("Name of the attribute cannot be null")
		return GetErrorByType(TGErrorGeneralException, INTERNAL_SERVER_ERROR, errMsg, "")
	}
	obj.Attributes[attrDescName] = attr
	if !attr.GetIsModified() {
		obj.ModifiedAttributes = append(obj.ModifiedAttributes, attr)
	}
	return nil
}
func (obj *AbstractEntity) setOrCreateAttribute(name string, value interface{}) tgdb.TGError {
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Entering AbstractEntity:SetOrCreateAttribute received N-V Pair as '%+v'='%+v'", name, value))
	}
	if name == "" || value == nil {
		if logger.IsDebug() {
					logger.Debug(fmt.Sprint("ERROR: Returning AbstractEntity:SetOrCreateAttribute as either Name or value is EMPTY"))
		}
		errMsg := fmt.Sprintf("Name of the attribute cannot be null")
		return GetErrorByType(TGErrorGeneralException, INTERNAL_SERVER_ERROR, errMsg, "")
	}
	attr := obj.GetAttribute(name)
	if attr == nil {
		gmd := obj.GetGraphMetadata()
		attrDesc, err := gmd.GetAttributeDescriptor(name)
		if err != nil {
			logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:SetOrCreateAttribute unable to get descriptor for attribute '%s' w/ error '%+v'", name, err.Error()))
			return err
		}
		if attrDesc == nil {
			if value == nil {
				errMsg := fmt.Sprintf("Attribute value is required")
				return GetErrorByType(TGErrorGeneralException, INTERNAL_SERVER_ERROR, errMsg, "")
			}
			aType := reflect.TypeOf(value).String()
			if logger.IsDebug() {
							logger.Debug(fmt.Sprintf("Inside AbstractEntity:SetOrCreateAttribute Abstract Entity creating new attribute '%+v':'%+v'(%+v) <=======", name, value, aType))
			}
			attrDesc = gmd.CreateAttributeDescriptorForDataType(name, aType)
		}
		newAttr, aErr := CreateAttributeWithDesc(nil, attrDesc.(*AttributeDescriptor), nil)
		if aErr != nil {
			logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:SetOrCreateAttribute unable to create attribute '%s' w/ descriptor and value '%+v'", name, value))
			return aErr
		}
		newAttr.SetOwner(obj)
		attr = newAttr
	}
	if !attr.GetIsModified() {
		obj.ModifiedAttributes = append(obj.ModifiedAttributes, attr)
	}
	err := attr.SetValue(value)
	if err != nil {
		logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:SetOrCreateAttribute unable to set attribute value w/ error '%+v'", err.Error()))
		return err
	}
	obj.Attributes[name] = attr
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Returning AbstractEntity:SetOrCreateAttribute created/set attribute for '%+v'='%+v'", name, value))
	}
	return nil
}
func (obj *AbstractEntity) GetIsInitialized() bool {
	return obj.getIsInitialized()
}
func (obj *AbstractEntity) GetModifiedAttributes() []tgdb.TGAttribute {
	return obj.getModifiedAttributes()
}
func (obj *AbstractEntity) SetAttributes(modAttrs map[string]tgdb.TGAttribute) {
	obj.setAttributes(modAttrs)
}
func (obj *AbstractEntity) SetAttributeViaDescriptor(attrDesc *AttributeDescriptor, value interface{}) tgdb.TGError {
	if attrDesc == nil {
		errMsg := "Attribute descriptor is required"
		return GetErrorByType(TGErrorIOException, INTERNAL_SERVER_ERROR, errMsg, "")
	}
	return nil
}
func (obj *AbstractEntity) SetEntityKind(kind tgdb.TGEntityKind) {
	obj.setEntityKind(kind)
}
func (obj *AbstractEntity) SetEntityType(eType tgdb.TGEntityType) {
	obj.setEntityType(eType)
}
func (obj *AbstractEntity) SetIsInitialized(flag bool) {
	obj.setIsInitialized(flag)
}
func (obj *AbstractEntity) SetModifiedAttributes(modAttrs []tgdb.TGAttribute) {
	obj.setModifiedAttributes(modAttrs)
}
func (obj *AbstractEntity) AbstractEntityReadExternal(is tgdb.TGInputStream) tgdb.TGError {
	if logger.IsDebug() {
			logger.Debug(fmt.Sprint("Entering AbstractEntity:AbstractEntityReadExternal"))
	}
	newEntityFlag, err := is.(*ProtocolDataInputStream).ReadBoolean()  
	if err != nil {
		logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityReadExternal - unable to read newEntityFlag w/ Error: '%+v'", err.Error()))
		return err
	}
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal read newEntityFlag as '%+v'", newEntityFlag))
	}
	if newEntityFlag {
		obj.SetIsNew(false)
	}
	eKind, err := is.(*ProtocolDataInputStream).ReadByte()
	if err != nil {
		logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityReadExternal - unable to read eKind w/ Error: '%+v'", err.Error()))
		return err
	}
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal read eKind as '%+v'", eKind))
	}
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal - Object Kind is '%+v'", obj.EntityKind))
	}
	if obj.GetEntityKind() != tgdb.TGEntityKind(eKind) {
		logger.Error(fmt.Sprint("ERROR: Returning AbstractEntity:AbstractEntityReadExternal as obj.GetEntityKind() != types.TGEntityKind(eKind)"))
		errMsg := "Invalid object for deserialization. Expecting..."  
		return GetErrorByType(TGErrorIOException, INTERNAL_SERVER_ERROR, errMsg, "")
	}
	entityId, err := is.(*ProtocolDataInputStream).ReadLong()
	if err != nil {
		logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityReadExternal - unable to read entityId w/ Error: '%+v'", err.Error()))
		return err
	}
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal read entityId as '%d'", entityId))
	}
	version, err := is.(*ProtocolDataInputStream).ReadInt()
	if err != nil {
		logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityReadExternal - unable to read version w/ Error: '%+v'", err.Error()))
		return err
	}
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal read version as '%d'", version))
	}
	var eType tgdb.TGEntityType
	entityTypeId, err := is.(*ProtocolDataInputStream).ReadInt()
	if err != nil {
		logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityReadExternal - unable to read entityTypeId w/ Error: '%+v'", err.Error()))
		return err
	}
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal read entityTypeId as '%d'", entityTypeId))
	}
	if entityTypeId != 0 {
		eType1, err := obj.graphMetadata.GetNodeTypeById(entityTypeId)
		if err != nil {
			logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityReadExternal - unable to read nodeType w/ Error: '%+v'", err.Error()))
			return err
		}
		if logger.IsDebug() {
					logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal verified eType1 (nodeTypeById) as '%+v'", eType1))
		}
		if eType1 == nil {
			eType, err = obj.graphMetadata.GetEdgeTypeById(entityTypeId)
			if err != nil {
				logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityReadExternal - unable to read edgeType w/ Error: '%+v'", err.Error()))
				return err
			}
			if logger.IsDebug() {
							logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal verified eType (edgeTypeById) as '%+v'", eType))
			}
			if eType == nil {
				logger.Warning(fmt.Sprintf("WARNING: Cannot lookup entity desc '%d' from graph meta data cache", entityTypeId))
			}
		} else {
			eType = eType1
		}
	}
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal inferred from metadata, eType as '%+v'", eType))
	}
	count, err := is.(*ProtocolDataInputStream).ReadInt()
	if err != nil {
		logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityReadExternal - unable to read count w/ Error: '%+v'", err.Error()))
		return err
	}
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal read attribute count as '%d'", count))
	}
	for i := 0; i < count; i++ {
		attr, err := ReadExternalForEntity(obj, is)
		if err != nil {
			logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityReadExternal - unable to read attr w/ Error: '%+v'", err.Error()))
			return err
		}
		if logger.IsDebug() {
					logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityReadExternal read attr as '%+v'", attr))
		}
		err = obj.SetAttribute(attr)
		if err != nil {
			logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityReadExternal - unable to set attr w/ Error: '%+v'", err.Error()))
			return err
		}
	}
	obj.EntityId = entityId
	obj.SetEntityType(eType)
	obj.SetIsNew(newEntityFlag)
	obj.SetVersion(version)
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Returning AbstractEntity:AbstractEntityReadExternal w/ NO error, for entity: '%+v'", obj))
	}
	return nil
}
func (obj *AbstractEntity) AbstractEntityWriteExternal(os tgdb.TGOutputStream) tgdb.TGError {
	if logger.IsDebug() {
			logger.Debug(fmt.Sprint("Entering AbstractEntity:AbstractEntityWriteExternal"))
	}
	os.(*ProtocolDataOutputStream).WriteBoolean(obj.GetIsNew())
	os.(*ProtocolDataOutputStream).WriteByte(int(obj.GetEntityKind()))  
	os.(*ProtocolDataOutputStream).WriteLong(obj.GetVirtualId())
	os.(*ProtocolDataOutputStream).WriteInt(obj.GetVersion())
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Inside AbstractEntity:AbstractEntityWriteExternal - obj.EntityType is '%+v'", obj.GetEntityType()))
	}
	if obj.GetEntityType() == nil {
		os.(*ProtocolDataOutputStream).WriteInt(0)
	} else {
		os.(*ProtocolDataOutputStream).WriteInt(obj.GetEntityType().GetEntityTypeId())
	}
	modCount := 0
	for _, attr := range obj.Attributes {
		if attr.GetIsModified() {
			modCount++
		}
	}
	os.(*ProtocolDataOutputStream).WriteInt(modCount)
	for _, attr := range obj.Attributes {
		if !attr.GetIsModified() {
			logger.Warning(fmt.Sprint("WARNING: Continuing loop AbstractEntity:AbstractEntityWriteExternal as attr is NOT modified"))
			continue
		}
		err := attr.WriteExternal(os)
		if err != nil {
			logger.Error(fmt.Sprintf("ERROR: Returning AbstractEntity:AbstractEntityWriteExternal - unable to write attr w/ Error: '%+v'", err.Error()))
			return err
		}
	}
	if logger.IsDebug() {
			logger.Debug(fmt.Sprintf("Returning AbstractEntity:AbstractEntityWriteExternal w/ NO error, for entity: '%+v'", obj))
	}
	return nil
}
func (obj *AbstractEntity) GetAttribute(attrName string) tgdb.TGAttribute {
	return obj.getAttribute(attrName)
}
func (obj *AbstractEntity) GetAttributes() ([]tgdb.TGAttribute, tgdb.TGError) {
	return obj.getAttributes()
}
func (obj *AbstractEntity) GetEntityKind() tgdb.TGEntityKind {
	return obj.getEntityKind()
}
func (obj *AbstractEntity) GetEntityType() tgdb.TGEntityType {
	return obj.getEntityType()
}
func (obj *AbstractEntity) GetGraphMetadata() tgdb.TGGraphMetadata {
	return obj.getGraphMetadata()
}
func (obj *AbstractEntity) GetIsDeleted() bool {
	return obj.getIsDeleted()
}
func (obj *AbstractEntity) GetIsNew() bool {
	return obj.getIsNew()
}
func (obj *AbstractEntity) GetVersion() int {
	return obj.getVersion()
}
func (obj *AbstractEntity) GetVirtualId() int64 {
	return obj.getVirtualId()
}
func (obj *AbstractEntity) IsAttributeSet(attrName string) bool {
	return obj.isAttributeSet(attrName)
}
func (obj *AbstractEntity) ResetModifiedAttributes() {
	obj.resetModifiedAttributes()
}
func (obj *AbstractEntity) SetAttribute(attr tgdb.TGAttribute) tgdb.TGError {
	return obj.setAttribute(attr)
}
func (obj *AbstractEntity) SetOrCreateAttribute(name string, value interface{}) tgdb.TGError {
	return obj.setOrCreateAttribute(name, value)
}
func (obj *AbstractEntity) SetEntityId(id int64) {
	obj.setEntityId(id)
}
func (obj *AbstractEntity) SetIsDeleted(flag bool) {
	obj.setIsDeleted(flag)
}
func (obj *AbstractEntity) SetIsNew(flag bool) {
	obj.setIsNew(flag)
}