/* file: product_relationship.swift 	 generated: Mon Jan  3 16:32:52 2022 */

/* This file was generated by the EXPRESS to Swift translator "exp2swift", 
    derived from STEPcode (formerly NIST's SCL).
 exp2swift version: v.1.0.1, derived from stepcode v0.8 as of 2019/11/23 
 WARNING: You probably don't want to edit it since your modifications 
    will be lost if exp2swift is used to regenerate it.
 */

 
import SwiftSDAIcore

extension AP242_MANAGED_MODEL_BASED_3D_ENGINEERING_MIM_LF {
//MARK: -ENTITY DEFINITION in EXPRESS
/*

  ENTITY product_relationship;
      id                : identifier;
      name              : label;
      description       : OPTIONAL text;
      relating_product  : product;
      related_product   : product;
  END_ENTITY; -- product_relationship (line:26425 file:ap242ed2_mim_lf_v1.101.TY.exp)

*/


//MARK: - ALL DEFINED ATTRIBUTES
/*
  ENTITY(SELF)	product_relationship
    ATTR:  id,	TYPE: identifier -- EXPLICIT

    ATTR:  name,	TYPE: label -- EXPLICIT

    ATTR:  description,	TYPE: OPTIONAL text -- EXPLICIT

    ATTR:  relating_product,	TYPE: product -- EXPLICIT
      -- possibly overriden by
          ENTITY: message_relationship,	TYPE: structured_message
          ENTITY: collection_relationship,	TYPE: collection

    ATTR:  related_product,	TYPE: product -- EXPLICIT
      -- possibly overriden by
          ENTITY: message_relationship,	TYPE: structured_message
          ENTITY: collection_relationship,	TYPE: collection


  SUB- ENTITY(2)	envelope_relationship
    (no local attributes)

  SUB- ENTITY(3)	message_relationship
    REDCR: relating_product,	TYPE: structured_message -- EXPLICIT
      -- OVERRIDING ENTITY: product_relationship

    REDCR: related_product,	TYPE: structured_message -- EXPLICIT
      -- OVERRIDING ENTITY: product_relationship

    ATTR:  related_message,	TYPE: structured_message -- DERIVED
      := SELF\product_relationship.related_product

    ATTR:  relating_message,	TYPE: structured_message -- DERIVED
      := SELF\product_relationship.relating_product


  SUB- ENTITY(4)	product_design_to_individual
    ATTR:  individual_product,	TYPE: product -- DERIVED
      := SELF\product_relationship.related_product

    ATTR:  product_design,	TYPE: product -- DERIVED
      := SELF\product_relationship.relating_product


  SUB- ENTITY(5)	collection_relationship
    REDCR: relating_product,	TYPE: collection -- EXPLICIT
      -- OVERRIDING ENTITY: product_relationship

    REDCR: related_product,	TYPE: collection -- EXPLICIT
      -- OVERRIDING ENTITY: product_relationship

    ATTR:  related_collection,	TYPE: collection -- DERIVED
      := SELF\product_relationship.related_product

    ATTR:  relating_collection,	TYPE: collection -- DERIVED
      := SELF\product_relationship.relating_product


*/


//MARK: - Partial Entity
  public final class _product_relationship : SDAI.PartialEntity {
    public override class var entityReferenceType: SDAI.EntityReference.Type {
      ePRODUCT_RELATIONSHIP.self
    }

    //ATTRIBUTES
    /// EXPLICIT ATTRIBUTE 
    public internal(set) var _id: tIDENTIFIER // PLAIN EXPLICIT ATTRIBUTE

    /// EXPLICIT ATTRIBUTE 
    public internal(set) var _name: tLABEL // PLAIN EXPLICIT ATTRIBUTE

    /// EXPLICIT ATTRIBUTE 
    public internal(set) var _description: tTEXT?  // PLAIN EXPLICIT ATTRIBUTE

