
Option Strict Off
Imports System
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Assemblies
Imports System.IO
Imports System.Xml
Imports System.Data

Module NXJournal

    Public Property NxSyslog As LogFile = Nothing
    Public Property lw As ListingWindow = Nothing
    Private Property SQL_ItemIdByItemPUID_DPNE As String = ""
    Private Property cmd As System.Data.Common.DbCommand = Nothing
    Private Property JobTemp_DP As String

    ' Private Const DB_PART_NO As String = "DB_PART_NO"
    Private Const DB_PART_REV As String = "DB_PART_REV"

    Sub Main(ByVal args() As String)

        Dim UFSession As UFSession = UFSession.GetUFSession()
        Dim NXSession As NXOpen.Session = NXOpen.Session.GetSession()
        NxSyslog = NXSession.LogFile
        lw = Nothing

        Dim Accept As NXOpen.Update.FailureOption = 5
        NXSession.UpdateManager.SetDefaultUpdateFailureAction(Accept)

        JobTemp_DP = System.Environment.GetEnvironmentVariable("JobTemp_DP")
        Dim inputFile_DPNE As String = System.Environment.GetEnvironmentVariable("NXRefferencesGet_InputFile_DPNE")
        SQL_ItemIdByItemPUID_DPNE = System.Environment.GetEnvironmentVariable("SQL_ItemIdByItemPUID_DPNE")

        Dim processPartFamily As Boolean = True
        'Boolean.TryParse(System.Environment.GetEnvironmentVariable("ProcessPartFamily"), processPartFamily)
        Dim processSubAssemby As Boolean = True
        'Boolean.TryParse(System.Environment.GetEnvironmentVariable("ProcessSubAssemby"), processSubAssemby)


        ' ###############################################
        ' ### Only for Testing ###
        'JobTemp_DP = "C:\Users\ideasadm\Desktop\NXReffTest\JobTemp"
        'inputFile_DPNE = "C:\Users\ideasadm\Desktop\NXReffTest\NXRefferencesGet_InputFile.txt"
        'exportRoot_DP = "J:\Mawera-Carve-Out\Examples\PLMP"
        'lw = NXSession.ListingWindow
        'ReplaceTCComponents = True
        'System.Environment.SetEnvironmentVariable("UGII_LOAD_OPTIONS", "D:\JobMgrL_T\JobClient\PLMS_ARASV_CSV3_Gen_M_00009_IMA\startup\NXNativ_load_options_loadallcomponentsandwave.def")
        ' ###############################################

        NxSyslog.WriteLine("##NXReffsGet: SQL_ItemIdByItemPUID_DPNE: " + SQL_ItemIdByItemPUID_DPNE.ToString)

        If IO.File.Exists(inputFile_DPNE) Then

            Try
                Dim inputFileLines As String() = IO.File.ReadAllLines(inputFile_DPNE)

                For Each line As String In inputFileLines

                    If line.Contains("|") Then
                        Dim objectCliNameForFileSys As String = line.Split("|"c)(0)
                        Dim NXPartFile_DPNE As String = line.Split("|"c)(1)
                        Dim NXReffXMLFile_DPNE As String = IO.Path.Combine(JobTemp_DP, objectCliNameForFileSys + ".xml")

                        NxSyslog.WriteLine("")
                        NxSyslog.WriteLine("##NXReffsGet:")
                        NxSyslog.WriteLine("##NXReffsGet: STARTs NX Refference extract for" + objectCliNameForFileSys)
                        NxSyslog.WriteLine("##NXReffsGet: NXPartFile_DPNE: " + NXPartFile_DPNE)
                        NxSyslog.WriteLine("##NXReffsGet: NXReffXMLFile_DPNE: " + NXReffXMLFile_DPNE)

                        ' get NX Refferences for each object
                        Call NXRefferencesGet(UFSession, NXSession, NxSyslog, NXPartFile_DPNE, NXReffXMLFile_DPNE, processSubAssemby, processPartFamily, lw)

                        NxSyslog.WriteLine("##NXReffsGet: END NX Refference extract for" + objectCliNameForFileSys)

                    End If

                Next

            Catch ex As Exception
                NxSyslog.WriteLine("##NXReffsGet: EX in Method Main: " + ex.ToString())
            End Try

        End If

    End Sub

    ''' <summary>
    ''' function to get Nx Refferences and write it into an XML File
    ''' </summary>
    ''' <remarks>
    ''' #New: 3.1503;08.04.2021;S.Gueth
    ''' </remarks>
    Private Sub NXRefferencesGet(UFSession_p As UFSession,
                                 NXSession_p As NXOpen.Session,
                                 NxSyslog_p As LogFile,
                                 NXPart_DPNE_p As String,
                                 NXReffXMLFile_DPNE As String,
                                 processSubAssemby_p As Boolean,
                                 processPartFamily_p As Boolean,
                                 Optional lw_p As ListingWindow = Nothing)

        Dim executionOK As Boolean = True

        Dim basePart As NXOpen.Part = Nothing
        Dim partCloseResponses1 As NXOpen.PartCloseResponses = Nothing

        Try

            'Dim lw As ListingWindow = theSession.ListingWindow
            If lw_p IsNot Nothing Then lw_p.Open()

            Dim NXRefferences_Obj As NXRefferences_cls = New NXRefferences_cls

            Dim partLoadStatus1 As NXOpen.PartLoadStatus = Nothing
            basePart = NXSession_p.Parts.OpenDisplay(NXPart_DPNE_p, partLoadStatus1)
            If basePart Is Nothing Then
                If lw_p IsNot Nothing Then lw_p.WriteLine("ERROR on loading part " + NXPart_DPNE_p)
                NxSyslog_p.WriteLine("##NXReffsGet: ERROR on loading part " + NXPart_DPNE_p)
                executionOK = False
                'Exit Sub
            End If
            partLoadStatus1.Dispose()

            'basePart = NXSession_p.Parts.Work

            Try

                Dim isPartFamilyInstance As Boolean = False
                Try
                    UFSession_p.Part.IsFamilyInstance(basePart.Tag, isPartFamilyInstance)
                Catch ex As Exception
                    If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                End Try

                Dim isPartFamilyTemplate As Boolean = False
                Try
                    UFSession_p.Part.IsFamilyTemplate(basePart.Tag, isPartFamilyTemplate)
                Catch ex As Exception
                    If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                End Try


                Try
                    NxSyslog_p.WriteLine("##NXReffsGet: is Part Family Member:  " + isPartFamilyInstance.ToString)
                    If isPartFamilyInstance Then
                        Try
                            Dim PFTemplateFilename As String = ""
                            UFSession_p.Part.AskTemplateFilename(basePart.Tag, PFTemplateFilename)
                            If Not String.IsNullOrEmpty(PFTemplateFilename) Then
                                NXRefferences_Obj.PartFamilyTemplate = PFTemplateFilename
                            End If
                        Catch ex As Exception
                        End Try

                    Else

                        Try
                            Dim fileinfo = New IO.FileInfo(NXPart_DPNE_p)
                            If fileinfo.IsReadOnly Then
                                fileinfo.IsReadOnly = False
                            End If
                        Catch ex As Exception
                        End Try
                    End If
                Catch ex As Exception
                    If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                End Try

                Try
                    NxSyslog_p.WriteLine("##NXReffsGet: is Part Family Master:  " + isPartFamilyTemplate.ToString)
                    If isPartFamilyTemplate Then
                        NXRefferences_Obj.isPartFamilyMaster = True
                    End If
                Catch ex As Exception
                    If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                End Try

            Catch ex As Exception
                If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
            End Try

            ' #Step 1: get assembly components
            Try

                If basePart.ComponentAssembly IsNot Nothing Then

                    Dim c As ComponentAssembly = basePart.ComponentAssembly

                    If c Is Nothing Then
                        NxSyslog_p.WriteLine("##NXReffsGet: No Component Assembly")
                        If lw_p IsNot Nothing Then lw_p.WriteLine("No Component Assembly")
                        Exit Try
                    End If
                    If c.RootComponent Is Nothing Then
                        NxSyslog_p.WriteLine("##NXReffsGet: No Component Assembly")
                        If lw_p IsNot Nothing Then lw_p.WriteLine("No Component Assembly")
                        Exit Try
                    End If

                    If lw_p IsNot Nothing Then lw_p.WriteLine("Root Assembly: " + c.RootComponent.DisplayName + " // " + c.RootComponent.OwningPart.FullPath + " // Components count: ")
                    NxSyslog_p.WriteLine("##NXReffsGet: Root Assembly: " + c.RootComponent.DisplayName + " // " + c.RootComponent.OwningPart.FullPath + " // Components count: " + c.RootComponent.GetChildren().Length.ToString)

                    Dim savePart As Boolean = False

                    Call ProcessComponentChilds(c.RootComponent, UFSession_p, NXSession_p, NxSyslog_p, NXRefferences_Obj, processSubAssemby_p, savePart, lw_p)

                    If savePart Then
                        Try
                            Dim partSaveStatus As PartSaveStatus = basePart.Save(NXOpen.BasePart.SaveComponents.False, NXOpen.BasePart.CloseAfterSave.False)
                            partSaveStatus.Dispose()
                            NxSyslog_p.WriteLine("##NXReffsGet: Save part: OK")
                            If lw_p IsNot Nothing Then lw_p.WriteLine("Save part: OK")
                        Catch ex As Exception
                            NxSyslog_p.WriteLine("##NXReffsGet: Save part: ERR " + ex.Message)
                            If lw_p IsNot Nothing Then lw_p.WriteLine("Save part: ERR " + ex.Message)
                        End Try
                    End If

                End If

            Catch ex As Exception
                If lw_p IsNot Nothing Then lw_p.WriteLine("Debug 1: " + ex.ToString)
                NxSyslog_p.WriteLine("##NXReffsGet: Debug 1: " + ex.ToString)
                executionOK = False
            End Try

            ' #Step 2: get wave link refferences
            Try
                If lw_p IsNot Nothing Then lw_p.WriteLine("Feature Count: " + basePart.Features.GetFeatures.Length.ToString)
                NxSyslog_p.WriteLine("##NXReffsGet: Feature Count: " + basePart.Features.GetFeatures.Length.ToString)
                Dim additionalWaveLinks As New List(Of String)
                Dim index As Integer = 0
                For Each theFeature As Features.Feature In basePart.Features

                    index += 1

                    If theFeature Is Nothing Then
                        Continue For
                    End If
                    If theFeature.FeatureType Is Nothing Then
                        Continue For
                    End If
                    If theFeature.Tag = NXOpen.Tag.Null Then
                        Continue For
                    End If

                    Try
                        If theFeature.FeatureType.ToUpper.Contains("LINKED") Then



                            Try
                                Dim file_DPNE As String = IO.Path.Combine(JobTemp_DP, "WaveDetails" + index.ToString + ".txt")
                                If lw_p Is Nothing Then
                                    lw_p = NXSession_p.ListingWindow
                                End If
                                lw_p.Open()
                                lw_p.SelectDevice(ListingWindow.DeviceType.File, file_DPNE)
                                NXSession_p.Information.DisplayObjectsDetails(New NXObject() {DirectCast(theFeature, NXObject)})
                                lw_p.Close()
                                lw_p.SelectDevice(ListingWindow.DeviceType.Window, "")

                                Try
                                    If IO.File.Exists(file_DPNE) Then

                                        For Each line As String In IO.File.ReadAllLines(file_DPNE)
                                            Try
                                                If line.ToUpper.Contains("Position determined by assembly".ToUpper) Then
                                                    Dim refTemp As String = Text.RegularExpressions.Regex.Match(line, ".*Position determined by assembly (.*?) \(.*", Text.RegularExpressions.RegexOptions.IgnoreCase).Groups(1).Value
                                                    If Not additionalWaveLinks.Contains(refTemp) Then
                                                        additionalWaveLinks.Add(refTemp)
                                                    End If
                                                    Exit For
                                                    End If
                                                    If line.ToUpper.Contains("Position durch Baugruppe ermittelt".ToUpper) Then
                                                    Dim refTemp As String = Text.RegularExpressions.Regex.Match(line, ".*Position durch Baugruppe ermittelt (.*?) \(.*", Text.RegularExpressions.RegexOptions.IgnoreCase).Groups(1).Value
                                                    If Not additionalWaveLinks.Contains(refTemp) Then
                                                        additionalWaveLinks.Add(refTemp)
                                                    End If
                                                    Exit For
                                                End If
                                            Catch ex As Exception
                                            End Try
                                        Next

                                        IO.File.Delete(file_DPNE)

                                    End If
                                Catch ex As Exception
                                End Try
                            Catch ex As Exception
                            End Try



                            Dim theSourceEntityTag As NXOpen.Tag = NXOpen.Tag.Null
                            Dim owningSourcePartTag As Tag = NXOpen.Tag.Null
                            Dim allowLoad As Boolean = True
                            Dim owningPartName As String = ""
                            Dim linkedFeatureInfo As UFWave.LinkedFeatureInfo
                            UFSession_p.Wave.AskLinkedFeatureInfo(theFeature.Tag, linkedFeatureInfo)
                            Try
                                UFSession_p.Wave.AskLinkSource(theFeature.Tag, allowLoad, theSourceEntityTag)
                                If theSourceEntityTag <> NXOpen.Tag.Null Then
                                    UFSession_p.Obj.AskOwningPart(theSourceEntityTag, owningSourcePartTag)
                                End If
                                If owningSourcePartTag <> NXOpen.Tag.Null Then
                                    UFSession_p.Part.AskPartName(owningSourcePartTag, owningPartName)
                                End If
                            Catch ex As Exception
                                If lw_p IsNot Nothing Then lw_p.WriteLine("EX on getting Wave Link PartName: " + ex.ToString)
                                owningPartName = linkedFeatureInfo.source_part_name
                            End Try

                            If lw_p IsNot Nothing Then lw_p.WriteLine(linkedFeatureInfo.source_part_name + " // " + linkedFeatureInfo.owning_part_name)

                            If Not String.IsNullOrEmpty(owningPartName) Then
                                NXRefferences_Obj.WaveLinkRefferences.Add(owningPartName)
                                If lw_p IsNot Nothing Then lw_p.WriteLine("WaveLink Source: " + owningPartName)
                                NxSyslog_p.WriteLine("##NXReffsGet: WaveLink Source: " + owningPartName)
                            End If

                        End If
                    Catch ex As Exception
                        If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                        NxSyslog_p.WriteLine("##NXReffsGet: Debug 2: " + ex.ToString)
                        executionOK = False
                    End Try
                Next

                For Each additionalWaveLink As String In additionalWaveLinks
                    NXRefferences_Obj.WaveLinkRefferences.Add(additionalWaveLink)
                Next

            Catch ex As Exception
                If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                NxSyslog_p.WriteLine("##NXReffsGet: Debug 3: " + ex.ToString)
                executionOK = False
            End Try


            ' #Step 3: get interpart link refferences
            Try

                If lw_p IsNot Nothing Then lw_p.WriteLine("Interpart Refs Count: " + basePart.Expressions.GetInterpartReferences.Length.ToString)
                NxSyslog_p.WriteLine("##NXReffsGet: Interpart Refs Count: " + basePart.Expressions.GetInterpartReferences.Length.ToString)

                Dim partNames As String() = Nothing
                Dim partDisplayNames As String() = Nothing
                Dim parts As NXObject() = Nothing
                basePart.Expressions.GetInterpartReferencesFor4gd(partNames, partDisplayNames, parts)

                If parts.Length > 0 Then
                    For i As Integer = 0 To parts.Length - 1
                        Dim fullPath As String = ""
                        Dim nxobj As NXObject = parts(i)
                        If nxobj.OwningPart IsNot Nothing AndAlso Not String.IsNullOrEmpty(nxobj.OwningPart.FullPath) Then
                            fullPath = nxobj.OwningPart.FullPath
                        Else
                            fullPath = partNames(i)
                        End If
                        NXRefferences_Obj.InterPartLinkRefferences.Add(fullPath)
                        If lw_p IsNot Nothing Then lw_p.WriteLine("Interpart Source: " + fullPath)
                        NxSyslog_p.WriteLine("##NXReffsGet: Interpart Source: " + fullPath)
                    Next
                End If

            Catch ex As Exception
                If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                NxSyslog_p.WriteLine("##NXReffsGet: Debug 4: " + ex.ToString)
                executionOK = False
            End Try

            If processPartFamily_p Then


                ' get part family refferences
                Try

                    If lw_p IsNot Nothing Then lw_p.WriteLine("")
                    NxSyslog_p.WriteLine("")

                    Dim familyCount As Integer = 0
                    Dim familyTags As Tag() = Nothing
                    UFSession_p.Part.AskFamilies(basePart.Tag, familyCount, familyTags)

                    If familyTags IsNot Nothing AndAlso familyTags.Length > 0 Then
                        For Each familyTag As Tag In familyTags

                            Dim family_data As UFFam.FamilyData
                            UFSession_p.Fam.AskFamilyData(familyTag, family_data)

                            If lw_p IsNot Nothing Then lw_p.WriteLine("Part Family Name: " + family_data.name)
                            NxSyslog_p.WriteLine("##NXReffsGet: Part Family Name: " + family_data.name)

                            If lw_p IsNot Nothing Then lw_p.WriteLine("Part Family Members: " + family_data.member_count.ToString)
                            NxSyslog_p.WriteLine("##NXReffsGet: Part Family Members: " + family_data.member_count.ToString)

                            If lw_p IsNot Nothing Then lw_p.WriteLine("")
                            NxSyslog_p.WriteLine("")

                            Dim pfmAttrDict As New Dictionary(Of Integer, String)
                            Dim DB_PART_NO_IDX As Integer = -1
                            Dim DB_PART_REV_IDX As Integer = -1

                            If family_data.attribute_count > 0 Then

                                If lw_p IsNot Nothing Then lw_p.WriteFullline("Part Family Attributes: ")
                                NxSyslog_p.WriteLine("##NXReffsGet: Part Family Attributes: ")

                                For i As Integer = 0 To family_data.attribute_count - 1
                                    Dim attribute_data As UFFam.AttributeData
                                    UFSession_p.Fam.AskAttributeData(family_data.attributes(i), attribute_data)
                                    pfmAttrDict.Add(i, attribute_data.name)
                                    If lw_p IsNot Nothing Then lw_p.WriteLine("           " + attribute_data.name + " // " + attribute_data.value)
                                    NxSyslog_p.WriteLine("##NXReffsGet:            " + attribute_data.name + " // " + attribute_data.value)

                                    ' store indexes for the following 4 attributes
                                    If attribute_data.subtype = UFConstants.UF_fam_attr_name_subtype Then
                                        DB_PART_NO_IDX = i
                                    End If
                                    If attribute_data.name.Equals(DB_PART_REV) Then
                                        DB_PART_REV_IDX = i
                                    End If
                                Next

                            End If


                            If family_data.member_count > 0 Then
                                For i As Integer = 0 To family_data.member_count - 1

                                    If lw_p IsNot Nothing Then lw_p.WriteLine("")
                                    NxSyslog_p.WriteLine("")

                                    If lw_p IsNot Nothing Then lw_p.WriteLine("------------------------------------------------")
                                    NxSyslog_p.WriteLine("##NXReffsGet: ------------------------------------------------")

                                    Dim member_data As UFFam.MemberData
                                    UFSession_p.Fam.AskMemberRowData(familyTag, i, member_data)

                                    If lw_p IsNot Nothing Then lw_p.WriteLine("")
                                    NxSyslog_p.WriteLine("")
                                    If lw_p IsNot Nothing Then lw_p.WriteLine("Part Family Member Data:")
                                    NxSyslog_p.WriteLine("##NXReffsGet: Part Family Member Data:")
                                    For j As Integer = 0 To member_data.value_count - 1
                                        If lw_p IsNot Nothing Then lw_p.WriteLine("     " + pfmAttrDict.Item(j) + ": " + member_data.values(j))
                                        NxSyslog_p.WriteLine("##NXReffsGet:      " + pfmAttrDict.Item(j) + ": " + member_data.values(j))
                                    Next

                                    Dim itemIdCurrent As String = ""
                                    Dim revCurrent As String = ""
                                    ' get current member data values
                                    If DB_PART_NO_IDX > -1 Then
                                        itemIdCurrent = member_data.values(DB_PART_NO_IDX)
                                    End If
                                    If DB_PART_REV_IDX > -1 Then
                                        revCurrent = member_data.values(DB_PART_REV_IDX)
                                    End If

                                    Dim PartFamilyRefference_obj As New NXRefferences_cls.PartFamilyRefference_cls
                                    PartFamilyRefference_obj.DBPartName = itemIdCurrent
                                    PartFamilyRefference_obj.DBRevName = revCurrent

                                    NXRefferences_Obj.PartFamilyRefferences.Add(PartFamilyRefference_obj)

                                Next

                            End If


                        Next

                    Else

                        If lw_p IsNot Nothing Then lw_p.WriteLine("Part has no family data!")
                        NxSyslog_p.WriteLine("##NXReffsGet: Part has no family data!")

                    End If

                Catch ex As Exception
                    If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                End Try

            End If

            ' write XML File
            If executionOK Then
                NXRefferences_Obj.WirteXMLFile(NXReffXMLFile_DPNE)
            End If

            partCloseResponses1 = NXSession_p.Parts.NewPartCloseResponses()

        Catch ex As Exception
            NxSyslog_p.WriteLine("##NXReffsGet: EX in Method NXRefferencesGet: " + ex.ToString())
        Finally
            If basePart IsNot Nothing Then
                basePart.Close(NXOpen.BasePart.CloseWholeTree.True, NXOpen.BasePart.CloseModified.UseResponses, partCloseResponses1)
                basePart = Nothing
            End If

            If partCloseResponses1 IsNot Nothing Then
                partCloseResponses1.Dispose()
            End If

        End Try

    End Sub

    ''' <summary>
    ''' function to process compoent children of an asselmby
    ''' </summary>
    ''' <remarks>
    ''' #New: 3.1503;19.05.2021;S.Gueth
    ''' </remarks>
    Private Sub ProcessComponentChilds(component_p As Component,
                                       UFSession_p As UFSession,
                                       NXSession_p As NXOpen.Session,
                                       NxSyslog_p As LogFile,
                                       ByRef NXRefferences_Obj_p As NXRefferences_cls,
                                       processSubAssemby_p As Boolean,
                                       ByRef savePart_p As Boolean,
                                       Optional lw_p As ListingWindow = Nothing)

        ' cycle through all child components
        For Each childComponent As Component In component_p.GetChildren()

            ' get callout
            Dim callout As String = ""
            Dim compRef As New NXRefferences_cls.NXComponentRefference_cls
            Try
                callout = childComponent.GetUserAttributeAsString("Callout", NXObject.AttributeType.Any, 0)
            Catch ex As Exception
            End Try
            compRef.CallOut = callout

            Dim partName As String = ""
            Dim refsetName As String = ""
            Dim instanceName As String = ""
            Dim origin(2) As Double
            Dim csysMatrix(8) As Double
            Dim transform(3, 3) As Double
            Try
                ' get component data for current child component
                UFSession_p.Assem.AskComponentData(childComponent.Tag, partName, refsetName, instanceName, origin, csysMatrix, transform)

                compRef.Refference_DPNE = partName
                Dim handle As String = ""

                Try
                    UFSession_p.Tag.AskHandleFromTag(childComponent.Tag, handle)
                Catch ex As Exception
                End Try

                compRef.UGEntityHandle = handle

                NxSyslog_p.WriteLine("")
                NxSyslog_p.WriteLine("##NXReffsGet: START processing " + childComponent.DisplayName)
                NxSyslog_p.WriteLine("##NXReffsGet: Child Comp: " + childComponent.DisplayName + " // " + compRef.Refference_DPNE + " // Callout: " + compRef.CallOut + " // JournalIdentifier: " + childComponent.JournalIdentifier + " // refsetName: " + refsetName + " // instanceName: " + instanceName + " // handle: " + handle)
                If lw_p IsNot Nothing Then lw_p.WriteLine("")
                If lw_p IsNot Nothing Then lw_p.WriteLine("START processing " + childComponent.DisplayName)
                If lw_p IsNot Nothing Then lw_p.WriteLine("Child Comp: " + childComponent.DisplayName + " // " + compRef.Refference_DPNE + " // Callout: " + compRef.CallOut + " // JournalIdentifier: " + childComponent.JournalIdentifier + " // refsetName: " + refsetName + " // instanceName: " + instanceName + " // handle: " + handle)

                Dim childItemID As String = ""
                Dim childRev As String = ""

                Try
                    childItemID = childComponent.GetUserAttributeAsString("DB_PART_NO", NXObject.AttributeType.String, 0)
                    childRev = childComponent.GetUserAttributeAsString("DB_PART_REV", NXObject.AttributeType.String, 0)
                Catch ex As Exception
                    If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                End Try

                Try
                    For Each attrInfo As NXObject.AttributeInformation In childComponent.GetInstanceUserAttributes()
                        Try
                            If attrInfo.Title Is Nothing Or attrInfo.Category Is Nothing Then
                                Continue For
                            End If

                            If attrInfo.Title.Equals("DB_PART_NO") AndAlso
                                       (attrInfo.Category.Equals("KAUF") Or attrInfo.Category.Equals("ET") Or attrInfo.Category.Equals("SPEZ")) AndAlso
                                       Not String.IsNullOrEmpty(attrInfo.StringValue) Then
                                If lw_p IsNot Nothing Then lw_p.WriteLine(attrInfo.Category + " // " + attrInfo.Title + " // " + attrInfo.StringValue)
                                NxSyslog_p.WriteLine(attrInfo.Category + " // " + attrInfo.Title + " // " + attrInfo.StringValue)
                                childItemID = attrInfo.StringValue
                            End If

                            If attrInfo.Title.Equals("DB_PART_REV") AndAlso
                                       (attrInfo.Category.Equals("KAUF Revision") Or attrInfo.Category.Equals("ET Revision") Or attrInfo.Category.Equals("SPEZ Revision")) AndAlso
                                       Not String.IsNullOrEmpty(attrInfo.StringValue) Then
                                If lw_p IsNot Nothing Then lw_p.WriteLine(attrInfo.Category + " // " + attrInfo.Title + " // " + attrInfo.StringValue)
                                NxSyslog_p.WriteLine(attrInfo.Category + " // " + attrInfo.Title + " // " + attrInfo.StringValue)
                                childRev = attrInfo.StringValue
                            End If
                        Catch ex As Exception
                            If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                        End Try

                    Next
                Catch ex As Exception
                    If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
                End Try

                compRef.ItemID = childItemID
                compRef.RevID = childRev

                NxSyslog_p.WriteLine("##NXReffsGet: ItemID: " + compRef.ItemID + " // Rev:" + compRef.RevID)
                If lw_p IsNot Nothing Then lw_p.WriteLine("ItemID: " + compRef.ItemID + " // Rev:" + compRef.RevID)

                Dim partName_NE As String = partName
                If partName_NE.Contains("\") Then
                    partName_NE = partName_NE.Substring(partName_NE.LastIndexOf("\") + 1)
                End If

                ' check if current component is tc refference or is not a full path
                If partName.Contains("PH=") Then
                    ' get item id from tc database by item puid

                    Dim ItemPUID As String = partName.Substring(partName.IndexOf("PH=") + 3).Trim
                    Dim itemIDFromTC = ItemIdFromTCDBGetByItemPUID(ItemPUID)
                    If Not String.IsNullOrEmpty(itemIDFromTC) Then
                        childItemID = itemIDFromTC
                        compRef.ItemID = childItemID
                    End If

                    compRef.TCRefference = partName

                ElseIf partName_NE.ToLower.StartsWith("dsg") Or partName_NE.ToLower.StartsWith("dwg") Then
                    childComponent.SetName(partName_NE.ToUpper.Replace(".PRT", ""))
                    savePart_p = True
                End If

            Catch ex As Exception
                If lw_p IsNot Nothing Then lw_p.WriteLine(ex.ToString)
            End Try

            compRef.isSuppressed = childComponent.IsSuppressed

            NxSyslog_p.WriteLine("##NXReffsGet: is suppressed: " + compRef.isSuppressed.ToString)
            If lw_p IsNot Nothing Then lw_p.WriteLine("is suppressed:" + compRef.isSuppressed.ToString)

            NxSyslog_p.WriteLine("##NXReffsGet: END processing " + childComponent.DisplayName)
            If lw_p IsNot Nothing Then lw_p.WriteLine("END processing " + childComponent.DisplayName)

            NXRefferences_Obj_p.NXComponentRefferences.Add(compRef)

            If processSubAssemby_p AndAlso childComponent.GetChildren.Length <> 0 Then
                Call ProcessComponentChilds(childComponent, UFSession_p, NXSession_p, NxSyslog_p, NXRefferences_Obj_p, processSubAssemby_p, savePart_p, lw_p)
            End If

        Next

    End Sub


    ''' <summary>
    ''' function to get Item ID by ItemPUID from TC database
    ''' </summary>
    ''' <remarks>
    ''' #New: 3.1503;08.04.2021;S.Gueth
    ''' </remarks>
    Private Function ItemIdFromTCDBGetByItemPUID(ByVal ItemPUID_p As String) As String
        Dim res As String = ""
        Try

            ' read sql file
            Static SQL_ItemIdByItemPUID As String = IO.File.ReadAllText(SQL_ItemIdByItemPUID_DPNE)

            ' get db connection
            Call DBConnection_cls.ConnectToDB(cmd)

            cmd.Parameters.Clear()
            cmd.CommandType = CommandType.Text
            cmd.CommandText = SQL_ItemIdByItemPUID

            '-- #Doc: define sql parameter
            Dim para_itemPUID = DBConnection_cls.DBProviderFactory.CreateParameter()
            para_itemPUID.ParameterName = "para_itemPUID"
            para_itemPUID.Value = ItemPUID_p
            cmd.Parameters.Add(para_itemPUID)

            NxSyslog.WriteLine("##NXReffsGet: para_itemPUID value: " + para_itemPUID.Value.ToString)
            If lw IsNot Nothing Then lw.WriteLine("para_itemPUID value: " + para_itemPUID.Value.ToString)

            Using reader As IDataReader = cmd.ExecuteReader()
                While reader.Read
                    res = reader.Item("ITEM_ID").ToString
                    Exit While
                End While
            End Using

            NxSyslog.WriteLine("##NXReffsGet: ItemIdFromTCDBGetByItemPUID result: " + res)
            If lw IsNot Nothing Then lw.WriteLine("ItemIdFromTCDBGetByItemPUID result: " + res)

        Catch ex As Exception
            NxSyslog.WriteLine("##NXReffsGet: EX in Method ItemIdFromTCDBGetByItemPUID: " + ex.ToString())
            If lw IsNot Nothing Then lw.WriteLine("EX in Method ItemIdFromTCDBGetByItemPUID: " + ex.ToString())
        End Try

        Return res
    End Function

End Module

''' <summary>
''' Class that defines a NX Refference
''' </summary>
''' <remarks>
''' #New: 3.1503;11.05.2021;S.Gueth
''' #LUp: 3.1503;12.05.2021;S.Gueth
''' </remarks>
<Serializable>
Public Class NXRefferences_cls

    Public Property NXComponentRefferences As New List(Of NXComponentRefference_cls)
    Public Property InterPartLinkRefferences As New List(Of String)
    Public Property WaveLinkRefferences As New List(Of String)
    Public Property PartFamilyRefferences As New List(Of PartFamilyRefference_cls)
    Public Property WasPartFamilyObject As Boolean = False
    Public Property PartFamilyTemplate As String = ""
    Public ReadOnly Property isPartFamilyMember As Boolean
        Get
            If String.IsNullOrEmpty(Me.PartFamilyTemplate) Then
                Return False
            Else
                Return True
            End If
        End Get
    End Property
    Public Property isPartFamilyMaster As Boolean = False

    ReadOnly Property RefferencesCount As Integer
        Get
            Return NXComponentRefferences.Count + InterPartLinkRefferences.Count + WaveLinkRefferences.Count + PartFamilyRefferences.Count
        End Get
    End Property

    Public Function WirteXMLFile(ByVal File_DPNE_p As String) As Boolean

        Dim fileInfo_obj As New IO.FileInfo(File_DPNE_p)
        If Not IO.Directory.Exists(fileInfo_obj.Directory.FullName) Then
            Try
                IO.Directory.CreateDirectory(fileInfo_obj.Directory.FullName)
            Catch ex As Exception
            End Try
        End If

        Try
            Dim xs As New System.Xml.Serialization.XmlSerializer(GetType(NXRefferences_cls))
            Using strWriter As New IO.StringWriter
                xs.Serialize(strWriter, Me)
                IO.File.WriteAllText(File_DPNE_p, strWriter.ToString)
                If IO.File.Exists(File_DPNE_p) Then
                    Return True
                End If
            End Using
        Catch ex As Exception
        End Try
        Return False
    End Function

    Public Shared Function LoadFromXMLFile(ByVal File_DPNE_p As String) As NXRefferences_cls
        Dim result As NXRefferences_cls = Nothing
        Try
            Dim xs As New System.Xml.Serialization.XmlSerializer(GetType(NXRefferences_cls))
            Using reader As TextReader = New StringReader(IO.File.ReadAllText(File_DPNE_p))
                result = CType(xs.Deserialize(reader), NXRefferences_cls)
            End Using
        Catch ex As Exception
            Throw ex
        End Try
        Return result
    End Function

    <Serializable>
    Public Class NXComponentRefference_cls
        Public Property Refference_DPNE As String = ""
        Public Property ItemID As String = ""
        Public Property RevID As String = ""
        Public Property CallOut As String = ""
        Public Property isReplaced As Boolean = False
        Public Property TCRefference As String = ""
        Public Property isSuppressed As Boolean = False
        Public Property asRefferenceOnly As Boolean = False
        Public Property UGEntityHandle As String = ""
        Public Property isNONGeometricComponent As Boolean = False
    End Class

    <Serializable>
    Public Class PartFamilyRefference_cls
        Public Property DBPartName As String = ""
        Public Property DBRevName As String = ""
    End Class

End Class

''' <summary>
''' class for databse connection
''' </summary>
''' <remarks>
''' #New: 3.1503;08.04.2021;S.Gueth
''' set following environmen tvaribales before executing nx journal:
''' DBProvider
''' OracleBin
''' SiteID
''' DBConnectionString
''' </remarks>
Public Class DBConnection_cls

    Private Shared Property dbConnection As Common.DbConnection = Nothing

    ''' <remarks>
    ''' #New: 3.1503;08.04.2021;S.Gueth
    ''' </remarks>
    Private Shared ReadOnly Property DBProvider As String
        Get
            Static DBProvider_stat = System.Environment.GetEnvironmentVariable("DBProvider")
            Return DBProvider_stat
        End Get
    End Property

    ''' <remarks>
    ''' #New: 3.1503;08.04.2021;S.Gueth
    ''' </remarks>
    Private Shared ReadOnly Property OracleBin As String
        Get
            Static OracleBin_stat = System.Environment.GetEnvironmentVariable("OracleBin")
            EnsureOracleBinIsInPath(OracleBin_stat)
            Return OracleBin_stat
        End Get
    End Property

    ''' <remarks>
    ''' #New: 3.1503;08.04.2021;S.Gueth
    ''' </remarks>
    Private Shared ReadOnly Property SiteID As String
        Get
            Static SiteID_stat = System.Environment.GetEnvironmentVariable("SiteID")
            Return SiteID_stat
        End Get
    End Property

    ''' <remarks>
    ''' #New: 3.1503;08.04.2021;S.Gueth
    ''' </remarks>
    Private Shared ReadOnly Property DBConnectionString As String
        Get
            Static DBConnectionString_stat = System.Environment.GetEnvironmentVariable("DBConnectionString")
            Return DBConnectionString_stat
        End Get
    End Property

    ''' <remarks>
    ''' #New: 3.1503;08.04.2021;S.Gueth
    ''' </remarks>
    Public Shared ReadOnly Property DBProviderFactory As Common.DbProviderFactory
        Get
            Static dbProviderFactory_stat As Common.DbProviderFactory = Common.DbProviderFactories.GetFactory(DBProvider)
            Return dbProviderFactory_stat
        End Get
    End Property

    ''' <summary>
    ''' function to get db connection object
    ''' </summary>
    ''' <remarks>
    ''' #New: 3.1503;08.04.2021;S.Gueth
    ''' </remarks>
    Private Shared Function GetConnection() As Common.DbConnection


        NxSyslog.WriteLine("##JournalDBConnection: Before connection to DB of TC.Site " + SiteID + " using DBProvider:" + DBProvider)
        If lw IsNot Nothing Then lw.WriteLine("Before connection to DB of TC.Site " + SiteID + " using DBProvider:" + DBProvider)

        Dim dbConnection_r As Common.DbConnection = DBProviderFactory.CreateConnection()
        dbConnection_r.ConnectionString = DBConnectionString

        Return dbConnection_r

    End Function

    ''' <summary>
    ''' generates the connection to the database
    ''' </summary>
    ''' <remarks>
    ''' #New: 3.1503;08.04.2021;S.Gueth
    ''' </remarks>
    Public Shared Sub ConnectToDB(ByRef cmd_p As Common.DbCommand)

        If dbConnection Is Nothing Then
            dbConnection = GetConnection()
        End If

        If cmd_p Is Nothing Then
            cmd_p = DBProviderFactory.CreateCommand()
            cmd_p.Connection = dbConnection
        End If

        If dbConnection Is Nothing Then
            NxSyslog.WriteLine("##JournalDBConnection: ERR: dbConnection Is Nothing")
            If lw IsNot Nothing Then lw.WriteLine("ERR: dbConnection Is Nothing")
        End If

        '-- open database connection
        If cmd_p.Connection.State <> ConnectionState.Open Then
            dbConnection.Open()
        End If

        If cmd_p.Connection.State <> ConnectionState.Open Then
            NxSyslog.WriteLine("##JournalDBConnection: ERR Connetion.State:" + cmd_p.Connection.State.ToString + "<>" + ConnectionState.Open.ToString)
            If lw IsNot Nothing Then lw.WriteLine("ERR: dbConnection Is Nothing")
        End If

    End Sub


    ''' <summary>
    ''' check if oracle bin db is in path
    ''' </summary>
    ''' <remarks>
    ''' #New: 3.1503;08.04.2021;S.Gueth
    ''' </remarks>
    Private Shared Sub EnsureOracleBinIsInPath(oracleBinDP_p As String)

        Dim pathEnvVar As String = Environment.GetEnvironmentVariable("PATH")
        If Not pathEnvVar.Contains(oracleBinDP_p) Then
            Environment.SetEnvironmentVariable("PATH", oracleBinDP_p + ";" + pathEnvVar)
        End If

    End Sub

End Class
