content center replace

Download Content Center Replace

If you can't read please download the document

Upload: dwi-darsono

Post on 29-Nov-2015

20 views

Category:

Documents


4 download

DESCRIPTION

conten

TRANSCRIPT

Option Strict On Imports Imports Imports Imports System System.Diagnostics System.Collections.Generic Inventor

Public Class ContentCenterReplace Inherits ComponentReplacer Private m_ccFinder As ContentCenterFinder Public Sub New(ByVal doc As Document, ByVal app As Application, Optional ByVal Language As String = "en-US") MyBase.New(doc, app, "ContentCenterReplace") m_ccFinder = New ContentCenterFinder(app, Language) m_ccFinder.CustomPartDirectory = CustomPartDirectory End Sub Public Property CreationMode() As FileCreationMode Get Return m_ccFinder.CreationMode End Get Set(ByVal value As FileCreationMode) m_ccFinder.CreationMode = value End Set End Property Public Property KeyColumnName() As String Get Return m_ccFinder.KeyColumnName End Get Set(ByVal value As String) m_ccFinder.KeyColumnName = value End Set End Property Public Sub Replace(ByVal componentName As String, ByVal ccPath As String , ByVal partNumber As String) Dim occurrence As ComponentOccurrence = FindComponent(componentN ame) Replace(occurrence, ccPath, partNumber) End Sub Public Sub Replace(ByVal occurrence As ComponentOccurrence, ByVal ccPath As String, ByVal partNumber As String) Dim newFileName As String = GetPartFullFileName(ccPath, partNumb er) ReplaceComponent(occurrence, newFileName) End Sub Public Sub ReplaceCustom(ByVal componentName As String, ByVal ccPath As String, ByVal partNumber As String, ByVal fileName As String, ByVal ParamArray c ustomNamesAndValues() As Object) Dim occurrence As ComponentOccurrence = FindComponent(componentN ame) ReplaceCustom(occurrence, ccPath, partNumber, fileName, customNa mesAndValues) End Sub

Public Sub ReplaceCustom(ByVal occurrence As ComponentOccurrence, ByVal ccPath As String, ByVal partNumber As String, ByVal fileName As String, ByVal Pa ramArray customNamesAndValues() As Object) Dim newFileName As String = GetCustomPartFullFileName(ccPath, pa rtNumber, fileName, customNamesAndValues) ReplaceComponent(occurrence, newFileName) End Sub Public Function GetPartFullFileName(ByVal ccPath As String, ByVal partNu mber As String) As String m_ccFinder.CustomPartDirectory = CustomPartDirectory Dim newFileName As String = m_ccFinder.FindFileName(ccPath, part Number, Nothing) CheckFileName(newFileName, ccPath, partNumber) Return newFileName End Function Public Function GetCustomPartFullFileName(ByVal ccPath As String, ByVal partNumber As String, ByVal fileName As String, ByVal ParamArray customNamesAndV alues() As Object) As String m_ccFinder.CustomPartDirectory = CustomPartDirectory Dim customNv As NameValueMap = CreateCustomMap(customNamesAndVal ues) Dim customInfo As New CustomInformation() customInfo.CustomFileName = fileName customInfo.CustomNamesAndValues = customNv Dim newFileName As String = m_ccFinder.FindFileName(ccPath, part Number, customInfo) CheckFileName(newFileName, ccPath, partNumber) Return newFileName End Function Private Sub CheckFileName(ByVal newFileName As String, ByVal ccPath As S tring, ByVal partNumber As String) If String.IsNullOrEmpty(newFileName) Then Throw New ArgumentException(String.Format("Content Cente r part not found: {0}:{1}", ccPath, partNumber)) End If End Sub Public Function GetValuesInColumn(ByVal familyPathName As String, ByVal columnName As String) As ArrayList Return m_ccFinder.GetValuesInColumn(familyPathName, columnName) End Function Public Function GetFamilyNames(ByVal pathName As String) As ArrayList Return m_ccFinder.GetFamilyNames(pathName) End Function Public Function GetMatchingFamilyNames(ByVal pathName As String, ByVal p artialName As String, Optional ByVal options As FamilyMatchingOptions = FamilyMa tchingOptions.Recurse) As Dictionary(Of String, String) Return m_ccFinder.GetMatchingFamilyNames(pathName, partialName, options) End Function Private Sub ReplaceComponent(ByVal occurrence As ComponentOccurrence, By Val newFileName As String) ReplaceIfDifferent(occurrence, newFileName) End Sub

