diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btdocs/Designs/generate-bnep-document.ebs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btdocs/Designs/generate-bnep-document.ebs Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,1315 @@ +' Generate-report.ebs +' +' This is a RoseScript utility with which a user can traverse a +' Rational Rose model and generate a Microsoft Word Document +' from the template "Formal.dot" +' +' A lot of the early versions of this script were derived from +' work previously published on the Rational Developer's Network +' and made freely available. +' +' TBD: +' 3. Provide cleaning subroutine or external utility to curb growth of %TEMP% +' with rosedXXX.wmf files of rendered diagrams. +' 4. Provide a package selection drop-down on the Dialog so that many projects can +' coexist in the same model (bonus - reduces the probability of a +' mook accidentally choosing to document the EPOC32 "include" package). +' +Const DefaultTool$ = "ReportGen" +Const PRODUCTDEFAULTWORDDOCFILENAME = 103 +' +' Different report type specs +' +Const RepAnalysisType = 0 +Const RepDesignType = 1 +Const RepAnalysisNDesignType = 2 +Const RepTestType = 3 +' +' Model verification options +' +Const RepVerifyNot = 0 +Const RepVerifySection = 1 +Const RepVerifyEmbed = 2 +' +' There is a state machine in here and these are the states +' +Const RPh_StartUp = 0 +Const RPh_Dynamic = 1 +Const RPh_Static = 2 +Const RPh_TailBoiler = 3 +Const RPh_Crosscheck = 4 +' +' For proofreading purposes +' +Const MissingTextStr$ = "ATTENTION: Do You Need Documentation For This Item?" +' +' Useful type declaraions +' +' +' Told you there was a state machine in here +' +Type GeneratorStateType + Phase As Integer +End Type +' +' Configurability - if this was Python, I'd serialise it +' and make it a config file +' +Type ReportOptionsType + Title As String + FileName As String + Template As String + Generate As Boolean + WhiteBlock As Boolean + ClassDiagrams As Boolean + ScenarioDiagrams As Boolean + StateDiagrams As Boolean + UseCaseDiagrams As Boolean + CppSyntax As Boolean + PublicOnly As Boolean + FEBoiler As Boolean + BEBoiler As Boolean + SupportSubheadingTags As Boolean + HighlightDocGaps As Boolean + DocType As Integer + VerifyType As Integer +End Type +' +' When verifying the model, we need to establish relationships +' between scenario/sequence diagrams and their title. Also, on each iteration, we need to +' check that we don't create duplicate entries where a method is used +' more than once in the same context. +' +Type DiagEntry + FigureTitle As String + Diagram As ScenarioDiagram + SeenBefore As Boolean +End Type +' +' Globals - don't we just lurve Basic? +' +Private ReportOptions As ReportOptionsType +Private GeneratorState As GeneratorStateType +' +' An array of DiagEntry +' +Public GlobalDiagList() As DiagEntry +' +' So, the documentation doesn't explain how one would elicit the +' size of a dynamic array, so the counts have to be externalised. +' Just exactly how crap is that? +' +Public DiagListCount As Integer +Public GlobalDiagListSize As Integer + +Public LicensedRoseApplication As Application +Private resIFace As Object + +Public RWU_DiagramCount As Integer +' +' Sort of like an Application Constructor - yech! +' +Sub WordUtilInit() + Let RWU_DiagramCount = 1 + Let DiagListCount = 0 + Let GlobalDiagListSize = 0 + ReDim GlobalDiagList(0) +End Sub + +' +' Helper function +' +Sub Para(WordApp As Object) + WordApp.InsertPara +End Sub +' +' For banging in a huge bunch of whitespace +' +Sub WhiteBlock(WordApp As Object) + Para WordApp + Para WordApp + Para WordApp + Para WordApp + Para WordApp +End Sub +' +' Helper for page breaks +' +Sub Break(WordApp As Object) + WordApp.InsertPageBreak +End Sub +' +' This is to overcome the limitations of Word as a programmable application +' and all I can say is that the details are nasty. +' +Sub ReplaceFinalParagraphKludge (WordApp As Object) + WordApp.linedown + WordApp.charright 1, 1 ' go right one character and select + WordApp.insertpara ' overwrite the selected para marker with a new one + WordApp.lineup +End Sub +' +' Will need to reset the state on these objects regularly +' +Sub ResetGlobalDiagList + For i% = 0 To GlobalDiagListSize-1 + GlobalDiagList(i).SeenBefore = False + Next i +End Sub +' +' We need this for extracting diagrams and rendering them +' on the file system before inserting them into a Word +' document. Note that this does not clean up after itself +' which means that you are likely to accumulate rosedXXX.wmf +' files in your %TEMP% directory. The good news is that it +' transparently reuses files on each run, so this is not inevitable +' and unrestrained growth. +' +Function GetTmpFileName + Dim tmpFileName As String + Dim tmpPathName As String + + tmpPathName = Environ("TEMP") + If tmpPathName = "" Then + tmpPathName = CurDir + End If + Do + tmpFileName = tmpPathName + "\rosed" & RWU_DiagramCount & ".wmf" + If Not Dir(tmpFileName)="" Then + Kill(tmpFileName) + End If + Loop Until (Dir(tmpFileName)="") + RWU_DiagramCount = RWU_DiagramCount + 1 + GetTmpFileName = tmpFileName +End Function + +'---------------------------------------------------------------------------- +' +' Specialist Word-related subroutines +' +' +' Generic Diagram insertion +' +Sub WordInsertDiagram(fileName As String, WordApp As Object) + 'ReplaceFinalParagraphKludge WordApp + WordApp.CenterPara + WordApp.InsertPicture fileName, false, false + Para WordApp + ReplaceFinalParagraphKludge WordApp +End Sub +' +' Each diagram type is literally a different type in the object model, so +' since Basic has no polymorphic facilities, we have to resort to +' coding up a subroutine for each type. Yawn! +' +Sub WordInsertScenarioDiagram(aDiagram As ScenarioDiagram, WordApp As Object) + Dim tmpFileName As String + Let tmpFileName = GetTmpFileName + aDiagram.RenderEnhanced tmpFileName + WordInsertDiagram tmpFileName, WordApp +End Sub + +Sub WordInsertStateDiagram(aDiagram As StateDiagram, WordApp As Object) + Dim tmpFileName As String + Let tmpFileName = GetTmpFileName + aDiagram.RenderEnhanced tmpFileName + WordInsertDiagram tmpFileName, WordApp +End Sub + +Sub WordInsertClassDiagram(aDiagram As ClassDiagram, WordApp As Object) + Dim tmpFileName As String + Let tmpFileName = GetTmpFileName + aDiagram.RenderEnhanced tmpFileName + WordInsertDiagram tmpFileName, WordApp +End Sub + +' +' So we want to be able to translate our "depth" in the model into the +' appropriate heading style in Word. +' +Function GetWordHeadingStyleName(HeadingNumber As Integer) As String + GetWordHeadingStyleName = "Heading " & CStr(HeadingNumber) +End Function +' +' Generalised heading insertion by number +' +Sub WordInsertHeading(aLevel As Integer, aString As String, WordApp As Object) + ' If you do not do it, it will not run. + ReplaceFinalParagraphKludge WordApp + ' Here's the real code that actually does something + WordApp.FormatStyle GetWordHeadingStyleName(aLevel) + WordApp.Insert aString + Para WordApp + WordApp.FormatStyle "Normal" +End Sub + +Sub WordInsertDocumentation(HeadingLevel As Integer, Documentation As String, WordApp As Object) + ' + ' It was requested that the script support the insertion of + ' an HTML-like tag in the object documentation that would force the + ' insertion of a subheading in the output text. + ' This will interefere with the real HTML generation capabilities + ' of Rose, so it was originally only supported as a variant on the + ' script. This presents boring maintenance duplication issues, however, so it + ' was reincorporated as a configurable option. Unfortunately, it does change + ' the signature of this method such that it requires a HeadingLevel even when it + ' doesn't use one. + ' + Dim Astr As String + Dim Bstr As String + Dim Cstr As String + + If Documentation <> "" Then + If ReportOptions.SupportSubheadingTags Then + Astr = Trim(Documentation) + Print "Astr: ", Astr + x% = InStr(1,Astr,"",1) + y% = InStr(1,Astr,"",1) + While x% <> 0 And y% <> 0 + Cstr = Left(Astr,x%-1) + Print "Cstr : ", Cstr + WordApp.FormatStyle "Normal" + WordApp.Insert Trim(Cstr) + Para WordApp + + Bstr = Mid(Astr,x%+3,y%-(x%+3)) + Print "Bstr : ", Bstr + WordInsertHeading HeadingLevel,Trim(Bstr),WordApp + + Astr = Right(Astr,Len(Astr)-(y%+3)) + Print "Astr : ",Astr + x% = InStr(1,Astr,"",1) + y% = InStr(1,Astr,"",1) + Wend + WordApp.FormatStyle "Normal" + WordApp.Insert Trim(Astr) + Para WordApp + Else + WordApp.FormatStyle "Normal" + WordApp.Insert Trim(Documentation) + Para WordApp + End If + Else + ' Oh no - we seem to have missed out a piece of documentation. + ' Another proofreading setting will highlight this lacuna for + ' you in lucky red text. + If ReportOptions.HighlightDocGaps Then + WordApp.FormatStyle "Body Text" + WordApp.Insert MissingTextStr + Para WordApp + End If + End If + ' + ' To assist in the proofreading phases, it seemed useful + ' to have a mode in which large chunks of whitespace were + ' inserted into the document at every point where the hard working + ' editor might wish to scribble notes and comments during the development + ' of the text. Run the script with this set and print out the resultant document + ' and you have a doc that facilitates the inveterate scribbler. + ' I'm a great believer in appropriate technology. + ' + If ReportOptions.WhiteBlock Then + WhiteBlock WordApp + End If + +End Sub +' +' Of course we want each of our diagrams to be numbered and titled. +' It's the done thing, and it's the thing that gets done here. +' +Sub WordInsertFigureName(aFigureName As String, WordApp As Object) + WordApp.FormatStyle "Centered" + WordApp.Insert "Figure " + CStr(RWU_DiagramCount-1) & ": " & aFigureName + Para WordApp + WordApp.FormatStyle "Normal" +End Sub +' +' Unfortunately, we have to operate slightly differently for scenarios, because of +' the verifications we may wish to run. +' +Sub WordInsertScenarioFigureName(aFigureName As String, WordApp As Object, XCEntry As DiagEntry) + Dim tstr$ + tstr = "Figure " + CStr(RWU_DiagramCount-1) & ": " & aFigureName + WordApp.FormatStyle "Centered" + 'WordApp.Insert "Figure " + CStr(RWU_DiagramCount-1) & ": " & aFigureName + WordApp.Insert tstr + Para WordApp + WordApp.FormatStyle "Normal" + ' Need to keep track of titles applied to scenario diagrams. + XCEntry.FigureTitle = tstr + Let GlobalDiagList(DiagListCount) = XCEntry + DiagListCount = DiagListCount + 1 +End Sub + + +'--------------------------------------------------------------------------- +' +' Some handy utility muffins. +' + +Public Function GetResourceString(resourceID As Long) As String + + If (resIFace Is Nothing) then + Set resIFace = CreateObject("rvsreportgenres.rvsrepgeninterface") + End If + + GetResourceString = resIFace.GetString(resourceID) +End Function + + +Function GetLicensedRoseApplication() As Application + Set GetLicensedRoseApplication = RoseApp.GetLicensedApplication("{A567222E-CBBE-11D0-BC0B-00A024C67143}") +End Function + +Function ReportDialogLoop(controlname$, action%, suppvalue%) As Integer + If controlname$ = "Browse" Then + FileName$ = SaveFilename$ ("Create a Word document", "Word Documents:*.DOC") + If FileName$ <> "" Then + DlgText "FileName", FileName$ + End If + ReportDialogLoop = 1 + End If +End Function + +Function EnclosingDirPath(FileName As String) + ' Extracts the enclosing directory path from a file name + Dim Pos1, Pos2, Pos3 + On Error GoTo EnclosingDirPath_exception + + Pos3 = 255 + Pos2 = 1 + Pos1 = 1 + Do + Pos3 = InStr(Pos2 + 1, FileName, "\") + If Pos3 <> 0 Then + Pos1 = Pos2 + Pos2 = Pos3 + Else + Exit Do + End If + Loop + + EnclosingDirPath = Left(FileName, Pos2 - 1) + Exit Function + +EnclosingDirPath_exception: + Resume EnclosingDirPath_end +EnclosingDirPath_end: + 'Exit with the full path + EnclosingDirPath = FileName +End Function + +Function GetAllOfClasses(aCategory As Category) As ClassCollection + + Dim theCatClassCollection As New ClassCollection + Dim theCatClass As Class, theCatInnerClass As Class + Dim I As Integer, J As Integer + + For I = 1 To aCategory.Classes.Count + Set theCatClass = aCategory.Classes.GetAt(I) + theCatClassCollection.Add theCatClass + For J = 1 To theCatClass.GetAllNestedClasses.Count + Set theCatInnerClass = theCatClass.GetAllNestedClasses.GetAt(J) + theCatClassCollection.Add theCatInnerClass + Next J + Next I + + Set GetAllOfClasses = theCatClassCollection +End Function + +Function MakeFileName (Path As String, FileName As String) As String + ' Check to see if the last character is a separator + If Instr ("\/", Right$(Path, 1)) Then + MakeFileName$ = Path & FileName + Else + MakeFileName$ = Path & "\" & FileName + End If +End Function + +Function ChangeFileExtension (FullFileName As String, NewExtension As String) As String + FilePath$ = FileParse$ (FullFileName, 2) + FileRoot$ = FileParse$ (FullFileName, 4) + ChangeFileExtension$ = MakeFileName$ (FilePath$, FileRoot$ & "." & NewExtension$) +End Function + +'------------------------------------------------------------------------------ +' +' Rose collections are unsorted. This is not considered sightly. +' + +Sub sortalpha( aCategory As Category, myAlpha() As String) + Dim theCatClassCollection As ClassCollection + Set theCatClassCollection = GetAllOfClasses(aCategory) + + For ike = 1 To theCatClassCollection.count + myAlpha(ike) = theCatClassCollection.GetAt(ike).Name + Next ike + arraysort myAlpha + + Set theCatClassCollection = Nothing +End Sub + +Sub sortalphaclassdiagrams( aCategory As Category, myAlpha() As String) + Dim classDiagrams As ClassDiagramCollection + Set classDiagrams = aCategory.ClassDiagrams + + For ike = 1 To classDiagrams.count + myAlpha(ike) = classDiagrams.GetAt(ike).Name + Next ike + arraysort myAlpha + + Set classDiagrams = Nothing +End Sub + +Sub sortalphascenariodiagrams( aCategory As Category, myAlpha() As String) + Dim scenarioDiagrams As ScenarioDiagramCollection + Set scenarioDiagrams = aCategory.ScenarioDiagrams + + For ike = 1 To ScenarioDiagrams.count + myAlpha(ike) = ScenarioDiagrams.GetAt(ike).Name + Next ike + arraysort myAlpha + + Set ScenarioDiagrams = Nothing +End Sub + + +'------------------------------------------------------------------------------ +' +' These higher level procedures pretty much do what their names say they do. +' +Sub SearchForClassDiagramsInPackage(WordApp As Object, aCategory As Category, HeadingNumber As Integer) + + Dim classDiagrams As ClassDiagramCollection + Dim aClassDiagram As ClassDiagram + Dim Alpha() As String + + Set classDiagrams = aCategory.ClassDiagrams + ReDim Alpha(classDiagrams.Count) + SortAlphaClassDiagrams aCategory, alpha + + If classDiagrams.Count Then + 'Dim theClass As Class + 'Dim NestedClasses As ClassCollection + + For CLSID = 1 To classDiagrams.Count + Ike = classDiagrams.FindFirst(Alpha(CLSID)) + Set aClassDiagram = classDiagrams.GetAt(Ike) + If Not (aClassDiagram.IsUseCaseDiagram) Then + WordInsertHeading HeadingNumber, aClassDiagram.Name, WordApp + WordInsertClassDiagram aClassDiagram, WordApp + WordInsertFigureName aClassDiagram.Name, WordApp + WordInsertDocumentation HeadingNumber+1, aClassDiagram.Documentation, WordApp + End If + Next CLSID + End If + + + 'For clsID = 1 To classDiagrams.Count + ' Set aClassDiagram=classDiagrams.GetAt(clsID) + ' If Not (aClassDiagram.IsUseCaseDiagram) Then + ' WordInsertHeading HeadingNumber, aClassDiagram.Name, WordApp + ' WordInsertClassDiagram aClassDiagram, WordApp + ' WordInsertFigureName aClassDiagram.Name, WordApp + ' WordInsertDocumentation HeadingNumber+1, aClassDiagram.Documentation, WordApp + ' End If + 'Next clsID +End Sub + +Sub SearchForSeqAndCollabDiagramsInPackage(WordApp As Object, aCategory As Category, HeadingNumber As Integer) + + Dim ScenarioDiagrams As ScenarioDiagramCollection + Dim aScenarioDiagram As ScenarioDiagram + Dim Alpha() As String + + Set ScenarioDiagrams = aCategory.ScenarioDiagrams + ReDim Alpha(ScenarioDiagrams.Count) + SortAlphaScenarioDiagrams aCategory, alpha + + Dim XCEntry As DiagEntry + GlobalDiagListSize = GlobalDiagListSize + ScenarioDiagrams.Count + ReDim Preserve GlobalDiagList(GlobalDiagListSize) + For ScenID = 1 To ScenarioDiagrams.Count + Ike = ScenarioDiagrams.FindFirst(Alpha(ScenID)) + Set aScenarioDiagram=ScenarioDiagrams.GetAt(Ike) + WordInsertHeading HeadingNumber, aScenarioDiagram.Name, WordApp + WordInsertScenarioDiagram aScenarioDiagram, WordApp + Set XCEntry.Diagram = aScenarioDiagram + WordInsertScenarioFigureName aScenarioDiagram.Name, WordApp, XCEntry + WordInsertDocumentation HeadingNumber+1, aScenarioDiagram.Documentation, WordApp + Next ScenID +End Sub + +Sub SearchForClassDiagramsInUseCase(WordApp As Object, aUseCase As UseCase, HeadingNumber As Integer) + + Dim classDiagrams As ClassDiagramCollection + Dim aClassDiagram As ClassDiagram + + Set classDiagrams = aUseCase.ClassDiagrams + + For clsID = 1 To classDiagrams.Count + Set aClassDiagram=classDiagrams.GetAt(clsID) + If Not (aClassDiagram.IsUseCaseDiagram) Then + WordInsertHeading HeadingNumber, aClassDiagram.Name, WordApp + WordInsertClassDiagram aClassDiagram, WordApp + WordInsertFigureName aClassDiagram.Name, WordApp + WordInsertDocumentation HeadingNumber+1, aClassDiagram.Documentation, WordApp + Else + If (aClassDiagram.IsUseCaseDiagram) And (ReportOptions.UseCaseDiagrams) Then + WordInsertHeading HeadingNumber, aClassDiagram.Name, WordApp + WordInsertClassDiagram aClassDiagram, WordApp + WordInsertFigureName aClassDiagram.Name, WordApp + WordInsertDocumentation HeadingNumber+1, aClassDiagram.Documentation, WordApp + End If + End If + Next clsID +End Sub + + +Sub SearchForSeqAndCollabDiagramsInUseCase(WordApp As Object, aUseCase As UseCase, HeadingNumber As Integer) + + Dim ScenarioDiagrams As ScenarioDiagramCollection + Dim aScenarioDiagram As ScenarioDiagram + + Set ScenarioDiagrams = aUseCase.ScenarioDiagrams + Dim XCEntry As DiagEntry + GlobalDiagListSize = GlobalDiagListSize + ScenarioDiagrams.Count + ReDim Preserve GlobalDiagList(GlobalDiagListSize) + For ScenID = 1 To ScenarioDiagrams.Count + Set aScenarioDiagram=ScenarioDiagrams.GetAt(ScenID) + WordInsertHeading HeadingNumber, aScenarioDiagram.Name, WordApp + WordInsertScenarioDiagram aScenarioDiagram, WordApp + Set XCEntry.Diagram = aScenarioDiagram + WordInsertScenarioFigureName aScenarioDiagram.Name, WordApp, XCEntry + WordInsertDocumentation HeadingNumber+1, aScenarioDiagram.Documentation, WordApp + Next ScenID +End Sub + + + +Sub SearchForStateDiagramsInPackage(WordApp As Object, aCategory As Category, HeadingNumber As Integer) + Dim aStateMachineOwner As StateMachineOwner + Dim aStateMachineCollection As StateMachineCollection + Dim aStateMachine As StateMachine + Dim aStateDiagram As StateDiagram + Dim aStateDiagramCollection As StateDiagramCollection + Dim aStateCollection As StateCollection + Dim aState As State + + Set aStateMachineOwner = aCategory.StateMachineOwner + Set aStateMachineCollection = aStateMachineOwner.StateMachines + If aStateMachineCollection.Count Then + For SMID = 1 To aStateMachineCollection.Count + Set aStateMachine = aStateMachineCollection.GetAt(SMID) + Set aStateDiagramCollection = aStateMachine.Diagrams + WordInsertHeading HeadingNumber, aStateMachine.Name, WordApp + If aStateDiagramCollection.Count Then + For SDID = 1 To aStateDiagramCollection.Count + Set aStateDiagram = aStateDiagramCollection.GetAt(SDID) + WordInsertHeading HeadingNumber, aStateDiagram.Name, WordApp + WordInsertStateDiagram aStateDiagram, WordApp + WordInsertFigureName aStateDiagram.Name, WordApp + WordInsertDocumentation HeadingNumber+1, aStateDiagram.Documentation, WordApp + Next SDID + End If + Set aStateCollection = aStateMachine.States + If aStateCollection.Count Then + For STID = 1 To aStateCollection.Count + Set aState = AstateCollection.GetAt(STID) + WordInsertHeading HeadingNumber+1, aState.Name, WordApp + WordInsertDocumentation HeadingNumber+1, aState.Documentation, WordApp + Next STID + End If + Next SMID + End If +End Sub +' +' Cunningly, we find that Use Case diagrams are not a distinct type, +' but are a specialised state of ClassDiagram +' Ho ho, go figure. +' +Sub SearchForUseCaseDiagramsInPackage(WordApp As Object, aCategory As Category, HeadingNumber As Integer) + Dim ClassDiagrams As ClassDiagramCollection + Dim aClassDiagram As ClassDiagram + + Set ClassDiagrams = aCategory.ClassDiagrams + For ClsID = 1 To ClassDiagrams.Count + Set aClassDiagram = ClassDiagrams.GetAt(ClsID) + If aClassDiagram.IsUseCaseDiagram Then + WordInsertHeading HeadingNumber, aClassDiagram.Name, WordApp + WordInsertClassDiagram aClassDiagram, WordApp + WordInsertFigureName aClassDiagram.Name, WordApp + WordInsertDocumentation HeadingNumber+1, aClassDiagram.Documentation, WordApp + End If + Next ClsID +End Sub + + +'------------------------------------------------------------------------------ +' +' We live in a C++ world, so we need to be able to show our attributes +' in a way familiar to code monkeys. +' +Sub GenerateAttribute(WordApp As Object, anAttribute As Attribute, HeadingNumber As Integer) + Dim theAttribute As String + + If ReportOptions.CppSyntax Then + Select Case anAttribute.ExportControl + Case rsPublicAccess + theAttribute = "Public: " + Case rsProtectedAccess + theAttribute = "Protected: " + Case rsPrivateAccess + theAttribute = "Private: " + End Select + theAttribute = theAttribute & anAttribute.Type & " " + End If + + theAttribute = theAttribute & anAttribute.Name + If ReportOptions.CppSyntax Then + If Len(anAttribute.InitValue) > 0 Then + theAttribute = theAttribute & " = " & anAttribute.InitValue + End If + End If + + WordInsertHeading HeadingNumber, theAttribute, WordApp + WordInsertDocumentation HeadingNumber+1, anAttribute.Documentation, WordApp +End Sub +' +' We like our attributes grouped according to their access specification, of course +' +Sub GenerateClassAttributeAccessGroup(WordApp As Object, attColl As AttributeCollection, HeadingNumber As Integer) + If attColl.Count Then + For AttrID = 1 To attColl.Count + GenerateAttribute WordApp, attColl.GetAt(AttrID), HeadingNumber + Next AttrID + End If +End Sub +' +' So this procedure iterates across the lot and groups them accordingly. +' However, I'm pretty sure we would frown on any public class attributes, wouldn't we? +' And I always think that protected class attributes have to be well justified. +' Generally they are used to get round analysis errors, otherwise. +' +Sub GenerateClassAttributes(WordApp As Object, aClass As Class, HeadingNumber As Integer) + Dim PublicAttributes As New AttributeCollection + Dim ProtectedAttributes As New AttributeCollection + Dim PrivateAttributes As New AttributeCollection + Dim anAttribute As Attribute + + If aClass.Attributes.Count Then + For AttrID = 1 To aClass.Attributes.Count + Set anAttribute = aClass.Attributes.GetAt(AttrID) + Select Case anAttribute.ExportControl + Case rsPublicAccess + PublicAttributes.Add anAttribute + Case rsProtectedAccess + ProtectedAttributes.Add anAttribute + Case rsPrivateAccess + PrivateAttributes.Add anAttribute + End Select + Next AttrID + WordInsertHeading HeadingNumber, aClass.Name & " Attributes", WordApp + GenerateClassAttributeAccessGroup WordApp, PublicAttributes, HeadingNumber+1 + If Not ReportOptions.PublicOnly Then + GenerateClassAttributeAccessGroup WordApp, ProtectedAttributes, HeadingNumber+1 + GenerateClassAttributeAccessGroup WordApp, PrivateAttributes, HeadingNumber+1 + End If + End If +End Sub + +'------------------------------------------------------------------------------ +' +' So here we go, doing the same with operations as we did with attributes. +' +Function GenerateParameter (aParameter As Parameter) As String + Code$ = aParameter.Name + ":" + aParameter.Type + GenerateParameter = Code$ +End Function + +Sub GenerateOperation(WordApp As Object, anOperation As Operation, HeadingNumber As Integer) + Dim theOperation As String + + If ReportOptions.CppSyntax Then + Select Case anOperation.ExportControl + Case rsPublicAccess + theOperation = "Public: " + Case rsProtectedAccess + theOperation = "Protected: " + Case rsPrivateAccess + theOperation = "Private: " + End Select + End If + + theOperation = theOperation + anOperation.Name + + If ReportOptions.CppSyntax Then + Params$ = "" + If anOperation.Parameters.Count Then + For OperID = 1 To anOperation.Parameters.Count - 1 + Params$ = Params$ + GenerateParameter(anOperation.Parameters.GetAt(OperID)) + Params$ = Params$ + ", " + Next OperID + Params$ = Params$ + GenerateParameter(anOperation.Parameters.GetAt(anOperation.Parameters.Count)) + End If + theOperation = theOperation & "( " & Params$ & ")" + End If + WordInsertHeading HeadingNumber, theOperation, WordApp + WordInsertDocumentation HeadingNumber+1, anOperation.Documentation, WordApp + If ReportOptions.VerifyType = RepVerifyEmbed Then + GenerateMethodUsageEntry anOperation, WordApp + End If + +End Sub + +Sub GenerateClassOperationAccessGroup(WordApp As Object, attColl As OperationCollection, HeadingNumber As Integer) + If attColl.Count Then + For AttrID = 1 To attColl.Count + GenerateOperation WordApp, attColl.GetAt(AttrID), HeadingNumber + Next AttrID + End If +End Sub + + +Sub GenerateClassOperations(WordApp As Object, aClass As Class, HeadingNumber As Integer) + Dim PublicOperations As New OperationCollection + Dim ProtectedOperations As New OperationCollection + Dim PrivateOperations As New OperationCollection + Dim anOperation As Operation + + WordApp.FormatStyle "Normal" + If ReportOptions.VerifyType = RepVerifyEmbed Then + Para WordApp + WordApp.FormatFont Bold:=True + WordApp.Insert aClass.Name + WordApp.FormatFont Bold:=False + + If aClass.Operations.Count = 0 Then + WordApp.Insert " has no operations defined in this model." + 'Para WordApp + Else + WordApp.Insert " has " + WordApp.Insert CStr(aClass.Operations.Count) + WordApp.Insert " operations defined in this model:" + 'Para WordApp + End If + End If + If aClass.Operations.Count <> 0 Then + For OperID = 1 To aClass.Operations.Count + Set anOperation = aClass.Operations.GetAt(OperID) + Select Case anOperation.ExportControl + Case rsPublicAccess + PublicOperations.Add anOperation + Case rsProtectedAccess + ProtectedOperations.Add anOperation + Case rsPrivateAccess + PrivateOperations.Add anOperation + End Select + Next OperID + 'WordInsertHeading HeadingNumber, aClass.Name & " Operations", WordApp + GenerateClassOperationAccessGroup WordApp, PublicOperations, HeadingNumber + If Not ReportOptions.PublicOnly Then + GenerateClassOperationAccessGroup WordApp, ProtectedOperations, HeadingNumber + GenerateClassOperationAccessGroup WordApp, PrivateOperations, HeadingNumber + End If + End If +End Sub + +'------------------------------------------------------------------------------ + + +Sub GenerateTheClassBody(WordApp As Object, aClass As Class, HeadingNumber As Integer) + WordInsertDocumentation HeadingNumber+1, aClass.Documentation, WordApp + If aClass.Persistence Then + WordApp.Insert "Persistent Class" + Para WordApp + End If + + Dim SuperClasses As ClassCollection + Dim theSuperClass As Class + Set SuperClasses = aClass.GetSuperClasses + If SuperClasses.Count Then + ClassList$ = "" + For CLSID = 1 To SuperClasses.Count + Set theSuperClass = SuperClasses.GetAt(CLSID) + If ClassList$ <> "" Then + ClassList$ = ClassList$ & ", " + End If + ClassList$ = ClassList$ & theSuperClass.Name + Next CLSID + WordApp.Insert "Derived from " & ClassList$ + Para WordApp + End If + + GenerateClassAttributes WordApp, aClass, HeadingNumber+1 + GenerateClassOperations WordApp, aClass, HeadingNumber+1 +End Sub +' +' For each class in the category +' +Sub GenerateLogicalClass(WordApp As Object, aClass As Class, HeadingNumber As Integer) + On Error Resume Next + + WordInsertHeading HeadingNumber, aClass.Name, WordApp + GenerateTheClassBody WordApp, aClass, HeadingNumber +End Sub + +Sub PrintClassesForCategory (WordApp As Object, aCategory As Category, HeadingNumber As Integer, myAlpha() As String) + Dim lastNoNameClassIndex As Integer + Dim theCatClassCollection As ClassCollection + Set theCatClassCollection = GetAllOfClasses(aCategory) + + If theCatClassCollection.Count Then + Dim theClass As Class + Dim NestedClasses As ClassCollection + + For CLSID = 1 To theCatClassCollection.Count + If(myAlpha(CLSID) = "") Then + If (lastNoNameClassIndex = 0) Then + Ike = theCatClassCollection.FindFirst("") + lastNoNameClassIndex = Ike + Else + Ike = theCatClassCollection.FindNext(lastNoNameClassIndex,"") + lastNoNameClassIndex = Ike + End If + Else + Ike = theCatClassCollection.FindFirst(myAlpha(CLSID)) + End If + Set theClass = theCatClassCollection.GetAt(Ike) + GenerateLogicalClass WordApp, theClass, HeadingNumber+1 + Next CLSID + End If + Set theClassCollection = Nothing +End Sub + + +Sub PrintCategoryClasses(WordApp As Object, aCategory As Category, HeadingNumber As Integer) + Dim Alpha() As String + Dim theCatClassCollection As ClassCollection + + If HeadingNumber > 1 Then + WordInsertHeading HeadingNumber, aCategory.Name, WordApp + End If + WordInsertDocumentation HeadingNumber+1, aCategory.Documentation, WordApp + + Set theCatClassCollection = GetAllOfClasses(aCategory) + ReDim Alpha(theCatClassCollection.Count) + SortAlpha aCategory, alpha + + If ReportOptions.ClassDiagrams Then + SearchForClassDiagramsInPackage WordApp, aCategory, (HeadingNumber+1) + End If + + If ReportOptions.StateDiagrams Then + SearchForStateDiagramsInPackage WordApp, aCategory, (HeadingNumber+1) + End If + + If ReportOptions.UseCaseDiagrams Then + SearchForUseCaseDiagramsInPackage WordApp, aCategory, (HeadingNumber+1) + End If + + If ReportOptions.ScenarioDiagrams Then + SearchForSeqAndCollabDiagramsInPackage WordApp, aCategory, (HeadingNumber+1) + End If + + 'PrintClassesForCategory WordApp, aCategory, HeadingNumber, Alpha + +End Sub + +Sub GenerateUseCase (WordApp As Object, aUseCase As UseCase, HeadingNumber As Integer) + WordInsertHeading HeadingNumber, aUseCase.Name, WordApp + WordInsertDocumentation HeadingNumber+1, aUseCase.Documentation, WordApp + If ReportOptions.ClassDiagrams Then + SearchForClassDiagramsInUseCase WordApp, aUseCase, (HeadingNumber+1) + End If + If ReportOptions.ScenarioDiagrams Then + SearchForSeqAndCollabDiagramsInUseCase WordApp, aUseCase, (HeadingNumber+1) + End If +End Sub + +Sub PrintCategoryUseCases(WordApp As Object, aCategory As Category, HeadingNumber As Integer) + Dim Alpha() As String + Dim theCatClassCollection As ClassCollection + + If HeadingNumber > 1 Then + WordInsertHeading HeadingNumber, aCategory.Name, WordApp + End If + WordInsertDocumentation HeadingNumber+1, aCategory.Documentation, WordApp + + SearchForClassDiagramsInPackage WordApp, aCategory, (HeadingNumber+1) + SearchForStateDiagramsInPackage WordApp, aCategory, (HeadingNumber+1) + SearchForUseCaseDiagramsInPackage WordApp, aCategory, (HeadingNumber+1) + SearchForSeqAndCollabDiagramsInPackage WordApp, aCategory, (HeadingNumber+1) + + If aCategory.UseCases.Count Then + Dim theUseCase As UseCase + Dim numberOfApplicableUseCases As Integer + Dim UseCaseNames$() + numberOfApplicableUseCases = 0 + For ucID = 1 To aCategory.UseCases.Count + Set theUseCase = aCategory.UseCases.GetAt(ucID) + ReDim Preserve UseCaseNames$(numberOfApplicableUseCases +1) + UseCaseNames$(numberOfApplicableUseCases) = theUseCase.Name + numberOfApplicableUseCases = numberOfApplicableUseCases +1 + Next ucID + + ArraySort UseCaseNames$() + + For i% = 1 To numberOfApplicableUseCases + ucID = aCategory.UseCases.FindFirst(UseCaseNames$(i%)) + Set theUseCase = aCategory.UseCases.GetAt(ucID) + If theUseCase Is Nothing Then + Else + GenerateUseCase WordApp, theUseCase, (HeadingNumber +1) + End If + Next i% + End If + +End Sub + + +Sub PrintCategory(WordApp As Object, aCategory As Category, HeadingNumber As Integer) + Dim Beta() As String + If aCategory.Name <> "Undocument" Then + Select Case GeneratorState.Phase + Case RPh_Dynamic + If HeadingNumber = 1 Then + WordInsertHeading HeadingNumber, "Analysis", WordApp + End If + Call PrintCategoryUseCases(WordApp, aCategory, HeadingNumber) + Call PrintCategoryClasses(WordApp, aCategory, HeadingNumber) + Case RPh_Static + If HeadingNumber = 1 Then + WordInsertHeading HeadingNumber, "Design", WordApp + End If + Call PrintCategoryClasses(WordApp, aCategory, HeadingNumber) + Case RPh_StartUp + Case RPh_TailBoiler + Case RPh_Crosscheck + End Select + ReDim Beta(aCategory.Categories.Count) + For Ike = 1 To aCategory.Categories.Count + Beta(Ike) = aCategory.Categories.GetAt(Ike).Name + Next Ike + ArraySort Beta + For CatID = 1 To aCategory.Categories.Count + Ike = aCategory.Categories.FindFirst(Beta(CatID)) + Call PrintCategory(WordApp, aCategory.Categories.GetAt(Ike), HeadingNumber+1) + Next CatID + End If +End Sub + +Sub GenerateBehaviouralAnalysisSection(WordApp As Object) + Break WordApp + 'WordInsertHeading 1, "Behavioural Analysis", WordApp + GeneratorState.Phase = RPh_Dynamic + PrintCategory WordApp, LicensedRoseApplication.CurrentModel.RootUseCaseCategory, 1 +End Sub + +Sub GenerateStaticRelationshipSection(WordApp As Object) + Break WordApp + 'WordInsertHeading 1, "Static Relationships", WordApp + GeneratorState.Phase = RPh_Static + PrintCategory WordApp, LicensedRoseApplication.CurrentModel.RootCategory, 1 +End Sub + + +Sub GenerateMethodUsageEntry(Op As Operation, WordApp As Object) + ResetGlobalDiagList + Dim Mc As MessageCollection + Dim Used As Boolean + Used = False + WordApp.FormatStyle "Normal" + For i% = 0 To GlobalDiagListSize-1 + Set Mc = GlobalDiagList(i).Diagram.GetMessages + For j% = 1 To Mc.Count + If Mc.GetAt(j).GetOperation Is Not Nothing Then + If Mc.GetAt(j).GetOperation.GetUniqueId = Op.GetUniqueId Then + Used = True + If GlobalDiagList(i).SeenBefore = False Then + WordApp.Insert "Used in " + WordApp.Insert GlobalDiagList(i).FigureTitle + Para WordApp + GlobalDiagList(i).SeenBefore = True + End If + End If + End If + Next j + Next i + If Used = False Then + WordApp.Insert "Not used in any Sequence or Collaboration in this view of the model." + Para WordApp + End If +End Sub + +Sub GenerateScenarioCrosscheckSection(WordApp As Object) + Break WordApp + GeneratorState.Phase = RPh_Crosscheck + + WordInsertHeading 1, "Model Verification and Checking", WordApp + + Dim AllClasses As ClassCollection + Dim Op2 As Operation + Dim Ops As OperationCollection + Dim Used As Boolean + Set AllClasses = LicensedRoseApplication.CurrentModel.GetAllClasses + + For i% = 1 To AllClasses.Count + Dim UsedClassOps As New OperationCollection + Dim UnusedClassOps As New OperationCollection + WordInsertHeading 2,AllClasses.GetAt(i).Name,WordApp + + Set Ops = AllClasses.GetAt(i).Operations + For j% = 1 To Ops.Count + Set Op2 = Ops.GetAt(j) + WordApp.FormatFont Bold:=True + WordApp.Insert Op2.Name + WordApp.FormatFont Bold:=False + Para WordApp + GenerateMethodUsageEntry Op2, WordApp + Next j + Next i +End Sub + +Sub GenerateTailEndBoilerPlate(WordApp As Object) + GeneratorState.Phase = RPh_TailBoiler + Break WordApp + WordInsertHeading 1, "Further Information", WordApp + WordInsertHeading 2, "People", WordApp + WordInsertHeading 2, "References", WordApp + WordInsertHeading 2, "Open Issues", WordApp + WordInsertHeading 2, "Glossary", WordApp + WordInsertHeading 2, "Document History", WordApp + WordInsertHeading 2, "Document Review Date", WordApp +End Sub + +Sub GenerateReport(WordApp As Object) +Dim UsedOperations As New OperationCollection + WordApp.EndOfDocument + If ReportOptions.FEBoiler = True Then + WordInsertHeading 1, "Introduction", WordApp + WordInsertHeading 2, "Overview", WordApp + WordInsertHeading 2, "Purpose and Scope", WordApp + End If + + Select Case ReportOptions.DocType + Case RepAnalysisType + GenerateBehaviouralAnalysisSection WordApp + Case RepDesignType + GenerateStaticRelationshipSection WordApp + Case RepAnalysisNDesignType + GenerateBehaviouralAnalysisSection WordApp + GenerateStaticRelationshipSection WordApp + Case RepTestType + End Select + + If ReportOptions.VerifyType = RepVerifySection Then + GenerateScenarioCrosscheckSection WordApp + End If + + If ReportOptions.BEBoiler = True Then + GenerateTailEndBoilerPlate WordApp + End If +End Sub + +Begin Dialog ReportDialog ,,224,320,"Generate Symbian Documentation",.ReportDialogLoop + + Text 8,4,148,8,"Report &Title",.TitleText + TextBox 12,16,202,12,.Title + + Text 8,32,112,8,"&Template File Name:",.TemplateFileNameText + TextBox 12,44,202,12,.TemplateFileName + + Text 8,60,112,8,"&Report File Name:",.FileNameText + TextBox 12,72,202,12,.FileName + + PushButton 174,87,44,14,"Browse",.Browse + + GroupBox 8,102,92,60,"Report Document Type",.ReportTypeGroup + OptionGroup .ReportType + OptionButton 12,114,80,8,"Analysis",.AnalysisReport + OptionButton 12,126,80,8,"Design",.DesignReport + OptionButton 12,138,80,8,"Analysis and Design",.AnalysisNDesignReport + OptionButton 12,150,80,8,"Test",.TestReport + + GroupBox 102,102,116,60,"Usage Verification",.VerifyTypeGroup + OptionGroup .VerifyType + OptionButton 106,114,80,8,"None",.NoVerify + OptionButton 106,126,80,8,"Added Section",.SectionVerify + OptionButton 106,138,80,8,"Embedded in Text",.EmbedVerify + + GroupBox 8,170,212,30,"Proofreading Options",.Proofing + CheckBox 12,182,92,8,"Expanded Whitespace",.WhiteBlock + CheckBox 106,182,92,8,"Highlight Gaps",.HighlightDocGaps + + GroupBox 8,205,212,80,"Content Options",.Content + CheckBox 12,220,92,8,"Class Diagrams",.ClassDiagrams + CheckBox 12,232,92,8,"Scenario Diagrams",.ScenarioDiagrams + CheckBox 12,244,92,8,"State Diagrams",.StateDiagrams + CheckBox 12,256,92,8,"Use Case Diagrams",.UseCaseDiagrams + CheckBox 12,268,92,8,"C++ Syntax",.CppSyntax + + CheckBox 106,220,92,8,"Public Items Only",.PublicOnly + CheckBox 106,232,92,8,"Front-end Boilerplate",.FEBoiler + CheckBox 106,244,92,8,"Back-end Boilerplate",.BEBoiler + CheckBox 106,256,92,8,"Use Subhead",.SubTag + + PushButton 8,292,76,14,"&Generate",.Generate + CancelButton 144,292,76,14 +End Dialog + + +Sub Main + Dim MyDialog As ReportDialog + + Set LicensedRoseApplication = GetLicensedRoseApplication() + LicensedRoseApplication.CurrentModel.DefaultTool = DefaultTool$ + 'NewDirectory$ = EnclosingDirPath(LicensedRoseApplication.ApplicationPath) + NewDirectory$ = CurDir$ + + If NewDirectory$ <> "" Then + If Mid$(NewDirectory$, 2, 1) = ":" Then + ChDrive NewDirectory$ + End If + ChDir NewDirectory$ + Else + MsgBox "Error: Directory not found." + Exit Sub + End If + + ' + ' Right, let's set some sensible default values + ' + DefaultFileName$ = GetResourceString(PRODUCTDEFAULTWORDDOCFILENAME) + ModelName$ = LicensedRoseApplication.CurrentModel.GetFileName() + If ModelName$ = "" Then + MyDialog.FileName$ = MakeFileName$(NewDirectory$, DefaultFileName$) + MyDialog.Title$ = FileParse$(DefaultFileName, 4) + Else + MyDialog.FileName$ = ChangeFileExtension$(ModelName$, "doc") + MyDialog.Title$ = FileParse$(ModelName$, 4) + End If + MyDialog.TemplateFileName$ = ChangeFileExtension$(ModelName$, "dot") + ' + ' Let's assume we're not proofreading at the moment + ' + MyDialog.WhiteBlock = False + MyDialog.HighlightDocGaps = False + ' + ' I think we want all the diagrams we can get + ' + MyDialog.ClassDiagrams = True + MyDialog.ScenarioDiagrams = True + MyDialog.StateDiagrams = True + MyDialog.UseCaseDiagrams = True + ' + ' We are a C++ shop, after all + ' + MyDialog.CppSyntax = True + ' + ' We can see everything for now + ' + MyDialog.PublicOnly = False + ' + ' The options to generate boilerplate and tagged headings are turned off + ' + MyDialog.FEBoiler = False + MyDialog.BEBoiler = False + MyDialog.SubTag = False + ' + ' Let's assume that we want to run across the entire model for the time being + ' + MyDialog.ReportType = RepAnalysisNDesignType + ' + ' The default is to verify in the body of the document + ' + MyDialog.VerifyType = RepVerifyEmbed + + ' + ' Right let's give the user a chance to set some preferences, in case + ' they differ from these eminently sensible ones. + ' + Result = Dialog (MyDialog) + If Result = 0 Then + Exit Sub + End If + ' + ' I suppose that if we give them the UI to change them, we ought to actually + ' take notice of them + ' + If Result = 2 Then + ReportOptions.Generate = TRUE + ReportOptions.Title = MyDialog.Title + ReportOptions.FileName = MyDialog.FileName + ReportOptions.Template = MyDialog.TemplateFileName + ReportOptions.WhiteBlock = MyDialog.WhiteBlock + ReportOptions.HighlightDocGaps = MyDialog.HighlightDocGaps + ReportOptions.ClassDiagrams = MyDialog.ClassDiagrams + ReportOptions.ScenarioDiagrams = MyDialog.ScenarioDiagrams + ReportOptions.StateDiagrams = MyDialog.StateDiagrams + ReportOptions.UseCaseDiagrams = MyDialog.UseCaseDiagrams + ReportOptions.CppSyntax = MyDialog.CppSyntax + ReportOptions.PublicOnly = MyDialog.PublicOnly + ReportOptions.FEBoiler = MyDialog.FEBoiler + ReportOptions.BEBoiler = MyDialog.BEBoiler + ReportOptions.SupportSubheadingTags = MyDialog.SubTag + + ReportOptions.DocType = MyDialog.ReportType + ReportOptions.VerifyType = MyDialog.VerifyType + + GeneratorState.Phase = RPh_StartUp + RoseAppDirectory$ = EnclosingDirPath(LicensedRoseApplication.ApplicationPath) + If Not FileExists (ReportOptions.Template) Then + ReportOptions.Template = RoseAppDirectory$ &"\Formal.dot" + If Not FileExists (ReportOptions.Template) Then + MsgBox "Error: Missing file [" & ReportOptions.Template & "]" + Exit Sub + End If + End If + End If + + ' + ' Crack open MS Word then + ' + Dim WordApplication As Object + Dim WordApp As Object + WordUtilInit + + Set WordApplication = CreateObject("Word.Application") + + ' + ' This is a very lazy thing to do, and difficult to obtain + ' documentation on now that Micro$oft have deprecated the interface + ' + Set WordApp = WordApplication.WordBasic + ' + ' But it makes some parts of life so easy + ' + WordApp.AppMaximize + ' + ' Create a new document based on our template + ' + WordApp.FileNew ReportOptions.Template + ' + ' Rush to the end of the new document + ' + WordApp.EndOfDocument + ' + ' Generate the filling + ' + GenerateReport(WordApp) + ' + ' Finalise the Table of Contents + ' + WordApp.EditSelectAll + WordApp.UpdateFields + ' + ' Save it all away + ' + WordApp.FileSaveAs ReportOptions.FileName + ' + ' Night night + ' + WordApp.FileExit + +End Sub