<#--
   ******************************************************
   *
   *                       NOTICE
   *
   *   THIS SOFTWARE IS THE PROPERTY OF AND CONTAINS
   *   CONFIDENTIAL INFORMATION OF INFOR GLOBAL SOLUTIONS
   *   TECHNOLOGY GMBH AND/OR ITS AFFILIATES OR SUBSIDIARIES
   *   AND SHALL NOT BE DISCLOSED WITHOUT PRIOR WRITTEN
   *   PERMISSION. LICENSED CUSTOMERS MAY COPY AND ADAPT 
   *   THIS SOFTWARE FOR THEIR OWN USE IN ACCORDANCE WITH 
   *   THE TERMS OF THEIR SOFTWARE LICENSE AGREEMENT. 
   *   ALL OTHER RIGHTS RESERVED.
   *       
   *   (c) COPYRIGHT 2007. INFOR GLOBAL SOLUTIONS 
   *   TECHNOLOGY GMBH AND/OR ITS AFFILIATES AND SUBSIDIARIES.
   *   ALL RIGHTS RESERVED.
   *   THE WORD AND DESIGN MARKS SET FORTH HEREIN ARE 
   *   TRADEMARKS AND/OR REGISTERED TRADEMARKS OF INFOR
   *   GLOBAL SOLUTIONS TECHNOLOGY GMBH AND/OR ITS AFFILIATES AND 
   *   SUBSIDIARIES. ALL RIGHTS RESERVED. ALL OTHER 
   *   TRADEMARKS LISTED HEREIN ARE THE PROPERTY OF THEIR
   *   RESPECTIVE OWNERS.
   *
   ******************************************************
  -->
<#--
     Generate the interface documentation for a BID
     - object is an instance of BusinessInterfaceDefinition
  -->
<?xml version="1.0"?>
<#macro AttributeTable iComponent>
	<#if iComponent.isHidden>
		<#return>
	</#if>
	<#--
		Outputs the information of one component.
		A table is created with the attributes of this component.
	-->
	<#global skipAttList = "" />
	<#-- Component name -->
	<fo:block font-size="12pt" font-weight="bold" space-before="10pt" space-after="10pt">Component: ${iComponent.name}</fo:block>

	<#if iComponent.name != boname >
		<fo:block font-size="10pt" space-after="10pt" white-space-collapse="false">${iComponent.documentation?default("No description available.")?html}</fo:block>
	</#if>
	<#-- Table of attributes -->
	<fo:block font-size="6pt">(bold-italic-underlined attributes are identifiers, bold-italic attributes are mandatory)</fo:block>
	<fo:block font-size="8pt">
		<fo:table border="0.5pt solid black" text-align="left" table-layout="fixed">
			<fo:table-column column-width="6cm"/>
			<fo:table-column column-width="12cm"/>
			<fo:table-body>
				<#list iComponent.attribute as attribute>
				<#-- Some attributes are part of a GroupAttribute or ComplexAttribute.
					 They will be output when the group is processed, so can be skipped here -->
					<#if !attribute.parentAttribute?has_content>
						<@AttributeRow iAttribute=attribute iAttributeName=attribute.name indent=""/>
					</#if>
				</#list>
			</fo:table-body>
		</fo:table>
	</fo:block>
	<#-- If there are subcomponents in this component then we recursively do the same -->
	<#list iComponent.relationship as relationship>
 		<#if relationship.type="aggregation">
      		<@AttributeTable iComponent=relationship.component />
    	</#if>
	</#list>
</#macro>

