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

// NetworkDialPlanTableClassID is the 16-bit ID for the OMCI
// Managed entity Network dial plan table
const NetworkDialPlanTableClassID = ClassID(145) // 0x0091

var networkdialplantableBME *ManagedEntityDefinition

// NetworkDialPlanTable (Class ID: #145 / 0x0091)
//	The network dial plan table ME is optional for ONUs providing VoIP services. This ME is used to
//	provision dial plans from the OLT. Instances of this ME are created and deleted by the OLT. If a
//	non-OMCI interface is used to manage SIP for VoIP, this ME is unnecessary.
//
//	Relationships
//		An instance of this ME may be associated with one or more instances of the SIP user data ME.
//
//	Attributes
//		Managed Entity Id
//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
//			(2-bytes)
//
//		Dial Plan Number
//			This attribute indicates the current number of dial plans in the dial plan table. (R)
//			(mandatory) (2-bytes)
//
//		Dial Plan Table Max Size
//			This attribute defines the maximum number of dial plans that can be stored in the dial plan
//			table. (R, setbycreate) (mandatory) (2-bytes)
//
//		Critical Dial Timeout
//			This attribute defines the critical dial timeout for digit map processing, in milliseconds. The
//			recommended default value is 4000-ms. (R,-W, setbycreate) (mandatory) (2-bytes)
//
//		Partial Dial Timeout
//			This attribute defines the partial dial timeout for digit map processing, in milliseconds. The
//			recommended default value is 16000-ms. (R,-W, setbycreate) (mandatory) (2-bytes)
//
//		Dial Plan Format
//			This attribute defines the dial plan format standard that is supported in the ONU for VoIP.
//			Valid values include the following.
//
//			0	Not defined
//
//			1	ITU-T H.248 format with a specific plan (table entries define the dialling plan)
//
//			2	NCS format [b-PKT-SP-NCS ]
//
//			3	Vendor-specific format
//
//			(R,-W, setbycreate) (mandatory) (1-byte)
//
//		Dial Plan Table
//			The table is the digit map that describes the dial plans used by the VoIP service, along with
//			fields to manage the table. An example digit map is the string,
//
//			(0T|00T|[1-7]xxx|8xxxxxxx|#xxxxxxx|*xx|91xxxxxxxxxx|9011x.T)
//
//			Each row of the table comprises the following fields:
//
//			Dial plan ID: The row number, a unique identifier of a dial plan within the dial plan table
//			(1-byte).
//
//			Action: Remove (0) or add (1) this plan (set action). When a dial plan is being removed, the
//			dial plan token field is not used. (1-byte).
//
//			Dial plan token: The definition of the dial plan itself. In the previous example, tokens include
//			the strings "0T" and "*xx". Unused trailing bytes may be padded with nulls or ASCII spaces.
//			(28-bytes)
//
//			NOTE - Due to previously ambiguous documentation, implementations may vary. For
//			interoperability, the OLT should write table entries as documented above, while it is encouraged
//			for the ONU to accept any characters outside the formal grammar as delimiters and to accept the
//			concatenation of rows as a single string that defines a digit map.
//
//			(R,-W) (mandatory) (30 * N bytes, where N is the number of dial plans)
//
type NetworkDialPlanTable struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

// Attribute name constants

const NetworkDialPlanTable_DialPlanNumber = "DialPlanNumber"
const NetworkDialPlanTable_DialPlanTableMaxSize = "DialPlanTableMaxSize"
const NetworkDialPlanTable_CriticalDialTimeout = "CriticalDialTimeout"
const NetworkDialPlanTable_PartialDialTimeout = "PartialDialTimeout"
const NetworkDialPlanTable_DialPlanFormat = "DialPlanFormat"
const NetworkDialPlanTable_DialPlanTable = "DialPlanTable"

func init() {
	networkdialplantableBME = &ManagedEntityDefinition{
		Name:    "NetworkDialPlanTable",
		ClassID: NetworkDialPlanTableClassID,
		MessageTypes: mapset.NewSetWith(
			Create,
			Delete,
			Get,
			GetNext,
			Set,
			SetTable,
		),
		AllowedAttributeMask: 0xfc00,
		AttributeDefinitions: AttributeDefinitionMap{
			0: Uint16Field(ManagedEntityID, PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
			1: Uint16Field(NetworkDialPlanTable_DialPlanNumber, UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read), false, false, false, 1),
			2: Uint16Field(NetworkDialPlanTable_DialPlanTableMaxSize, UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 2),
			3: Uint16Field(NetworkDialPlanTable_CriticalDialTimeout, UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
			4: Uint16Field(NetworkDialPlanTable_PartialDialTimeout, UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 4),
			5: ByteField(NetworkDialPlanTable_DialPlanFormat, UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 5),
			6: TableField(NetworkDialPlanTable_DialPlanTable, TableAttributeType, 0x0400, TableInfo{nil, 30}, mapset.NewSetWith(Read, Write), false, false, false, 6),
		},
		Access:  CreatedByOlt,
		Support: UnknownSupport,
	}
}

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