Private Function CreateCustomMap(ByVal ParamArray customNamesAndValues() As Object) As NameValueMap Dim customNv As NameValueMap = m_app.TransientObjects.CreateName ValueMap() Dim currentName As String = String.Empty Dim index As Integer For Each obj As Object In customNamesAndValues If (index Mod 2 = 0) Then currentName = obj.ToString() Else customNv.Add(currentName, obj) End If index += 1 Next Return customNv End Function End Class Public Enum FileCreationMode ByFunctionName = 0 AsCustom AsStandard End Enum Public Class NonContentReplace Inherits ComponentReplacer Private m_sourcePartDirectory As String Public Sub New(ByVal doc As Document, ByVal app As Application) MyBase.New(doc, app, "NonContentReplace") m_sourcePartDirectory = IO.Path.GetDirectoryName(doc.FullFileNam e) End Sub Public Property SourcePartDirectory() As String Get Return m_sourcePartDirectory End Get Set(ByVal value As String) m_sourcePartDirectory = value End Set End Property Public Sub ReplaceCustom(ByVal componentName As String, ByVal templateFi leName As String, ByVal generatedFileName As String, ByVal ParamArray parameterN amesAndValues() As Object) Dim occurrence As ComponentOccurrence = FindComponent(componentN ame) ReplaceCustom(occurrence, templateFileName, generatedFileName, p arameterNamesAndValues) End Sub Public Sub ReplaceCustom(ByVal occurrence As ComponentOccurrence, ByVal templateFileName As String, ByVal generatedFileName As String, ByVal ParamArray parameterNamesAndValues() As Object) If (Not generatedFileName.EndsWith(".ipt", StringComparison.Ordi

nalIgnoreCase)) Then generatedFileName += ".ipt" End If Dim fullPath As String = IO.Path.Combine(CustomPartDirectory, ge neratedFileName) If (Not IO.File.Exists(fullPath)) Then GeneratePart(fullPath, templateFileName, parameterNamesA ndValues) End If ReplaceIfDifferent(occurrence, fullPath) End Sub Sub GeneratePart(ByVal generatedFullFileName As String, ByVal templateFi leName As String, ByVal parameterNamesAndValues() As Object) Dim templateFullFileName As String = IO.Path.Combine(m_sourcePar tDirectory, templateFileName) Dim templatePart As Document = Nothing Try templatePart = m_app.Documents.Open(templateFullFileName , False) Catch ex As Exception Throw New ArgumentException("NonContentReplace: Cannot f ind (or open) the part: " + templateFullFileName, ex) End Try Try templatePart.SaveAs(generatedFullFileName, True) Catch ex As Exception Throw New ArgumentException("NonContentReplace: Cannot s ave the generated part: " + generatedFullFileName, ex) Finally templatePart.ReleaseReference() End Try If (parameterNamesAndValues.Length = 0) Then Return Dim errorHit As Boolean = False Dim parameterNotFound As String = String.Empty Dim generatedPart As Document = m_app.Documents.Open(generatedFu llFileName, False) Try Dim partDoc As PartDocument = DirectCast(generatedPart, PartDocument) Dim partParams As Parameters = partDoc.ComponentDefiniti on.Parameters Dim currentName As String = String.Empty Dim index As Integer For Each obj As Object In parameterNamesAndValues If (index Mod 2 = 0) Then currentName = obj.ToString() Else Dim foundParameter As Boolean = AssignPa rameter(currentName, obj, partParams) If (Not foundParameter) Then parameterNotFound = currentName Exit For End If End If index += 1 Next