<#macro AttributeRow iAttribute iAttributeName indent>
	<#if iAttribute.isHidden>
		<#return>
	</#if>
	<#--
		Outputs the information of one attribute.
		indent is used for group or complex attributes.
	-->
    <fo:table-row>
    	<#-- Attribute name column -->
		<fo:table-cell padding="6pt" border="0.5pt solid black">
      	<#if iAttribute.isIdentifier>
      		<fo:block font-weight="bold" font-style="italic" text-decoration="underline">${indent}${iAttributeName}</fo:block>
      	<#elseif iAttribute.isMandatory>
        	<fo:block font-weight="bold" font-style="italic">${indent}${iAttributeName}</fo:block>
		<#else>
			<fo:block>${indent}${iAttributeName}</fo:block>
      	</#if>
     	</fo:table-cell>
     	<#-- Attribute info column -->
		<fo:table-cell padding="6pt" border="0.5pt solid black">
			<#-- Datatype related info -->
			<#if iAttribute.type="group">
				<fo:block font-weight="bold">Group.</fo:block>
			<#elseif iAttribute.type="complex">
				<@ShowDatatype iAttribute.datatype.idref />
			<#else>
				<#if iAttribute.datatype?has_content && iAttribute.datatype.idref?has_content>
					<@ShowDatatype iAttribute.datatype.idref />
				<#else>
					<fo:block font-weight="bold">No datatype specified.</fo:block>
				</#if>
			</#if>
			<#-- if attribute is used as reference to other BO then it is mentioned here -->
			<#if associatedBOList != "" >
				<#local ref = IsReferenceTo(iAttribute)/>
				<#if ref != "" >
					<fo:block font-style="italic" margin-left="5mm" space-before="1mm">[${ref}]</fo:block>
				</#if>
			</#if>
			<#-- Attribute documentation -->
			<#if iAttribute.documentation?has_content>
				<fo:block white-space-collapse="false" space-before="10pt">${iAttribute.documentation?html}</fo:block>
			</#if>
		</fo:table-cell>
	</fo:table-row>
	<#-- if the the attribute is a GroupAttribute or ComplexAttribute then related attributes
		 are processed. GroupAttributes/ComplexAttributes can contain normal attributes or
		 other GroupAttributesComplexAttributes. So processing is done recursively.
	-->
   	<#list iAttribute.attributeRelationship as relatt>
   		<#-- we are now one level deeper, increase the indent -->
		<@AttributeRow iAttribute=relatt.attribute.idref iAttributeName=relatt.name indent=indent+"=> "/>
   	</#list>
</#macro>

<#function IsReferenceTo iAttribute>
	<#-- returns the BO reference output -->
	<#local s = "" />
	<#list associationList as a>
		<#if a.fromAttr = iAttribute.name>
			<#local s = "references to Business Object <fo:inline font-weight=\"bold\">" + a.toBO + "</fo:inline>"/>
		</#if>
	</#list>
	<#return s>
</#function>

<#macro ShowDatatype iDatatype>
	<#-- Outputs the Datatype related info -->
	<#if iDatatype.datatypeRelationship?has_content >
	    <fo:block font-weight="bold">
	    Complex datatype: ${iDatatype.name}
	    </fo:block>
	<#else>
	    <fo:block font-weight="bold">
	    Datatype
	    <fo:inline font-weight="normal"> (${iDatatype.name}): </fo:inline>
	    ${iDatatype.primitiveDatatype}
		${EnumToString(iDatatype)} 
	    <fo:inline font-weight="normal">${FacetToString(iDatatype)}</fo:inline>
	    </fo:block>
	    .
	</#if>
</#macro>

<#macro DrawStructure iComponent>
	<#if iComponent.isHidden>
		<#return>
	</#if>
	<#-- Outputs the component structure of the BID in a pictorial way -->
	<fo:block>
		<fo:instream-foreign-object content-height="100">
		<svg:svg xmlns:svg="http://www.w3.org/2000/svg" height="14" width="1000">
		<#if linenr != 1>
			<svg:line x1="${clevel*20+10}" y1="0" x2="${clevel*20+10}" y2="8"/>
			<svg:line x1="${clevel*20+10}" y1="8" x2="${clevel*20+18}" y2="8"/>
		</#if>
			<svg:text x="${clevel*20+22}" y="10" font-size="8pt">${multi} ${iComponent.name}</svg:text>
		</svg:svg>
		</fo:instream-foreign-object>
	</fo:block>
	<#list iComponent.relationship as relationship>
	 	<#if relationship.type="aggregation">
	 		<#global multi = ConvertMultiplicity(relationship.multiplicity)>
	 		<#global clevel = clevel + 1>
	 		<#global linenr = linenr + 1>
			<@DrawStructure iComponent=relationship.component />
	 		<#global clevel = clevel - 1>
	    </#if>
	</#list>
