Open API Examples

Hi Team,

Please can someone point me to code examples ( open API code ) of how to do the following

  1. generate Table of Contents - the following didn’t work for me

IRDTableOfContentsTemplate currentRDTableOfContentsTemplate = reportDiagramDetails.createRDTableOfContentsTemplate();
reportDiagramDetails.addRDTableOfContentsTemplate(currentRDTableOfContentsTemplate);

… this comes of course before applying all the templates via code in statements after this. Good to have -> would be good if this auto updates as well when rendering.

  1. Apply a base word doc template ( how to specify the path to this i.e. from the ones we have in Doc Composer -> Manage Templates ), so that it can include all styling and cover page from that base word doc template. The following didn’t apply to the IReportDiagramDetails.

reportDiagramDetails.setDocBasePath(“MyPageTemplate.docx”);

Would this pick up this word doc template from the Doc Composer > Manage Doc templates that we uploaded.

Maybe this would work after I use the following

ApplicationManager.instance().getDocumentationManager().generateDocComposerWord(lDoc, lOutput, myComponent )

  1. Write revision history ( of ArchiMate Diagram ) either via the Open API code or via the XML template that I can include via Open API as a IRDOOTemplate

  2. Pass a value from Open API Code to inside a XML Template ( applied by IRDOOTemplate )

  3. Pass a value from Open API Code to Word Doc Base Template e.g. ${TEXT, ”departmentName”} in word doc base template

  4. Write version of Doc Composer - Doc Template and XML Templates

  5. Specify page orientation for each IRDOOTemplate or in general - Portrait/ Landscape

Your help is much appreciated, thanks.

1.
You may update the TOC after you updated the content of your document.

IReportDiagramUIModel document = ...;
DocumentationManager docManager = ApplicationManager.instance().getDocumentationManager();
docManager.updateRDTableOfContentsTemplates(document);

2.

IReportDiagramDetails documentDetails = ...;
documentDetails.getReportDiagramOption().setWordDocumnentTemplatePath(...); // fyi: sorry for typo on this function name: documnent
documentDetails.getReportDiagramOption().setUseWordDocumnentTemplate(true);

fyi: setDocBasePath(…) is used for Fill-in document


Sorry, may I ask you a question first.
When I read your question 5, the ${TEXT, ...} is used in Fill-in Doc.
As screenshot, are you using Fill-in Doc?


If in Fill-in doc, you should not need to ask question 2, because your document must be generated based on your predefined .docx.


3.
Sorry, the content of the revision history comes from where?

  • Teamwork project commit?
  • ArchiMate diagram’s comments?
    etc…?

4.
Sorry, it is not supported. But you may use GenericModel to define your ‘variables’ and generate them into your document:

6.
Sorry, what is ‘version’ of Doc Composer? (similar to question 3?)

7.
It is the page setting in section(s)

  • in General:
IReportDiagramDetails documentDetails = ...;
documentDetails.getReportDiagramOption().getDefaultSection().getPageInfo().setPortrait(false);
  • per template:
    inserting a Section-Break into the document, to let coming template(s) showing in its page setting
IRDSectionTemplate sectionTemplate = documentDetails.createRDSectionTemplate();
sectionTemplate.setPageInfo(sectionTemplate.createReportPageInfo());
sectionTemplate.getPageInfo().setPortrait(false);
documentDetails.addTemplate(sectionTemplate);

Thanks Peter.

2.
Sorry, may I ask you a question first.
When I read your question 5 , the ${TEXT, ...} is used in Fill-in Doc.
LN: I am using Fill In Doc that I want to apply as a DocBasePath - how do i specify its path ( don’t want to specify a local path but VP Path - I can pick up from workspace location I guess - ApplicationManager.instance().getWorkspaceLocation() ) & how do i pass the value of departmentName from Open API based on users input

3.
Sorry, the content of the revision history comes from where?
LN: ArchiMate Projects commit history

6.
Sorry, what is ‘version’ of Doc Composer? (similar to question 3?)
LN: The version of the word doc base template applied via DocBasePath

Sorry for late reply

Sorry about that, we didn’t aware user may create a blank new document via OpenAPI. We need to spend some time on enhance it.