    /// EXPLICIT ATTRIBUTE 
    public internal(set) var _relating_product: ePRODUCT // PLAIN EXPLICIT ATTRIBUTE

    /// EXPLICIT ATTRIBUTE 
    public internal(set) var _related_product: ePRODUCT // PLAIN EXPLICIT ATTRIBUTE

    public override var typeMembers: Set<SDAI.STRING> {
      var members = Set<SDAI.STRING>()
      members.insert(SDAI.STRING(Self.typeName))
      //SELECT data types (indirectly) referencing the current type as a member of the select list
      members.insert(SDAI.STRING(sCLASSIFICATION_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sACTION_ITEMS.typeName)) // -> sCLASSIFICATION_ITEM
      members.insert(SDAI.STRING(sCHANGE_MANAGEMENT_OBJECT.typeName)) // -> sACTION_ITEMS
      members.insert(SDAI.STRING(sIR_USAGE_ITEM.typeName)) // -> sCLASSIFICATION_ITEM
      members.insert(SDAI.STRING(sMULTI_LANGUAGE_ATTRIBUTE_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sIDENTIFICATION_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sEVIDENCE_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sSECURITY_CLASSIFICATION_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sANALYSED_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sAPPROVAL_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sGENERAL_ORGANIZATIONAL_DATA_SELECT.typeName)) // -> Self
      members.insert(SDAI.STRING(sEVENT_OCCURRENCE_ITEM.typeName)) // -> sGENERAL_ORGANIZATIONAL_DATA_SELECT
      members.insert(SDAI.STRING(sDESCRIPTION_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sDOCUMENT_REFERENCE_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sGROUPABLE_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sCERTIFICATION_ITEM.typeName)) // -> Self
      members.insert(SDAI.STRING(sEFFECTIVITY_ITEM.typeName)) // -> Self
      return members
    }


    //VALUE COMPARISON SUPPORT
    public override func hashAsValue(into hasher: inout Hasher, visited complexEntities: inout Set<SDAI.ComplexEntity>) {
      super.hashAsValue(into: &hasher, visited: &complexEntities)
      self._id.value.hashAsValue(into: &hasher, visited: &complexEntities)
      self._name.value.hashAsValue(into: &hasher, visited: &complexEntities)
      self._description?.value.hashAsValue(into: &hasher, visited: &complexEntities)
      self._relating_product.value.hashAsValue(into: &hasher, visited: &complexEntities)
      self._related_product.value.hashAsValue(into: &hasher, visited: &complexEntities)
    }

    public override func isValueEqual(to rhs: SDAI.PartialEntity, visited comppairs: inout Set<SDAI.ComplexPair>) -> Bool {
      guard let rhs = rhs as? Self else { return false }
      if !super.isValueEqual(to: rhs, visited: &comppairs) { return false }
      if let comp = self._id.value.isValueEqualOptionally(to: rhs._id.value, visited: &comppairs)	{
        if !comp { return false }
      }
      else { return false }
      if let comp = self._name.value.isValueEqualOptionally(to: rhs._name.value, visited: &comppairs)	{
        if !comp { return false }
      }
      else { return false }
      if let comp = self._description?.value.isValueEqualOptionally(to: rhs._description?.value, visited: &comppairs)	{
        if !comp { return false }
      }
      else { return false }
      if let comp = self._relating_product.value.isValueEqualOptionally(to: rhs._relating_product.value, visited: &comppairs)	{
        if !comp { return false }
      }
      else { return false }
      if let comp = self._related_product.value.isValueEqualOptionally(to: rhs._related_product.value, visited: &comppairs)	{
        if !comp { return false }
      }
      else { return false }
      return true
    }