</#macro>

<#macro ListAssociations iComponent>
	<#if iComponent.isHidden>
		<#return>
	</#if>
	<#-- 
		Collects all association related information into a hash: 
			associationList (fromAttr, toBO )
		and into a string:
			associatedBOList	containing a comma separated list of associated BOs 
	-->
	<#list iComponent.relationship as relationship>
	 	<#if relationship.type="aggregation">
			<@ListAssociations iComponent=relationship.component />
		<#else>
			<#if !associatedBOList?contains(relationship.toBusinessInterface.value) >
				<#if associatedBOList = "">
					<#global associatedBOList = associatedBOList + relationship.toBusinessInterface.value />
				<#else>
					<#global associatedBOList = associatedBOList + ", " + relationship.toBusinessInterface.value />
				</#if>
			</#if>
			<#list relationship.relationshipAttribute as ra >
				<#global associationList=associationList+[{
					"fromAttr":ra.from.value,
					"toBO":relationship.toBusinessInterface.value
					}]>
			</#list>
	    </#if>
	</#list>
</#macro>

<#macro MethodTable iComponent>
	<#--
		Outputs a table of all methods and their documentation.
	-->
      <fo:block font-size="12pt" font-weight="bold" space-before="10pt" space-after="10pt">Methods</fo:block>
	<#if iComponent.method?has_content>
      <fo:block font-size="8pt">
        <fo:table border="0.5pt solid black" text-align="left" table-layout="fixed">
          <fo:table-column column-width="6cm"/>
          <fo:table-column column-width="12cm"/>
          <fo:table-body>
			<#list iComponent.method as method>
			<fo:table-row>
				<fo:table-cell padding="6pt" border="0.5pt solid black">
					<fo:block>${method.name}</fo:block>
				</fo:table-cell>
				<fo:table-cell padding="6pt" border="0.5pt solid black">
					<fo:block white-space-collapse="false">${method.documentation?default("No documentation available.")?html}</fo:block>
				</fo:table-cell>
			</fo:table-row>
			</#list>
          </fo:table-body>
        </fo:table>
      </fo:block>
	<#else>
      <fo:block font-size="10pt" font-weight="normal">Interface has no methods.</fo:block>
	</#if>
</#macro>

<#macro EventTable iComponent>
	<#--
		Outputs a table of all events and their documentation.
	-->
      <fo:block font-size="12pt" font-weight="bold" space-before="10pt" space-after="10pt">Events</fo:block>
	<#if iComponent.event?has_content>
      <fo:block font-size="8pt">
        <fo:table border="0.5pt solid black" text-align="left" table-layout="fixed">
          <fo:table-column column-width="6cm"/>
          <fo:table-column column-width="12cm"/>
          <fo:table-body>
			<#list iComponent.event as event>
			<fo:table-row>
				<fo:table-cell padding="6pt" border="0.5pt solid black">
					<fo:block>${event.name}</fo:block>
				</fo:table-cell>
				<fo:table-cell padding="6pt" border="0.5pt solid black">
					<fo:block white-space-collapse="false">${event.documentation?default("No documentation available.")?html}</fo:block>
				</fo:table-cell>
			</fo:table-row>
			</#list>
          </fo:table-body>
        </fo:table>
      </fo:block>
	<#else>
      <fo:block font-size="10pt" font-weight="normal">Interface has no events.</fo:block>
	</#if>
</#macro>

<#function EnumToString iDatatype>
	<#-- Converts all enumerates into one comma separated string inbetween () -->
	<#assign i = 0 />
	<#assign str = "" />
		<#list iDatatype.facet as iFacet>
			<#if iFacet.type = "enumeration">
				<#if i = 0>
					<#assign str = str + "(" + iFacet.value />
					<#assign i = 1/>
				<#else>
					<#assign str = str + ", " + iFacet.value />
				</#if>
			</#if>
		</#list>
		<#if i = 1 >
			<#assign str = str + ")" />
		</#if>
	<#return str>