generatedPart.Update() generatedPart.Save() Catch ex As Exception errorHit = True Finally generatedPart.ReleaseReference() End Try If (errorHit) Then Throw New ArgumentException("NonContentReplace: Error as signing parameters in the part: " + generatedFullFileName) End If If (Not String.IsNullOrEmpty(parameterNotFound)) Then Throw New ArgumentException(String.Format("NonContentRep lace: No parameter named {0} was not found in the part {1}", parameterNotFound, generatedFullFileName)) End If End Sub Function AssignParameter(ByVal currentName As String, ByVal obj As Objec t, ByVal partParams As Parameters) As Boolean For Each param As Inventor.Parameter In partParams If (param.Name = currentName) Then If (param.Units = "Text") Then param.Value = obj.ToString() ElseIf (param.Units = "Boolean") Then param.Value = CBool(obj) Else param.Expression = obj.ToString() End If Return True End If Next Return False End Function End Class Public MustInherit Class ComponentReplacer Protected m_doc As Document Protected m_app As Inventor.Application Protected m_assemDoc As AssemblyDocument Protected m_customPartDirectory As String Protected m_replaceAll As Boolean Protected m_deleteOldFiles As Boolean Private m_derivedClassName As String Public Sub New(ByVal doc As Document, ByVal app As Application, ByVal de rivedClassName As String) m_doc = doc m_app = app m_derivedClassName = derivedClassName m_assemDoc = TryCast(m_doc, AssemblyDocument) If (m_assemDoc Is Nothing) Then Throw New ArgumentException(m_derivedClassName & " can o nly be used in an assembly.") End If If (Not String.IsNullOrEmpty(m_doc.FullFileName)) Then

CustomPartDirectory = IO.Path.GetDirectoryName(m_doc.Ful lFileName) End If End Sub Public Property CustomPartDirectory() As String Get Return m_customPartDirectory End Get Set(ByVal value As String) m_customPartDirectory = value End Set End Property Public Property ReplaceAll() As Boolean Get Return m_replaceAll End Get Set(ByVal value As Boolean) m_replaceAll = value End Set End Property Public Property DeleteOldFiles() As Boolean Get Return m_deleteOldFiles End Get Set(ByVal value As Boolean) m_deleteOldFiles = value End Set End Property Friend Sub ReplaceIfDifferent(ByVal occurrence As ComponentOccurrence, B yVal newFileName As String) Dim oldFileName As String = GetFileName(occurrence) If (String.Equals(oldFileName, newFileName, StringComparison.Ord inalIgnoreCase)) Then Trace.WriteLine(" Component doesn't need replacement: " & newFileName) Return End If occurrence.Replace(newFileName, ReplaceAll) If (DeleteOldFiles) Then DeleteFile(oldFileName) End Sub Friend Function GetFileName(ByVal occurrence As ComponentOccurrence) As String Dim oldFileName As String = String.Empty Try oldFileName = occurrence.ReferencedDocumentDescriptor.Fu llDocumentName Catch End Try Return oldFileName End Function Friend Function FindComponent(ByVal componentName As String) As Componen tOccurrence