    public override func isValueEqualOptionally(to rhs: SDAI.PartialEntity, visited comppairs: inout Set<SDAI.ComplexPair>) -> Bool? {
      guard let rhs = rhs as? Self else { return false }
      var result: Bool? = true
      if let comp = super.isValueEqualOptionally(to: rhs, visited: &comppairs) {
        if !comp { return false }
      }
      else { result = nil }
      if let comp = self._id.value.isValueEqualOptionally(to: rhs._id.value, visited: &comppairs) {
        if !comp { return false }
      }
      else { result = nil }
      if let comp = self._name.value.isValueEqualOptionally(to: rhs._name.value, visited: &comppairs) {
        if !comp { return false }
      }
      else { result = nil }
      if let comp = self._description?.value.isValueEqualOptionally(to: rhs._description?.value, visited: &comppairs) {
        if !comp { return false }
      }
      else { result = nil }
      if let comp = self._relating_product.value.isValueEqualOptionally(to: rhs._relating_product.value, visited: &comppairs) {
        if !comp { return false }
      }
      else { result = nil }
      if let comp = self._related_product.value.isValueEqualOptionally(to: rhs._related_product.value, visited: &comppairs) {
        if !comp { return false }
      }
      else { result = nil }
      return result
    }


    //EXPRESS IMPLICIT PARTIAL ENTITY CONSTRUCTOR
    public init(ID: tIDENTIFIER, NAME: tLABEL, DESCRIPTION: tTEXT? , RELATING_PRODUCT: ePRODUCT, 
                RELATED_PRODUCT: ePRODUCT) {
      self._id = ID
      self._name = NAME
      self._description = DESCRIPTION
      self._relating_product = RELATING_PRODUCT
      self._related_product = RELATED_PRODUCT
      super.init(asAbstructSuperclass:())

    }

    //p21 PARTIAL ENTITY CONSTRUCTOR
    public required convenience init?(parameters: [P21Decode.ExchangeStructure.Parameter], exchangeStructure: P21Decode.ExchangeStructure) {
      let numParams = 5
      guard parameters.count == numParams
      else { exchangeStructure.error = "number of p21 parameters(\(parameters.count)) are different from expected(\(numParams)) for entity(\(Self.entityName)) constructor"; return nil }

      guard case .success(let p0) = exchangeStructure.recoverRequiredParameter(as: tIDENTIFIER.self, from: parameters[0])
      else { exchangeStructure.add(errorContext: "while recovering parameter #0 for entity(\(Self.entityName)) constructor"); return nil }

      guard case .success(let p1) = exchangeStructure.recoverRequiredParameter(as: tLABEL.self, from: parameters[1])
      else { exchangeStructure.add(errorContext: "while recovering parameter #1 for entity(\(Self.entityName)) constructor"); return nil }

      guard case .success(let p2) = exchangeStructure.recoverOptionalParameter(as: tTEXT.self, from: parameters[2])
      else { exchangeStructure.add(errorContext: "while recovering parameter #2 for entity(\(Self.entityName)) constructor"); return nil }

      guard case .success(let p3) = exchangeStructure.recoverRequiredParameter(as: ePRODUCT.self, from: parameters[3])
      else { exchangeStructure.add(errorContext: "while recovering parameter #3 for entity(\(Self.entityName)) constructor"); return nil }

      guard case .success(let p4) = exchangeStructure.recoverRequiredParameter(as: ePRODUCT.self, from: parameters[4])
      else { exchangeStructure.add(errorContext: "while recovering parameter #4 for entity(\(Self.entityName)) constructor"); return nil }

      self.init( ID: p0, NAME: p1, DESCRIPTION: p2, RELATING_PRODUCT: p3, RELATED_PRODUCT: p4 )
    }
  }


//MARK: - Entity Reference

/** ENTITY reference
- EXPRESS:
```express
  ENTITY product_relationship;
      id                : identifier;
      name              : label;
      description       : OPTIONAL text;
      relating_product  : product;
      related_product   : product;
  END_ENTITY; -- product_relationship (line:26425 file:ap242ed2_mim_lf_v1.101.TY.exp)

```
*/
  public final class ePRODUCT_RELATIONSHIP : SDAI.EntityReference {