At this moment, I may provide a simple sample to answer the Q2, Q5 first.
sample DocBase: MyDocBase.docx (252.9 KB)


			String lDocBasePath = ...;//"MyDocBase.docx";
			File lOutput = ...;
			
			
			DiagramManager lDiagramManager = ApplicationManager.instance().getDiagramManager();
			IProject lProject = ApplicationManager.instance().getProjectManager().getProject();
			
			IReportDiagramDetailsContainer lDocDetailsContainer;
			{
				IModelElement[] lElements = lProject.toAllLevelModelElementArray(IModelElementFactory.MODEL_TYPE_REPORT_DIAGRAM_DETAILS_CONTAINER);
				if (lElements == null || lElements.length == 0) {
					lDocDetailsContainer = IModelElementFactory.instance().createReportDiagramDetailsContainer();
				}
				else {
					lDocDetailsContainer = (IReportDiagramDetailsContainer) lElements[0];
				}
			}
			
			
			IReportDiagramUIModel lDocument = (IReportDiagramUIModel) lDiagramManager.createDiagram(IDiagramTypeConstants.DIAGRAM_TYPE_REPORT_DIAGRAM);
			IReportDiagramDetails lDocDetails = lDocDetailsContainer.createReportDiagramDetails();
			lDocument.setGenericXMLElementAddress(lDocDetails.getAddress());
			
			// Q2. set it is Fill-In Doc, and DocBasePath.
			lDocDetails.setFillInDoc(true);
			lDocDetails.setDocBasePath(lDocBasePath);
			
			
			/*
			 * Sorry, this .version is internal used (we didn't aware user will create a blank new IReportDiagramUIModel via OpenAPI)
			 * Please hardcode the follow "20150413" and don't modify it.
			 */
			lDocDetails.setVersion("20150413");
			
			
			
			// Q5. specify ${TEXT, ...} value.
			// my doc base defined a "Text-1" ${TEXT, Text-1}
			IFIText lText = lDocDetails.getFITextByName("Text-1");
			if (lText == null) {
				lText = lDocDetails.createFIText();
				lText.setName("Text-1");
				lDocDetails.addFiField(lText);
				/*
				 * the IFIText is referenced by ReportDiagramDetails in both .children + .fiFields properties
				 * .getFITextByName(...) & .createFIText(...) working on .children property
				 * .addFiField(...) working on .fiFields property
				 */
			}
			IFITextInstance lTextInstance; // the value of ${TEXT, ...} is specified in TextInstance, on this case, this ${TEXT, ...} should have 1 instance only.
			if (lText.instanceCount() == 0) {
				lTextInstance = IModelElementFactory.instance().createFITextInstance();
				lText.addInstance(lTextInstance);
			}
			else {
				lTextInstance = lText.getInstanceByIndex(0);
			}
			lTextInstance.setNickDescription("Hello World");
			lTextInstance.setNickHTMLDescription("<html><body>Hello World</body></html>");
			
			
			
			lDiagramManager.openDiagram(lDocument);
			
			// TODO
			/*
			 * Sorry, this function is only available to generate word document for Non Fill-In Doc.
			 * We will enhance to support generating Fill-In Doc. Please wait.
			 */  
			ApplicationManager.instance().getDocumentationManager().generateDocComposerWord(lDocument, lOutput, null);

On the above sample code, a Fill-In Doc can be created with “Hello World” text specified.
You can generate the .docx via Fill-In Doc’s Generate/Preview button
But cannot generate via OpenAPI’s DocumentManager.generateDocComposerWord(...) function.

We will post here if the enhancement is ready. Please wait…

Hi Peter, thanks again for the help.

It would be great to have a feature that supports passing variable values gathered from end user via a dialog for example and then added to the cover page/ document information page - using Open API’s DocumentManager.generateDocComposerWord(…) function.That would be extremely useful for us.

Waiting :).

Sample DocBase:
MyDocBase.docx (254.1 KB)

Sample TemplateXML:

Sample OpenAPI Code:

			String lDocBasePath = ...;//"MyDocBase.docx";
			File lOutput = ...;
			
			
			DiagramManager lDiagramManager = ApplicationManager.instance().getDiagramManager();
			DocumentationManager lDocManager = ApplicationManager.instance().getDocumentationManager();
			IProject lProject = ApplicationManager.instance().getProjectManager().getProject();
			
			// on this demo, assume the Project has a "Transition Architectures" archimate diagram. This ArchiMate diagram will be generated into document.
			IArchiMateDiagramUIModel lArchiMateDiagram = null; // assume not null
			for (IDiagramUIModel lDiagram : lProject.toDiagramArray()) {
				if (lDiagram instanceof IArchiMateDiagramUIModel && "Transition Architectures".equals(lDiagram.getName())) {
					lArchiMateDiagram = (IArchiMateDiagramUIModel) lDiagram;
				}
			}
			
			IReportDiagramDetailsContainer lDocDetailsContainer;
			{
				IModelElement[] lElements = lProject.toAllLevelModelElementArray(IModelElementFactory.MODEL_TYPE_REPORT_DIAGRAM_DETAILS_CONTAINER);
				if (lElements == null || lElements.length == 0) {
					lDocDetailsContainer = IModelElementFactory.instance().createReportDiagramDetailsContainer();
				}
				else {
					lDocDetailsContainer = (IReportDiagramDetailsContainer) lElements[0];
				}
			}
			
			
			IReportDiagramUIModel lDocument = (IReportDiagramUIModel) lDiagramManager.createDiagram(IDiagramTypeConstants.DIAGRAM_TYPE_REPORT_DIAGRAM);
			IReportDiagramDetails lDocDetails = lDocDetailsContainer.createReportDiagramDetails();
			lDocument.setGenericXMLElementAddress(lDocDetails.getAddress());
			
			// Q2. set it is Fill-In Doc, and DocBasePath.
			lDocDetails.setFillInDoc(true);
			lDocDetails.setDocBasePath(lDocBasePath);
			
			
			/*
			 * Sorry, this .version is internal used (we didn't aware user will create a blank new IReportDiagramUIModel via OpenAPI)
			 * Please hardcode the follow "20150413" and don't modify it.
			 */
			lDocDetails.setVersion("20150413");
			if (lDocDetails.rDNumberingSettingCount() == 0) {
				lDocDetails.createRDNumberingSetting();
			}
			lDocManager.initDefaultRDNumberingSetting(lDocDetails.getRDNumberingSettingByIndex(0));
			if (lDocDetails.rDStyleRepositoryCount() == 0) {
				lDocDetails.createRDStyleRepository();
			}
			lDocManager.initDefaultRDStyleRepository(lDocDetails.getRDStyleRepositoryByIndex(0));
			
			

			// Q6. Commit History of this document
			{
				/*
				 * ${PROJECT, Document Revisions}
				 * 
				 * "Document Revisions" is my customized TemplateXML
				 */
				IRDTemplateVariable lRevDiffScopeVar = IModelElementFactory.instance().createRDTemplateVariable();
				lRevDiffScopeVar.setName("${Doc.RevDiff.scope}"); // this name was specified in TemplateXML
				lRevDiffScopeVar.setKind(IRDTemplateVariable.KIND_REV_DIFF_SCOPE);
				IRDRevDiffScope lRevDiffScope = IModelElementFactory.instance().createRDRevDiffScope();
				lRevDiffScopeVar.setRevDiffScope(lRevDiffScope);
				lRevDiffScope.setBranchName("trunk");
				lRevDiffScope.setFromRev(1);
				lDocDetails.addVariable(lRevDiffScopeVar);
			}
			
			
			// Q5. specify ${TEXT, ...} value.
			{
				// ${TEXT, Text-1}
				IFIText lText = lDocDetails.getFITextByName("Text-1");
				if (lText == null) {
					lText = lDocDetails.createFIText();
					lText.setName("Text-1");
					lDocDetails.addFiField(lText);
					/*
					 * the IFIText is referenced by ReportDiagramDetails in both .children + .fiFields properties
					 * .getFITextByName(...) & .createFIText(...) working on .children property
					 * .addFiField(...) working on .fiFields property
					 */
				}
				IFITextInstance lTextInstance; // the value of ${TEXT, ...} is specified in TextInstance, on this case, this ${TEXT, ...} should have 1 instance only.
				if (lText.instanceCount() == 0) {
					lTextInstance = IModelElementFactory.instance().createFITextInstance();
					lText.addInstance(lTextInstance);
				}
				else {
					lTextInstance = lText.getInstanceByIndex(0);
				}
				lTextInstance.setNickDescription("Hello World");
				lTextInstance.setNickHTMLDescription("<html><body>Hello World</body></html>");
			}
			
			{
				// ${DIAGRAM, Main ArchiMate, ArchiMateDiagram, One, My TemplateXML with Variable}
				IFIDiagram lMainArchiMate = lDocDetails.getFIDiagramByName("Main ArchiMate");
				if (lMainArchiMate == null) {
					lMainArchiMate = lDocDetails.createFIDiagram();
					lMainArchiMate.setName("Main ArchiMate");
					lDocDetails.addFiField(lMainArchiMate);
				}
				/*
				 * if "One" or "Any" is specified, specify the .selectedDiagramAddresses
				 * else if "LoopInElement" is specified, specify the .selectedLoopInElement
				 */
				// 
				lMainArchiMate.setSelectedDiagramAddresses(new String[] {lArchiMateDiagram.getId()});
				
				
				// Q4. specify variable for the IRDOOTemplate.
				{
					/*
					 * in Fill-in Doc, there is no instance of IRDOOTemplate; The variables can be specified in
					 * If the TemplateXML is generated for ${DIAGRAM, ...}, or ${ELEMENT, ...}
					 * the variable can be specified in IFIDiagram, or IFIElement
					 */
					IRDTemplateVariable lLookupModelTypeVar = IModelElementFactory.instance().createRDTemplateVariable();
					lLookupModelTypeVar.setName("${lookupModelType}");
					lLookupModelTypeVar.setKind(IRDTemplateVariable.KIND_NORMAL);
					lLookupModelTypeVar.setFollowGlobal(false);
					lLookupModelTypeVar.setValue(IModelElementFactory.MODEL_TYPE_ARCHI_MATE_GAP);
					lMainArchiMate.addVariable(lLookupModelTypeVar);
				}
				

				// Q3. Commit History of the ArchiMate diagram
				{
					/*
					 * "Revision Differences" is a predefined TemplateXML, use <RevDiff scope=${...}> used to generate the 'changes' in your revisions.
					 * <RevDiff> .scope is a variable, allows you to specify the scope of the changes.
					 * On the following case, I will show my "Transition Architectures" archimate diagram's changes from revision '3' to current revision.
					 */
					IRDTemplateVariable lRevDiffScopeVar = IModelElementFactory.instance().createRDTemplateVariable();
					lRevDiffScopeVar.setName("${Diagram.RevDiff.scope}"); // this name was specified in TemplateXML
					lRevDiffScopeVar.setKind(IRDTemplateVariable.KIND_REV_DIFF_SCOPE);
					lRevDiffScopeVar.setFollowGlobal(false);
					IRDRevDiffScope lRevDiffScope = IModelElementFactory.instance().createRDRevDiffScope();
					lRevDiffScopeVar.setRevDiffScope(lRevDiffScope);
					lRevDiffScope.setBranchName("trunk");
					lRevDiffScope.setFromRev(3);
					lRevDiffScope.setScopeType(IRDRevDiffScope.SCOPE_TYPE_DIAGRAM);
					lRevDiffScope.setScopeDiagramIds(new String[] {lArchiMateDiagram.getId()});
					lMainArchiMate.addVariable(lRevDiffScopeVar);
				}
			}
			
			
			