Dim compDef As AssemblyComponentDefinition = m_assemDoc.Componen tDefinition For Each compOcc As Inventor.ComponentOccurrence In compDef.Occu rrences If String.Equals(compOcc.Name, componentName, StringComp arison.OrdinalIgnoreCase) Then Return compOcc End If Next Throw New ArgumentException(m_derivedClassName + ": component no t found: " & componentName) End Function Public Sub DeleteFile(ByVal fileName As String) If (String.IsNullOrEmpty(fileName)) Then Return If (Not fileName.StartsWith(CustomPartDirectory, StringCompariso n.OrdinalIgnoreCase)) Then Return ' Don't delete standard parts. End If m_app.Documents.CloseAll(UnreferencedOnly:=True) For Each doc As Document In m_app.Documents If (String.Equals(doc.FullFileName, fileName) AndAlso do c.Open) Then Return If (DocumentHasReferenceTo(doc, fileName)) Then Return Next Trace.WriteLine("Deleting file: " & fileName) Try IO.File.Delete(fileName) Catch ' We don't care if we can't delete. There is probably a good reason. End Try End Sub Function DocumentHasReferenceTo(ByVal doc As Document, ByVal fileName As String) As Boolean For Each docdesc As DocumentDescriptor In doc.ReferencedDocument Descriptors If (docdesc.FullDocumentName.Contains(""} ' Support paths such as: "Fasteners->Pins->Cotter Pins" m_pathLevels = pathName.Split(stringSeparators, StringSp litOptions.None) End If End Sub Private Function FindFamily(ByVal parentNode As ContentTreeViewNode, ByV al level As Integer) As ContentFamily If level = m_pathLevels.Length - 1 Then If parentNode.Families.Count = 0 Then Return Nothing End If For Each fam As ContentFamily In parentNode.Families If fam.DisplayName = m_pathLevels(level) Then ' Debug.Print("--- ContentFamily D irectory = " & fam.MemberDirectory) Return fam End If Next Return Nothing End If For Each cNode As ContentTreeViewNode In parentNode.ChildNodes If cNode.DisplayName = m_pathLevels(level) Then Return FindFamily(cNode, level + 1) End If Next Return Nothing End Function Private Function FindNode(ByVal parentNode As ContentTreeViewNode, ByVal

level As Integer) As ContentTreeViewNode If level = m_pathLevels.Length Then Return parentNode End If For Each cNode As ContentTreeViewNode In parentNode.ChildNodes ' Trace.WriteLine(" --- Content node name: " & cNode.Dis playName) If cNode.DisplayName = m_pathLevels(level) Then Return FindNode(cNode, level + 1) End If Next Return Nothing End Function Private Function FindColumn(ByVal family As ContentFamily, ByVal columnN ame As String) As ContentTableColumn For i As Integer = 0 To 1 For Each col As ContentTableColumn In family.TableColumn s ' Search first for InternalName, then for Displa yHeading. ' If the user knows the internal name, this is s afe. If he only knows the display name, this should be OK ' but there could be localization problems. ' The InternalName is displayed as a tooltip whe n you mouse over the column title. So the user can find it. If ((i = 0 AndAlso String.Equals(col.InternalNam e, columnName, StringComparison.OrdinalIgnoreCase)) OrElse _ (i = 1 AndAlso String.Equals(col.DisplayHeading , columnName, StringComparison.OrdinalIgnoreCase))) Then Return col End If Next Next Return Nothing End Function Private Function FindFileByColumn(ByVal family As ContentFamily) As Stri ng ' Return the complete filename for this part number or filename ' Ask the Content Center to create the member if required 'Debug.Print(" Family: {0}", family.DisplayName); Dim keyColumnInternalName As String = String.Empty If (Not String.IsNullOrEmpty(KeyColumnName)) Then Dim keyColumn As ContentTableColumn = FindColumn(family, KeyColumnName) If (keyColumn Is Nothing) Then Throw New ArgumentException(String.Format("Conte ntCenterReplace: The column name {0} was not found in the famuly: {1}", KeyColum nName, family.DisplayName)) End If keyColumnInternalName = keyColumn.InternalName End If Dim partNumberColIndex As Integer = -1 Dim fileNameColIndex As Integer = -1 Dim keyColumnIndex As Integer = -1 Dim i As Integer = 1