    //MARK: PARTIAL ENTITY
    public override class var partialEntityType: SDAI.PartialEntity.Type {
      _product_relationship.self
    }
    public let partialEntity: _product_relationship

    //MARK: SUPERTYPES
    public var super_ePRODUCT_RELATIONSHIP: ePRODUCT_RELATIONSHIP { return self } 	// [1]

    //MARK: SUBTYPES
    public var sub_eENVELOPE_RELATIONSHIP: eENVELOPE_RELATIONSHIP? {	// [2]
      return self.complexEntity.entityReference(eENVELOPE_RELATIONSHIP.self)
    }

    public var sub_eMESSAGE_RELATIONSHIP: eMESSAGE_RELATIONSHIP? {	// [3]
      return self.complexEntity.entityReference(eMESSAGE_RELATIONSHIP.self)
    }

    public var sub_ePRODUCT_DESIGN_TO_INDIVIDUAL: ePRODUCT_DESIGN_TO_INDIVIDUAL? {	// [4]
      return self.complexEntity.entityReference(ePRODUCT_DESIGN_TO_INDIVIDUAL.self)
    }

    public var sub_eCOLLECTION_RELATIONSHIP: eCOLLECTION_RELATIONSHIP? {	// [5]
      return self.complexEntity.entityReference(eCOLLECTION_RELATIONSHIP.self)
    }


    //MARK: ATTRIBUTES
    /// __EXPLICIT__ attribute
    /// - origin: SELF( ``ePRODUCT_RELATIONSHIP`` )
    public var DESCRIPTION: tTEXT?  {
      get {
        return self.partialEntity._description
      }
      set(newValue) {
        let partial = self.partialEntity
        partial._description = newValue
      }
    }

    /// __DERIVE__ attribute
    /// - origin: SUB( ``eMESSAGE_RELATIONSHIP`` )
    public var RELATED_MESSAGE: eSTRUCTURED_MESSAGE?  {
      get {
        if let cached = cachedValue(derivedAttributeName:"RELATED_MESSAGE") {
          return cached.value as! eSTRUCTURED_MESSAGE? 
        }
        guard let origin = sub_eMESSAGE_RELATIONSHIP else { return nil }
        let value = eSTRUCTURED_MESSAGE(origin.partialEntity._related_message__getter(SELF: origin))
        updateCache(derivedAttributeName:"RELATED_MESSAGE", value:value)
        return value
      }
    }

    /// __DERIVE__ attribute
    /// - origin: SUB( ``eCOLLECTION_RELATIONSHIP`` )
    public var RELATED_COLLECTION: eCOLLECTION?  {
      get {
        if let cached = cachedValue(derivedAttributeName:"RELATED_COLLECTION") {
          return cached.value as! eCOLLECTION? 
        }
        guard let origin = sub_eCOLLECTION_RELATIONSHIP else { return nil }
        let value = eCOLLECTION(origin.partialEntity._related_collection__getter(SELF: origin))
        updateCache(derivedAttributeName:"RELATED_COLLECTION", value:value)
        return value
      }
    }

    /// __DERIVE__ attribute
    /// - origin: SUB( ``ePRODUCT_DESIGN_TO_INDIVIDUAL`` )
    public var INDIVIDUAL_PRODUCT: ePRODUCT?  {
      get {
        if let cached = cachedValue(derivedAttributeName:"INDIVIDUAL_PRODUCT") {
          return cached.value as! ePRODUCT? 
        }
        guard let origin = sub_ePRODUCT_DESIGN_TO_INDIVIDUAL else { return nil }
        let value = ePRODUCT(origin.partialEntity._individual_product__getter(SELF: origin))
        updateCache(derivedAttributeName:"INDIVIDUAL_PRODUCT", value:value)
        return value
      }
    }

