Index: main/trunk/greenstone3/web/interfaces/default/transform/pages/document-iiif-manifest.xsl.SOWEMUSTTHINK
===================================================================
--- main/trunk/greenstone3/web/interfaces/default/transform/pages/document-iiif-manifest.xsl.SOWEMUSTTHINK	(revision 38244)
+++ main/trunk/greenstone3/web/interfaces/default/transform/pages/document-iiif-manifest.xsl.SOWEMUSTTHINK	(revision 38244)
@@ -0,0 +1,309 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+	xmlns:java="http://xml.apache.org/xslt/java"
+	xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+	xmlns:gslib="http://www.greenstone.org/skinning"
+	xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat"
+	extension-element-prefixes="java util"
+	exclude-result-prefixes="java util gsf">
+
+  <!--
+      Key goal: generate a IIIF v2 compliant manifest file in JSON format based on the document
+  -->
+  
+  <!-- Similar in spirit to document.xsl (catering for 'simple' and complex document structures such as 'pages'),
+       but considerably tailored down to produce the raw IIIF-manifest JSON format:
+         (i)  focus on just the (potientailly hierachically nested) pages
+         (ii) so a bit like ed=1, but implied rather than needing to be set
+  -->
+
+  <xsl:include href="layouts/header-vars.xsl"/>
+
+  <!--
+  <xsl:include href="pages/document-shared.xsl" />
+  -->
+
+  <xsl:include href="pages/document-vars.xsl" />
+
+  <!-- Additional changes needed to GS3 Java runtine for the following output tag to operate correctly -->
+  <!-- Testing with o=xsl and the debug XML+XSL pair of files generated (when an error was encountred) 
+       showed that the Greenstone3 runtime does not currently honour the output tag, in fact gslib.xsl
+       entries seem to turn up later on, and as this includes html-output.xsl, then a later xsl:output
+       tag is generated.  The problems runner deeper than this however, with the XSLT output generated
+       having a DTD.  Looks like gsdl3/TransformingReceptionist.java is geared to always generating 
+       XML output of some form of other (e.g. RSS XML output).  Generating raw text just doesn't
+       seem to get through.  So to make progress have introduced CGI argument 'excerptid-text' 
+       as a way of getting to the text that is generated within, say, a <pre> elemlent with an id attribute -->
+  <!--
+  <xsl:output method="text" version="1.0" encoding="utf-8" omit-xml-declaration="yes"/>
+  <xsl:strip-space elements="*"/>
+  -->
+
+  <!-- page/pageRequest[@baseURL]="//intermuse.sowemustthink.space/greenstone3/ -->
+  <!-- page/pageRequest[@fullURL]="//intermuse.sowemustthink.space/greenstone3/library?a=d.... -->
+  <xsl:variable name="window-location-origin">https://intermuse.sowemustthink.space</xsl:variable>
+
+  <!-- optional cgi-params for links to document pages -->
+  <xsl:variable name="opt-doc-link-args"></xsl:variable>
+  <xsl:variable name="bookswitch"></xsl:variable>
+  
+  <xsl:variable name="iiifPresentationRootIdentifier">http://ld.greenstone.org/<xsl:value-of select="$site_name"/>/<xsl:value-of select="$collNameChecked"/>/<xsl:value-of select="$docID"/></xsl:variable>
+  
+  <xsl:template match="/">
+      <html>
+	<body>
+	  <pre id="iiif-manifest">
+	    <xsl:apply-templates select="/page/pageResponse/document" />
+	</pre>
+      </body>
+    </html>
+  </xsl:template>
+
+  <xsl:template match="/page/pageResponse/document">
+    <!-- display the document -->
+    <xsl:choose>
+      <xsl:when test="@docType='simple'">
+	<xsl:call-template name="documentContent"/>
+      </xsl:when>	
+      <xsl:otherwise> <!-- kick off the recursive call for a more complex structured document-->
+	<xsl:call-template name="wrappedDocumentTopLevel"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  
+  <xsl:template name="wrappedDocumentTopLevel">
+    <!-- <xsl:call-template name="documentPre"/> -->
+    <xsl:call-template name="wrappedDocument"/> <!-- without ed=1, this template misses the binds in of documentPre and documentPost -->
+    <!-- <xsl:call-template name="documentPost"/> -->
+  </xsl:template>
+
+  <xsl:template name="wrappedDocument">
+    <xsl:call-template name="documentPre"/>
+      <xsl:for-each select="documentNode">
+	<xsl:call-template name="wrapDocumentNodes"/>
+      </xsl:for-each>
+    <xsl:call-template name="documentPost"/>    
+  </xsl:template>
+  
+ 
+  <xsl:template name="iiif-other-content">
+    <xsl:param name="optSection"/>    
+    <xsl:variable name="baseURL">https:<xsl:value-of select="/page/pageRequest/@baseURL"/></xsl:variable> <!-- **** had to hardwire https: -->
+    <xsl:variable name="gsfOptionIncludeFileAssocOpenAnnotations">
+      <xsl:value-of select="/page/pageResponse/format[@type='display']/gsf:option[@name='includeFileAssocOpenAnnotations']/@value"></xsl:value-of>
+    </xsl:variable>
+    <xsl:variable name="cgiParamIncludeFileAssocOpenAnnotations">
+      <xsl:value-of select="/page/pageRequest/paramList/param[@name='includeFileAssocOpenAnnotations']/@value"></xsl:value-of>
+    </xsl:variable>
+
+    <xsl:if test="$gsfOptionIncludeFileAssocOpenAnnotations='true' or $cgiParamIncludeFileAssocOpenAnnotations='true'">
+             "otherContent": [{
+                    "@id": "<xsl:value-of select="$baseURL"/><xsl:value-of select="$library_name"/>/sites/<xsl:value-of select="$site_name"/>/collect/<xsl:value-of select="$collNameChecked"/>/index/assoc/<gsf:metadata name="assocfilepath" select="root"/>/openannotation-list<xsl:value-of select="$optSection"/>.json",
+                    "@type": "sc:AnnotationList"
+              }],
+    </xsl:if>
+  </xsl:template>
+  
+
+  <xsl:template name="iiif-canvas-image">
+    <xsl:param name="identifier"/>
+    <xsl:param name="docType"/>
+    <!-- -->
+    <xsl:variable name="iiifImageRootIdentifier">
+      <xsl:text>/gs-cantaloupe/iiif/2/</xsl:text><xsl:value-of select="$site_name"/>:<xsl:value-of select="$collNameChecked"/>:<xsl:value-of select="$identifier"/>
+    </xsl:variable>
+
+    <xsl:variable name="section"><xsl:value-of select="position()" /></xsl:variable>
+    <xsl:variable name="optSection">
+      <xsl:choose>
+	<xsl:when test="$docType = 'simple'"></xsl:when><!-- i.e. empty -->
+	<xsl:otherwise><xsl:value-of select="position()" /></xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="chosenTitle">
+      <xsl:choose>
+	<xsl:when test="$docType = 'simple'">
+	  <xsl:call-template name="choose-title"/>
+	</xsl:when>
+	<xsl:otherwise>page <xsl:value-of select="$section"/></xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <!-- The following is useful for debugging, nested in 'pre' tags -->
+    <!--
+      docType   = <xsl:value-of select="$docType"/>
+      docID     = <xsl:value-of select="$docID"/>
+      position  = <xsl:value-of select="position()" />
+
+      identifer = <xsl:value-of select="$identifier"/>
+      section    = <xsl:value-of select="$section"/>
+      optSection = <xsl:value-of select="$optSection"/>
+
+      iiifPresRootIdentifier  = <xsl:value-of select="$iiifPresentationRootIdentifier" />
+      iiifImageRootIdentifier = <xsl:value-of select="$iiifImageRootIdentifier" />
+    -->
+    <!-- an array entry in 'canvases': { @content, @id, @type, label, width, height, images[{}], thumbnail {@id,@type} } -->
+    <!-- add a comma first, if it is not the first canvas element in the array -->
+      <xsl:if test="$section &gt; 1">
+          ,
+      </xsl:if>
+            {
+              "@context": "http://iiif.io/api/presentation/2/context.json",
+              "@id"     : "<xsl:value-of select="$iiifPresentationRootIdentifier" />/canvas/<xsl:value-of select="$section"/>",
+              "@type"   : "sc:Canvas",
+              "label"   : "<xsl:value-of select="$chosenTitle"/>",
+              <xsl:call-template name="iiif-other-content">
+                <xsl:with-param name="optSection"><xsl:value-of select="$optSection"/></xsl:with-param>
+              </xsl:call-template>
+              "width"   : <gsf:metadata name="ImageWidth"/>,
+              "height"  : <gsf:metadata name="ImageHeight"/>,              
+              "images": [{
+                  "@context":   "http://iiif.io/api/image/2/context.json",
+                  "@id":        "<xsl:value-of select="$iiifPresentationRootIdentifier" />/annotation/<xsl:value-of select="$section"/>",
+                  "@type":      "oa:Annotation",
+                  "motivation": "sc:painting",
+                  "on":         "<xsl:value-of select="$iiifPresentationRootIdentifier" />/canvas",
+                  "resource": {
+                    "@id":     "<xsl:value-of select="$window-location-origin" /><xsl:value-of select="$iiifImageRootIdentifier" />/full/full/0/default.jpg",
+                    "@type":   "dctypes:Image",
+                    "format":  "image/jpeg",
+                    "width":   <gsf:metadata name="ImageWidth"/>,
+                    "hieght":  <gsf:metadata name="ImageHeight"/>,
+                    "service": {
+                      "@context": "http://iiif.io/api/image/2/context.json",
+                      "@id":      "<xsl:value-of select="$window-location-origin" /><xsl:value-of select="$iiifImageRootIdentifier" />",
+                      "profile":  "https://iiif.io/api/image/2/profiles/level2.json"
+                    }
+                }
+              }],
+              "thumbnail": {
+                "@id":   "<xsl:value-of select="$window-location-origin" /><xsl:value-of select="$iiifImageRootIdentifier" />/full/,150/0/default.jpg",
+                "@type": "dctypes:Image"
+              }
+            }      
+    <!-- Another field to consider in the above JSON is: -->
+    <!--   "format": mime_type, // ???? or is it OK to always have this as image/jpeg and rely on IIIF Image Server coverting as/when needed??? -->
+  </xsl:template>
+
+
+  <xsl:template name="wrappedSectionPost">
+
+    <!-- add in IIIF Server link for section image -->
+    <xsl:variable name="nodeID" select="@nodeID"/>
+    <xsl:call-template name="iiif-canvas-image">
+      <xsl:with-param name="identifier" select="$nodeID" />
+      <xsl:with-param name="docType" select="@docType" />
+    </xsl:call-template>
+  </xsl:template>
+
+  <xsl:template name="sectionImage">
+    <!-- don't need this template to generate anything in the IIIF-Manifest JSON case -->
+  </xsl:template>
+
+  <xsl:template name="sectionContent">
+    <xsl:call-template name="wrappedSectionPost"/>
+  </xsl:template>
+
+  
+  <xsl:template name="documentPre">
+    <xsl:variable name="httpCollection">library/sites/<xsl:value-of select="$site_name"/>/collect/<xsl:value-of select="/page/pageResponse/collection/@name"/></xsl:variable>
+
+    <xsl:variable name="toplevelChosenTitle">
+      <xsl:choose>
+        <xsl:when test="@docType='simple'">
+	  <xsl:call-template name="choose-title"/>
+	</xsl:when>
+	<xsl:otherwise>
+	  <xsl:value-of disable-output-escaping="yes" select="/page/pageResponse/document/documentNode/metadataList/metadata[@name='Title']" />
+	</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+
+    <xsl:variable name="toplevelSASShortID">
+      <xsl:choose>
+        <xsl:when test="@docType='simple'">
+	  <gsf:metadata name="SASShortID" />
+	</xsl:when>
+	<xsl:otherwise>
+	  <xsl:value-of disable-output-escaping="yes" select="/page/pageResponse/document/documentNode/metadataList/metadata[@name='SASShortID']" />
+	</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+
+
+    <!-- start of iiif_manifest: -->
+    {
+        "@context": "http://iiif.io/api/presentation/2/context.json",
+        "@type": "sc:Manifest",
+        "@id": "<xsl:value-of select="$iiifPresentationRootIdentifier"/>/manifest",
+        "label": "<xsl:value-of select="$toplevelChosenTitle"/>",
+        "attribution": "The Internet of Musical Events (InterMusE): Digital Scholarship, Community, and the Archiving of Performance",
+        "license": "https://**** To Be Determined ****",
+        "logo": "https://intermuse.datatodata.org/wp-content/uploads/sites/4/2021/03/cropped-cropped-cropped-1.png",
+        "metadata": [
+          { "label": "creator", "value": ["aaa1","aaa2"] },
+          { "label": "title", "value": ["chosen-title"] }
+        ],
+
+        "service": {
+          "profile": "http://iiif.io/api/search/0/search",
+          "@id": "https://intermuse.sowemustthink.space/simpleAnnotationStore/search-api/<xsl:value-of select="$toplevelSASShortID"/>/search",
+          "@context": "http://iiif.io/api/search/0/context.json"
+	},
+	  
+        <!-- trival IIIF sequences => has one IIIF canvas in it -->
+        "sequences": [{
+          "@context": "http://iiif.io/api/image/2/context.json",
+          "@id": "<xsl:value-of select="$iiifPresentationRootIdentifier"/>/sequence/normal",
+          "@type": "sc:Sequence",
+          "canvases": [
+  </xsl:template>
+     
+  
+  <xsl:template name="documentContentSimpleIIIFImage">
+    <xsl:call-template name="iiif-canvas-image">
+      <xsl:with-param name="identifier" select="$docID" />
+      <xsl:with-param name="docType" select="@docType" />
+    </xsl:call-template>
+  </xsl:template>
+  
+  <xsl:template name="documentContent">
+    <!-- The way document.xsl templates are structured, only get to here is if @docType = 'simple' -->
+    <!-- A 'paged' (or 'hierarical') document goes throgh 'wrappedContent' -->
+    <xsl:call-template name="documentPre"/>
+    <xsl:call-template name="documentContentSimpleIIIFImage"/>
+    <xsl:call-template name="documentPost"/>
+  </xsl:template>
+
+  
+  <xsl:template name="wrapDocumentNodes">
+
+    <xsl:if test="@nodeType = 'leaf'">
+      <!-- for iiif-manifest JSON, put out a flat-list of images => only interested in leaf nodes -->
+      <xsl:call-template name="sectionContent"/>
+    </xsl:if>
+    
+    <xsl:if test="documentNode">
+      <xsl:for-each select="documentNode">
+        <xsl:call-template name="wrapDocumentNodes"/>
+      </xsl:for-each>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template name="wrappedSectionImage">
+    <!-- don't need this template to generate anything in the IIIF-Manifest JSON case -->
+  </xsl:template>
+
+  
+  
+  <xsl:template name="documentPost">
+    <!-- end of iiif_manifest: -->
+    <!-- close of canvases, then close higher level blocks to complete the JSON file -->
+	  ]
+	}]	  
+    }    	
+  </xsl:template>
+
+
+</xsl:stylesheet>