//			lDiagramManager.openDiagram(lDocument);
			  
			lDocManager.generateDocComposerWord(lDocument, lOutput, null);

Q2. Specify DocBase after created IReportDiagramDetails

			// Q2. set it is Fill-In Doc, and DocBasePath.
			lDocDetails.setFillInDoc(true);
			lDocDetails.setDocBasePath(lDocBasePath);

In my DocBase, there are 4 pages.


Q7. Portrait/Landscape
It is handled by sections.
Fill-in Doc does not support insert section via TemplateXML. It is expected to be predefined in your DocBase.
For example, in my DocBase, at the end of 2nd page, specified a Section-Break to let 3rd page can be set to Landscape.
And end of the 3rd page, specified another Section-Break to let 4th page set back to Portrait.

Q5. Specify value of ${TEXT, …}

Q1. Update TOC
Sorry, it is not supported in Fill-in Doc.

Q3. Changes of your ArchiMate Diagrams, and
Q4. Specify Variable of TemplateXML

Q6. The version of the word doc base template applied via DocBasePath
Sorry, I am still not understand.
On above sample code, I wrongly show you how to list the commit history of your project. as following screenshot.


Do you mean you want to specify a ‘version’ into your Doc Base .docx?
If yes, is it just hardcoded in your.docx? (as screenshot)