    /// __EXPLICIT__ attribute
    /// - origin: SELF( ``ePRODUCT_RELATIONSHIP`` )
    public var RELATED_PRODUCT: ePRODUCT {
      get {
        return SDAI.UNWRAP( self.partialEntity._related_product )
      }
      set(newValue) {
        let partial = self.partialEntity
        partial._related_product = SDAI.UNWRAP(newValue)
      }
    }

    /// __DERIVE__ attribute
    /// - origin: SUB( ``eCOLLECTION_RELATIONSHIP`` )
    public var RELATING_COLLECTION: eCOLLECTION?  {
      get {
        if let cached = cachedValue(derivedAttributeName:"RELATING_COLLECTION") {
          return cached.value as! eCOLLECTION? 
        }
        guard let origin = sub_eCOLLECTION_RELATIONSHIP else { return nil }
        let value = eCOLLECTION(origin.partialEntity._relating_collection__getter(SELF: origin))
        updateCache(derivedAttributeName:"RELATING_COLLECTION", value:value)
        return value
      }
    }

    /// __EXPLICIT__ attribute
    /// - origin: SELF( ``ePRODUCT_RELATIONSHIP`` )
    public var ID: tIDENTIFIER {
      get {
        return SDAI.UNWRAP( self.partialEntity._id )
      }
      set(newValue) {
        let partial = self.partialEntity
        partial._id = SDAI.UNWRAP(newValue)
      }
    }

    /// __DERIVE__ attribute
    /// - origin: SUB( ``eMESSAGE_RELATIONSHIP`` )
    public var RELATING_MESSAGE: eSTRUCTURED_MESSAGE?  {
      get {
        if let cached = cachedValue(derivedAttributeName:"RELATING_MESSAGE") {
          return cached.value as! eSTRUCTURED_MESSAGE? 
        }
        guard let origin = sub_eMESSAGE_RELATIONSHIP else { return nil }
        let value = eSTRUCTURED_MESSAGE(origin.partialEntity._relating_message__getter(SELF: origin))
        updateCache(derivedAttributeName:"RELATING_MESSAGE", value:value)
        return value
      }
    }

    /// __EXPLICIT__ attribute
    /// - origin: SELF( ``ePRODUCT_RELATIONSHIP`` )
    public var RELATING_PRODUCT: ePRODUCT {
      get {
        return SDAI.UNWRAP( self.partialEntity._relating_product )
      }
      set(newValue) {
        let partial = self.partialEntity
        partial._relating_product = SDAI.UNWRAP(newValue)
      }
    }

    /// __EXPLICIT__ attribute
    /// - origin: SELF( ``ePRODUCT_RELATIONSHIP`` )
    public var NAME: tLABEL {
      get {
        return SDAI.UNWRAP( self.partialEntity._name )
      }
      set(newValue) {
        let partial = self.partialEntity
        partial._name = SDAI.UNWRAP(newValue)
      }
    }

    /// __DERIVE__ attribute
    /// - origin: SUB( ``ePRODUCT_DESIGN_TO_INDIVIDUAL`` )
    public var PRODUCT_DESIGN: ePRODUCT?  {
      get {
        if let cached = cachedValue(derivedAttributeName:"PRODUCT_DESIGN") {
          return cached.value as! ePRODUCT? 
        }
        guard let origin = sub_ePRODUCT_DESIGN_TO_INDIVIDUAL else { return nil }
        let value = ePRODUCT(origin.partialEntity._product_design__getter(SELF: origin))
        updateCache(derivedAttributeName:"PRODUCT_DESIGN", value:value)
        return value
      }
    }


    //MARK: INITIALIZERS
    public convenience init?(_ entityRef: SDAI.EntityReference?) {
      let complex = entityRef?.complexEntity
      self.init(complex: complex)
    }

    public required init?(complex complexEntity: SDAI.ComplexEntity?) {
      guard let partial = complexEntity?.partialEntityInstance(_product_relationship.self) else { return nil }
      self.partialEntity = partial

      super.init(complex: complexEntity)
    }

