/*
 * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
 * Copyright 2020-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * NOTE: This file was generated, manual edits will be overwritten!
 *
 * Generated by 'goCodeGenerator.py':
 *              https://github.com/cboling/OMCI-parser/README.md
 */

package generated

import "github.com/deckarep/golang-set"

// AttributeMeClassID is the 16-bit ID for the OMCI
// Managed entity Attribute ME
const AttributeMeClassID = ClassID(289) // 0x0121

var attributemeBME *ManagedEntityDefinition

// AttributeMe (Class ID: #289 / 0x0121)
//	This ME describes a particular attribute type that is supported by the ONU. This ME is not
//	included in an MIB upload.
//
//	Relationships
//		One or more attribute entities are related to each ME entity. More than one ME entity can refer
//		to a given attribute entity.
//
//	Attributes
//		Managed Entity Id
//			This attribute uniquely identifies each instance of this ME. This number is the same as the one
//			that appears in the attributes table in the ME. Only one instance of each unique attribute need
//			be created. The ONU can assign attribute numbering as it pleases, out of the pool of 64K IDs;
//			however, it is suggested that the numbering follow a rational scheme to aid human readability.
//			(R) (mandatory) (2-bytes)
//
//		Name
//			This attribute contains a 25-byte mnemonic tag for the attribute. Strings shorter than 25-bytes
//			are padded with null characters. (R) (mandatory) (25-bytes)
//
//		Size
//			This attribute contains the size of the attribute, in bytes. The value 0 indicates that the
//			attribute can have a variable/unknown size. (R) (mandatory) (2-bytes)
//
//		Access
//			This attribute represents the OMCI access characteristics of the attribute. The following code
//			points are defined.
//
//			1	Read
//
//			2	Write
//
//			3	Read, write
//
//			5	Read, setbycreate
//
//			6	Write, setbycreate
//
//			7	Read, write, setbycreate
//
//			(R) (mandatory) (1-byte)
//
//		Format
//			This attribute represents the format of the attribute. The following code points are defined.
//
//			1	Pointer
//
//			2	Bit field
//
//			3	Signed integer
//
//			4	Unsigned integer
//
//			5	String
//
//			6	Enumeration (that is, a set of defined code points)
//
//			7	Table
//
//			(R) (mandatory) (1-byte)
//
//		Lower Limit
//			This attribute provides the lowest value for the attribute. Valid for numeric types (pointer,
//			signed integer, unsigned integer) only. For attributes smaller than 4-bytes, the desired numeric
//			value is expressed in 4-byte representation (for example, the 2s complement 1-byte integer 0xFE
//			is expressed as 0xFFFF-FFFE; the unsigned 1-byte integer 0xFE is expressed as 0x0000-00FE). (R)
//			(mandatory) (4-bytes)
//
//		Upper Limit
//			This attribute provides the highest value for the attribute. It has the same validity and format
//			as the lower limit attribute. (R) (mandatory) (4-bytes)
//
//		Bit Field
//			This attribute is a mask of the supported bits in a bit field attribute, valid for bit field
//			type only. A 1 in any position signifies that its code point is supported, while 0 indicates
//			that it is not supported. For bit fields smaller than 4-bytes, the attribute is aligned at the
//			least significant end of the mask. (R) (mandatory) (4-bytes)
//
//		Code Points Table
//			This attribute lists the code points supported by an enumerated attribute. (R) (mandatory) (2 *
//			Q bytes, where Q is the number of entries in the table.)
//
//		Support
//			This attribute represents the level of support of the attribute (same notation as the attribute
//			of the same name in the ME). The following code points are defined.
//
//			1	Fully supported (supported as defined in this object)
//
//			2	Unsupported (OMCI returns an error code if accessed)
//
//			3	Partially supported (some aspects of attribute supported)
//
//			4	Ignored (OMCI supported, but underlying function is not)
//
//			(R) (mandatory) (1-byte)
//
type AttributeMe struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

// Attribute name constants

const AttributeMe_Name = "Name"
const AttributeMe_Size = "Size"
const AttributeMe_Access = "Access"
const AttributeMe_Format = "Format"
const AttributeMe_LowerLimit = "LowerLimit"
const AttributeMe_UpperLimit = "UpperLimit"
const AttributeMe_BitField = "BitField"
const AttributeMe_CodePointsTable = "CodePointsTable"
const AttributeMe_Support = "Support"

func init() {
	attributemeBME = &ManagedEntityDefinition{
		Name:    "AttributeMe",
		ClassID: AttributeMeClassID,
		MessageTypes: mapset.NewSetWith(
			Get,
			GetNext,
		),
		AllowedAttributeMask: 0xff80,
		AttributeDefinitions: AttributeDefinitionMap{
			0: Uint16Field(ManagedEntityID, PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
			1: MultiByteField(AttributeMe_Name, OctetsAttributeType, 0x8000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read), false, false, false, 1),
			2: Uint16Field(AttributeMe_Size, UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read), false, false, false, 2),
			3: ByteField(AttributeMe_Access, UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read), false, false, false, 3),
			4: ByteField(AttributeMe_Format, UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read), false, false, false, 4),
			5: Uint32Field(AttributeMe_LowerLimit, UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read), false, false, false, 5),
			6: Uint32Field(AttributeMe_UpperLimit, UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read), false, false, false, 6),
			7: Uint32Field(AttributeMe_BitField, UnsignedIntegerAttributeType, 0x0200, 0, mapset.NewSetWith(Read), false, false, false, 7),
			8: TableField(AttributeMe_CodePointsTable, TableAttributeType, 0x0100, TableInfo{nil, 2}, mapset.NewSetWith(Read), false, false, false, 8),
			9: ByteField(AttributeMe_Support, UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read), false, false, false, 9),
		},
		Access:  CreatedByOnu,
		Support: UnknownSupport,
	}
}

// NewAttributeMe (class ID 289) creates the basic
// Managed Entity definition that is used to validate an ME of this type that
// is received from or transmitted to the OMCC.
func NewAttributeMe(params ...ParamData) (*ManagedEntity, OmciErrors) {
	return NewManagedEntity(*attributemeBME, params...)
}
