/*
 * 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"

// VlanTaggingFilterDataClassID is the 16-bit ID for the OMCI
// Managed entity VLAN tagging filter data
const VlanTaggingFilterDataClassID = ClassID(84) // 0x0054

var vlantaggingfilterdataBME *ManagedEntityDefinition

// VlanTaggingFilterData (Class ID: #84 / 0x0054)
//	This ME organizes data associated with VLAN tagging. Instances of this ME are created and
//	deleted by the OLT.
//
//	Relationships
//		An instance of this ME is associated with an instance of a MAC bridge port configuration data
//		ME. By definition, tag filtering occurs closer to the MAC bridge than the tagging operation.
//		Schematically, the ordering of the functions is as given in Figure 9.3.11-1:////		Figure 9.3.11-1
//
//	Attributes
//		Managed Entity Id
//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
//			implicitly linked to an instance of the MAC bridge port configuration data ME. (R, setbycreate)
//			(mandatory) (2-bytes)
//
//		Vlan Filter List
//			This attribute is a list of provisioned tag control information (TCI) values for the bridge
//			port. A TCI, comprising user priority, canonical format indicator (CFI) and virtual local area
//			network identifier (VID), is represented by 2-bytes. This attribute supports up to 12 VLAN
//			entries. The first N are valid, where N is given by the number of entries attribute. (R,-W,
//			setbycreate) (mandatory) (24-bytes)
//
//		Forward Operation
//			When a frame passes through the MAC bridge port, it is processed according to the operation
//			specified by this attribute, in accordance with Table-9.3.111. Figure 9.3.11-3 illustrates the
//			treatment of frames according to the provisioned action possibilities. Tagged and untagged
//			frames are treated separately, but both in accordance with Figure 9.3.11-3. While all forwarding
//			operations are plausible, only actions 0x10 and 0x12 are necessary to construct a VLAN mapper
//			and an 802.1p mapper, respectively. (R,-W, setbycreate) (mandatory) (1-byte)
//
//			Table 9.3.11-1 contains duplicate entries due to simplification of the original set of actions.
//
//			Table 9.3.11-1 and the actions listed are discussed in detail in the following.
//
//		Number Of Entries
//			This attribute specifies the number of valid entries in the VLAN filter list. (R,-W,
//			setbycreate) (mandatory) (1-byte)
//
type VlanTaggingFilterData struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

func init() {
	vlantaggingfilterdataBME = &ManagedEntityDefinition{
		Name:    "VlanTaggingFilterData",
		ClassID: 84,
		MessageTypes: mapset.NewSetWith(
			Create,
			Delete,
			Get,
			Set,
		),
		AllowedAttributeMask: 0xe000,
		AttributeDefinitions: AttributeDefinitionMap{
			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
			1: MultiByteField("VlanFilterList", OctetsAttributeType, 0x8000, 24, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
			2: ByteField("ForwardOperation", EnumerationAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
			3: ByteField("NumberOfEntries", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
		},
		Access:  CreatedByOlt,
		Support: UnknownSupport,
	}
}

// NewVlanTaggingFilterData (class ID 84) 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 NewVlanTaggingFilterData(params ...ParamData) (*ManagedEntity, OmciErrors) {
	return NewManagedEntity(*vlantaggingfilterdataBME, params...)
}