Please update the software to latest patch build (20200430bg or later), which enhanced

  • DocumentManager.generateDocComposerWord(...) to generate Fill-in Doc
  • set RevDiffScope variable into IReportDiagramDetails for ${PROJECT, …}

Details about update to latest patch can be found at

Hi Peter,

I am on VP 16.1 and patch version ( Build 20200430bi ). In the code below

	Iterator<IReportDiagramDetailsContainer> reportDiagramIterator = 
							project.modelElementIterator( IModelElementFactory.MODEL_TYPE_REPORT_DIAGRAM_DETAILS_CONTAINER );
	
	if (reportDiagramIterator.hasNext()) {
		reportDiagramDetailsContainer = reportDiagramIterator.next();
	} else {
		reportDiagramDetailsContainer = IModelElementFactory.instance().createReportDiagramDetailsContainer();
	}

	reportDiagramUIModel = (IReportDiagramUIModel) diagramManager.createDiagram(IDiagramTypeConstants.DIAGRAM_TYPE_REPORT_DIAGRAM);

	reportDiagramDetails = reportDiagramDetailsContainer.createReportDiagramDetails();
	reportDiagramUIModel.setGenericXMLElementAddress(reportDiagramDetails.getAddress());

	reportDiagramDetails.setDocBasePath("C:\\MyFolder\\MyBaseDoc.docx");
	reportDiagramDetails.setVersion(DOCBASE_VERSION);

	// Add Variables 
	IFIText variable = reportDiagramDetails.getFITextByName("REVIEWER_NAME");
	if (null == variable) {
		variable = reportDiagramDetails.createFIText();
		variable.setName("REVIEWER_NAME");
		reportDiagramDetails.addFiField(variable);
	}
	IFITextInstance lTextInstance;
	if (0 == variable.instanceCount()) {
		lTextInstance = IModelElementFactory.instance().createFITextInstance();
		variable.addInstance(lTextInstance);
	} else {
		lTextInstance = variable.getInstanceByIndex(0);
	}
	lTextInstance.setNickDescription("Mr. X");
	lTextInstance.setNickHTMLDescription("<html><body> Mr. X </body></html>");

	IReportDiagramOption reportDiagramOption = IModelElementFactory.instance().createReportDiagramOption();
	reportDiagramOption.setUseWordDocumnentTemplate(true);
	reportDiagramOption.setWordDocumnentTemplatePath( "C:\\MyFolder\\MyBaseDoc.docx" );
	reportDiagramDetails.setReportDiagramOption(reportDiagramOption);

	IRDSectionTemplate sectionTemplate = reportDiagramDetails.createRDSectionTemplate();
	sectionTemplate.setPageInfo(sectionTemplate.createReportPageInfo());
	sectionTemplate.getPageInfo().setPortrait(false);
	reportDiagramDetails.addRDSectionTemplate(sectionTemplate);		

	IRDOOTemplate currentIRDOOTemplate = reportDiagramDetails.createRDOOTemplate();

	currentIRDOOTemplate.setTemplateURI(templateName);
	currentIRDOOTemplate.setSourceType(1);

	currentIRDOOTemplate.setSourceId(archiMateDiagram.getId());
		
	ICompositeValueSpecification stateValueSpec = IModelElementFactory.instance().createCompositeValueSpecification();
	stateValueSpec.setName(archiMateDiagram.getId());
	stateValueSpec.setValue("Current State");

	currentIRDOOTemplate.addLayerFilter(stateValueSpec);
		
	reportDiagramDetails.addTemplate(currentIRDOOTemplate);
	reportDiagramDetails.addRDPageBreakTemplate(IModelElementFactory.instance().createRDPageBreakTemplate());

	ApplicationManager.instance().getDocumentationManager().generateDocComposerWord(reportDiagramUIModel, new File("C:\\MyFolder\MyGeneratedDocument.docx"), null);

	ApplicationManager.instance().getViewManager().showMessage("Generated at path: C:\\MyFolder\MyGeneratedDocument.docx");