</#function>

<#function FacetToString iDatatype>
	<#-- Converts all facets into a comma separated string inbetween []-->
	<#assign i = 0 />
	<#assign str = "" />
		<#list iDatatype.facet as iFacet>
			<#if iFacet.type != "enumeration">
				<#if i = 0>
					<#assign str = str + "[" + iFacet.type + "=" + iFacet.value />
					<#assign i = 1/>
				<#else>
					<#assign str = str + ", " + iFacet.type + "=" + iFacet.value />
				</#if>
			</#if>
		</#list>
		<#if i = 1 >
			<#assign str = str + "]" />
		</#if>
	<#return str>
</#function>

<#function HasStructure iInterface>
	<#-- Returns true if the BID has subcomponents, otherwise false -->
      <#list iInterface.relationship as rel>
		<#if rel.type="aggregation">
			<#if !rel.component.isHidden>
				<#return true>
			</#if>
		</#if>
      </#list>
      <#return false>
</#function>

<#function ConvertMultiplicity iMultiplicity>
	<#-- Converts the multiplicity term into a more concise format -->
	<#if iMultiplicity = "zeroToMany"><#return "(0-*)"></#if>
	<#if iMultiplicity = "oneToMany"><#return "(1-*)"></#if>
	<#if iMultiplicity = "zeroToOne"><#return "(0-1)"></#if>
	<#if iMultiplicity = "oneToOne"><#return "(1-1)"></#if>
</#function>

<#-- ================================== Main Program ====================================== -->
<#-- Keeps track of the positioning of components in the drawn structure (see macro DrawStructure)-->
<#global clevel = 0 />
<#global linenr = 1 />
<#-- Some global memory -->
<#global multi = "" />				<#-- used in macro DrawStructure -->
<#global associationList=[] />		<#-- used in macro ListAssociations -->
<#global associatedBOList = "" />	<#-- used in macro ListAssociations -->
<#global boname = object.name />	<#-- used in macro AttributeTable -->

<@ListAssociations iComponent = object />

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
	<fo:layout-master-set>
		<fo:simple-page-master master-name="A4"
			page-width="210mm" page-height="297mm"
			margin-left="2cm" margin-right="1cm"
			margin-top="1cm" margin-bottom="1cm">
			<fo:region-body/>
		</fo:simple-page-master>
	</fo:layout-master-set>
	<fo:page-sequence master-reference="A4">
		<fo:flow flow-name="xsl-region-body">
	    	<#-- Introduction -->
			<fo:block font-size="14pt" font-weight="bold">Interface name: ${object.name}</fo:block>
			<fo:block font-size="8pt" space-after="10pt">Version: ${object.versionID?default("?.?.???")}, status: ${object.status}, date: ${today?date}</fo:block>
			<fo:block font-size="12pt" font-weight="bold" space-after="10pt">Description</fo:block>
			<fo:block font-size="10pt" space-after="10pt" white-space-collapse="false">${object.documentation?default("No description available.")?html}</fo:block>
			<fo:block font-size="12pt" font-weight="bold" space-after="10pt">Component structure</fo:block>
			<#-- Pictorial component structure -->
			<#if HasStructure(object) >
				<@DrawStructure iComponent = object />
			<#else>
		  		<fo:block font-size="10pt" font-weight="normal">Interface has no structure.</fo:block>
			</#if>
			<#-- Association Relationships -->
			<fo:block font-size="12pt" font-weight="bold" space-after="10pt" space-before="10pt" >Relations with other interfaces</fo:block>
			<#if associatedBOList != "" >
		  		<fo:block font-size="10pt" font-weight="normal">${associatedBOList}.</fo:block>
			<#else>
		  		<fo:block font-size="10pt" font-weight="normal">Interface has no relations to other interfaces.</fo:block>
			</#if>
			<#-- Tables of attributes per component -->
			<@AttributeTable iComponent = object />
			<#-- Table of methods -->
			<@MethodTable iComponent = object />
			<#-- Table of events -->
			<@EventTable iComponent = object />
		</fo:flow>
	</fo:page-sequence>
</fo:root>