For Each col As ContentTableColumn In family.TableColumns '' Debug.Print("{0}, Column: {1} ({2})", tabString, c ol.DisplayHeading, col.InternalName); If col.InternalName = "PARTNUMBER" Then partNumberColIndex = i ElseIf col.InternalName = "FILENAME" Then fileNameColIndex = i ElseIf col.InternalName = keyColumnInternalName Then keyColumnIndex = i End If i += 1 Next If partNumberColIndex < 0 OrElse fileNameColIndex < 0 Then Return String.Empty End If For Each row As ContentTableRow In family.TableRows Dim found As Boolean = False For Each cell As ContentTableCell In row If (cell.Column = keyColumnIndex OrElse _ keyColumnIndex = -1 And (cell.Column = partNum berColIndex OrElse cell.Column = fileNameColIndex)) Then If FilenamesAreEqual(cell.Value, m_partN umber) Then found = True Exit For End If End If Next If Not found Then Continue For ' Next Row End If Dim fileNameCell As ContentTableCell = row.Item(fileName ColIndex) Return GetOrCreateFilename(family, row, fileNameCell.Val ue) Next Return String.Empty End Function ''' ''' Find the file on disk, or create it from the Content Center. ''' ''' ''' ''' ''' filename with full path. Private Function GetOrCreateFilename(ByVal family As ContentFamily, ByVa l row As ContentTableRow, ByVal fileNameCellValue As String) As String Dim asCustom As Boolean = m_customInfo IsNot Nothing If (m_creationMode = FileCreationMode.AsCustom) Then asCustom = True ElseIf (m_creationMode = FileCreationMode.AsStandard) Then asCustom = False End If Dim fileName As String = String.Empty Dim fileNameInput As String = String.Empty

Dim fileNameLastLevel As String = String.Empty Dim customInput As NameValueMap = Nothing If (m_customInfo Is Nothing) Then fileNameLastLevel = MakeValidFileName(fileNameCellValue + ".ipt") Else fileNameLastLevel = MakeValidFileName(m_customInfo.Custo mFileName + ".ipt") End If If (Not asCustom) Then Dim standardPath As String = IO.Path.Combine(m_ccDir, fa mily.MemberDirectory) fileName = IO.Path.Combine(standardPath, fileNameLastLev el) Else fileName = IO.Path.Combine(CustomPartDirectory, fileName LastLevel) End If If (m_customInfo IsNot Nothing) Then customInput = m_customInfo.CustomNamesAndValues fileNameInput = fileName End If If Not System.IO.File.Exists(fileName) Then Dim failureReason As Inventor.MemberManagerErrorsEnum Dim failureMessage As String = String.Empty Dim refresh As Inventor.ContentMemberRefreshEnum = Conte ntMemberRefreshEnum.kUseDefaultRefreshSetting Trace.WriteLine("-- ContentCenterFinder: Creating Part: " + fileName) ' string CreateMember(object Ro w, out Inventor.MemberManagerErrorsEnum FailureReason, ' out string FailureMessage, In ventor.ContentMemberRefreshEnum Refresh, ' bool Custom, string FileName, object CustomInput, object Options) fileName = family.CreateMember(row, failureReason, failu reMessage, refresh, asCustom, fileNameInput, _ customInput, Nothing) End If Return fileName End Function Public Shared Function MakeValidFileName(ByVal fileName As String) As St ring Dim invalidChars As Char() = New Char() {"/"c, "\"c, ":"c, ""c, """"c} If (fileName.IndexOfAny(invalidChars) < 0) Then Return fileName End If For Each ch As Char In invalidChars fileName = fileName.Replace(ch, "_"c) Next Return fileName End Function Public Shared Function FilenamesAreEqual(ByVal nameA As String, ByVal na meB As String) As Boolean

If (String.Equals(nameA, nameB, StringComparison.OrdinalIgnoreCa se)) Then Return True If (String.Equals(MakeValidFileName(nameA), MakeValidFileName(na meB), StringComparison.OrdinalIgnoreCase)) Then Return True Return False End Function Private Sub CompensateForComDefect() ' The Content Center API will remember a previous child node, an d it will not enumerate other siblings of the same parent. ' They are counting on the caller to release the reference. System.GC.Collect() End Sub End Class Class CustomInformation Public CustomNamesAndValues As NameValueMap Public CustomFileName As String End Class Public Enum FamilyMatchingOptions None = 0 Recurse = 1 MatchAllInSubCategories = 2 End Enum