Query 1: The value of REVIEWER_NAME which I am trying to get in my base word template document “C:\\MyFolder\MyBaseDoc.docx” by using ${TEXT, REVIEWER_NAME} is not being received ( rendered ) in the word document.

Query 2: If I set the
reportDiagramDetails.setFillInDoc(true);
the document is not generated by the following line
ApplicationManager.instance().getDocumentationManager().generateDocComposerWord(reportDiagramUIModel, new File(“C:\MyFolder\MyGeneratedDocument.docx”), null);

It just outputs the base doc template MyBaseDoc.docx and does not render the DCTL XML template sections but the variable values are getting properly replaced now for ${TEXT, REVIEWER_NAME}

Query 3: Instead of passing the local path here, can i upload this base word doc template to Doc Composer and specify the path in VP itself instead of “C:\\MyFolder\MyBaseDoc.docx” local path
reportDiagramOption.setWordDocumnentTemplatePath( “C:\MyFolder\MyBaseDoc.docx” );

At a high level , I am trying to do the following

  1. use a base word doc template ( which has all my styles and cover page only - so that it uses styles from here for generated document )
  2. render the rest of the document using existing template DCTL xml code by creating IRDOOTemplate and adding them to IReportDiagramDetailsContainer using the Java Open API code.
  3. Pass some of the values for cover page using a Dialog in Open API and then creating IFIText variables as above

Query 1 & 2:
I tested in 16.1 (20200430bi), seems it works.

Query 3:
Saving your file into your teamwork project’s files/ folder.
then you can specify the relative path.

I cannot comment the code you commented because that is the code that renders all the rest of the sections in my document. Let me explain please.

To Simplify this, the use case is as below

  1. Use Base Word Doc template that already is uploaded to Doc Composer Tools > Doc Composer > Manage Doc Templates > New - and then upload. It serves the purpose of providing a) Styles b) 1st Page i.e. Cover Page c) 2nd Page i.e. Document Information Page ( so I don’t want to do all this via Open API )

     	reportDiagramDetails.setDocBasePath(WORD_DOC_BASE_TEMPLATE_PATH);
    
  2. The 2nd page i.e. the Document Information Page of my generated document should contain information collected by Open API dialog from end user and passed to word doc ${TEXT, REVIEWER_NAME} as a example

     	IFIText variable = reportDiagramDetails.getFITextByName(name);
     	. . .
    
  3. Page 3 onwards of my generated document should render all following sections dynamically based on conditions
    a) Apply templates dynamically based on condition using Open API - Note: templates are chosen based on conditions of user input ( Open API Dialog )

     	IRDOOTemplate currentIRDOOTemplate = reportDiagramDetails.createRDOOTemplate();	
     	currentIRDOOTemplate.setTemplateURI(templateName);
     	currentIRDOOTemplate.setSourceType(1);
     	currentIRDOOTemplate.setSourceId(archiMateDiagram.getId());
    

    b) Apply layer filters dynamically based on condition using Open API - Note: layers are filtered based on conditions of user input ( Open API Dialog )

     	currentIRDOOTemplate.addLayerFilter(conditionalLayer);
    

    reportDiagramDetails.addTemplate(currentIRDOOTemplate);

  4. Generate the document programmatically

     `ApplicationManager.instance().getDocumentationManager().generateDocComposerWord(reportDiagramUIModel, new File(docName), null);`
    
  5. Open it directly automatically in front of user - something like

     	ApplicationManager.instance().getViewManager().showMessage("Generated at path: "+docName);
     	
     	if (Desktop.isDesktopSupported()) {
                 Desktop.getDesktop().open(new File(docName));
     	}

Since you are using Fill-in Doc, the section-break should be predefined in your DocBase .docx,
and your DocBase .docx should contains all your ${TEXT, …}, ${DIAGRAM, …}, etc… for generating the content based on your DocBase.

1 Like

Thanks a lot Peter.