    public required convenience init?<G: SDAIGenericType>(fromGeneric generic: G?) {
      guard let entityRef = generic?.entityReference else { return nil }
      self.init(complex: entityRef.complexEntity)
    }

    public convenience init?<S: SDAISelectType>(_ select: S?) { self.init(possiblyFrom: select) }
    public convenience init?(_ complex: SDAI.ComplexEntity?) { self.init(complex: complex) }

    //SIMPLE ENTITY REFERENCE
    public convenience init?(_ partial:_product_relationship) {
      let complex = SDAI.ComplexEntity(entities:[partial])
      self.init(complex: complex)
    }


    //MARK: DICTIONARY DEFINITION
    public class override var entityDefinition: SDAIDictionarySchema.EntityDefinition { _entityDefinition }
    private static let _entityDefinition: SDAIDictionarySchema.EntityDefinition = createEntityDefinition()

    private static func createEntityDefinition() -> SDAIDictionarySchema.EntityDefinition {
      let entityDef = SDAIDictionarySchema.EntityDefinition(name: "PRODUCT_RELATIONSHIP", type: self, explicitAttributeCount: 5)

      //MARK: SUPERTYPE REGISTRATIONS
      entityDef.add(supertype: ePRODUCT_RELATIONSHIP.self)

      //MARK: ATTRIBUTE REGISTRATIONS
      entityDef.addAttribute(name: "DESCRIPTION", keyPath: \ePRODUCT_RELATIONSHIP.DESCRIPTION, 
        kind: .explicitOptional, source: .thisEntity, mayYieldEntityReference: false)
      entityDef.addAttribute(name: "RELATED_MESSAGE", keyPath: \ePRODUCT_RELATIONSHIP.RELATED_MESSAGE, 
        kind: .derived, source: .subEntity, mayYieldEntityReference: true)
      entityDef.addAttribute(name: "RELATED_COLLECTION", keyPath: \ePRODUCT_RELATIONSHIP.RELATED_COLLECTION, 
        kind: .derived, source: .subEntity, mayYieldEntityReference: true)
      entityDef.addAttribute(name: "INDIVIDUAL_PRODUCT", keyPath: \ePRODUCT_RELATIONSHIP.INDIVIDUAL_PRODUCT, 
        kind: .derived, source: .subEntity, mayYieldEntityReference: true)
      entityDef.addAttribute(name: "RELATED_PRODUCT", keyPath: \ePRODUCT_RELATIONSHIP.RELATED_PRODUCT, 
        kind: .explicit, source: .thisEntity, mayYieldEntityReference: true)
      entityDef.addAttribute(name: "RELATING_COLLECTION", keyPath: \ePRODUCT_RELATIONSHIP.RELATING_COLLECTION, 
        kind: .derived, source: .subEntity, mayYieldEntityReference: true)
      entityDef.addAttribute(name: "ID", keyPath: \ePRODUCT_RELATIONSHIP.ID, 
        kind: .explicit, source: .thisEntity, mayYieldEntityReference: false)
      entityDef.addAttribute(name: "RELATING_MESSAGE", keyPath: \ePRODUCT_RELATIONSHIP.RELATING_MESSAGE, 
        kind: .derived, source: .subEntity, mayYieldEntityReference: true)
      entityDef.addAttribute(name: "RELATING_PRODUCT", keyPath: \ePRODUCT_RELATIONSHIP.RELATING_PRODUCT, 
        kind: .explicit, source: .thisEntity, mayYieldEntityReference: true)
      entityDef.addAttribute(name: "NAME", keyPath: \ePRODUCT_RELATIONSHIP.NAME, 
        kind: .explicit, source: .thisEntity, mayYieldEntityReference: false)
      entityDef.addAttribute(name: "PRODUCT_DESIGN", keyPath: \ePRODUCT_RELATIONSHIP.PRODUCT_DESIGN, 
        kind: .derived, source: .subEntity, mayYieldEntityReference: true)

      return entityDef
    }

  }
}
