Index: /main/trunk/greenstone2/perllib/plugins/BasePlugin.pm
===================================================================
--- /main/trunk/greenstone2/perllib/plugins/BasePlugin.pm	(revision 24218)
+++ /main/trunk/greenstone2/perllib/plugins/BasePlugin.pm	(revision 24219)
@@ -1300,9 +1300,17 @@
 		my ($pre_doc_ext) = ($file_extended_ext =~ m/^(.*)\..*$/);
 		my ($doc_ext) = ($tail_filename =~ m/^.*\.(.*)$/);
-		my $start_doclink = "<a href=\"_httpprefix_/collect/[collection]/index/assoc/{Or}{[parent(Top):assocfilepath],[assocfilepath]}/$url_tail_filename\">";
+
+##		my $start_doclink = "<a href=\"_httpprefix_/collect/[collection]/index/assoc/{Or}{[parent(Top):assocfilepath],[assocfilepath]}/$url_tail_filename\">";
+		my $start_doclink = "<a href=\'_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/$url_tail_filename\'>";
+		my $start_doclink_gs3 = "<a href=\'_httpprefix_/collect/[collection]/index/assoc/[assocfilepath]/$url_tail_filename\'>";
+
 		my $srcicon = "_icon".$doc_ext."_";
 		my $end_doclink = "</a>";
-
+		
 		my $assoc_form = "$start_doclink\{If\}{$srcicon,$srcicon,$doc_ext\}$end_doclink";
+
+		$doc_obj->add_utf8_metadata ($cursection, "equivDocLink", $start_doclink);
+		$doc_obj->add_utf8_metadata ($cursection, "equivDocIcon", $srcicon);
+		$doc_obj->add_utf8_metadata ($cursection, "/equivDocLink", $end_doclink);
 
 		if (defined $pre_doc_ext && $pre_doc_ext ne "") {
@@ -1313,5 +1321,5 @@
 		# for multiple metadata such as [mp3.assoclink]
 		$doc_obj->add_utf8_metadata ($cursection, "$doc_ext.assoclink", $assoc_form); 
-		
+
 		$equiv_form .= " $assoc_form";	
 	    }
Index: /main/trunk/greenstone2/perllib/plugins/DSpacePlugin.pm
===================================================================
--- /main/trunk/greenstone2/perllib/plugins/DSpacePlugin.pm	(revision 24218)
+++ /main/trunk/greenstone2/perllib/plugins/DSpacePlugin.pm	(revision 24219)
@@ -323,5 +323,5 @@
 
 	my @gsdlassocfile_tobe 
-	    = map { &util::filename_cat($dir,$_->{'file'}).":".$_->{'mimetype'}.":" } @$assoc_file_mimes;
+	    = map { &util::filename_cat($dir,$_->{'file'}) .":".$_->{'mimetype'}.":" } @$assoc_file_mimes if @$assoc_file_mimes;
 	$self->{'saved_metadata'}->{'gsdlassocfile_tobe'} = \@gsdlassocfile_tobe;
 
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/Action.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/Action.java	(revision 24218)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/Action.java	(revision 24219)
@@ -105,18 +105,44 @@
             meta_names.add(metadata.toString());
         }
-
-		// The XSL tranform for
-		//   gsf:link type="source" 
-		// makes use of 'assocfilepath' so need to make sure it's asked for
-
-		NodeList link_nodes = format.getElementsByTagName("gsf:link");
-			for (int i=0; i<link_nodes.getLength(); i++) {
-				Element elem = (Element)link_nodes.item(i);
-				String type = elem.getAttribute("type");
-			if (type.equals("source") || type.equals("sourcelinkfile")) {
-			meta_names.add("assocfilepath");
-			}
-		}
-
+	
+	// The XSL tranform for
+	//   gsf:link type="source" 
+	// makes use of 'assocfilepath' so need to make sure it's asked for
+	
+	NodeList link_nodes = format.getElementsByTagName("gsf:link");
+	for (int i=0; i<link_nodes.getLength(); i++) {
+	    Element elem = (Element)link_nodes.item(i);
+	    String type = elem.getAttribute("type");
+	    if (type.equals("source")) {
+		meta_names.add("assocfilepath");
+	    } else if (type.equals("sourcelinkfile")) {
+		meta_names.add("assocfilepath");
+		//meta_names.add("srclinkFile");
+	    }
+	}
+
+
+	// get all the metadata necessary for when the user has used "gsf:equivlink"
+	// so that we can build up the equivlink from the metadata components it needs
+	link_nodes = format.getElementsByTagName("gsf:equivlinkgs3"); 
+	if(link_nodes != null) {	  
+
+	    String[] equivlink_metanames = {"equivDocIcon", "equivDocLink", "/equivDocLink"};
+
+	    for(int i = 0; i < equivlink_metanames.length; i++) {
+		StringBuffer metadata = new StringBuffer();
+		metadata.append("all"); // this means the attr multiple = true;
+		metadata.append(GSConstants.META_RELATION_SEP);
+		
+		metadata.append(GSConstants.META_SEPARATOR_SEP);
+		metadata.append(','); // attr separator = ","
+		metadata.append(GSConstants.META_SEPARATOR_SEP);
+		metadata.append(GSConstants.META_RELATION_SEP);
+		
+		// the name of the metadata we're retrieving
+		metadata.append(equivlink_metanames[i]);
+		meta_names.add(metadata.toString());
+	    }
+	}
     }
 
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/XSLTUtil.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/XSLTUtil.java	(revision 24218)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/XSLTUtil.java	(revision 24219)
@@ -97,4 +97,30 @@
     }
 
+    /** Generates links to equivalent documents for a document with a default document icon/type. 
+     * Links are generated from the parameters: a list of document icons which are each in turn embedded 
+     * in the matching starting link tag in the list of docStartLinks (these starting links link to the 
+     * equivalent documents in another format). Each link's start tag is closed with the corresponding 
+     * closing tag in the docEndLinks list. Parameter token is the list separator. Parameter divider is 
+     * the string that should separate each final link generated from the next.
+     * Returns a string that represents a sequence of links to equivalent documents, where the anchor is
+     * a document icon. */
+    public static String getEquivDocLinks(String token, String docIconsString, String docStartLinksString, 
+					  String docEndLinksString, String divider)
+    {
+	String [] docIcons = StringUtils.split(docIconsString, token, -1);
+	String [] startLinks = StringUtils.split(docStartLinksString, token, -1);
+	String [] endLinks = StringUtils.split(docEndLinksString, token, -1);
+
+	StringBuffer buffer = new StringBuffer();
+	for(int i = 0; i < docIcons.length; i++) {
+	    if(i > 0) {
+		buffer.append(divider);
+	    }
+	    buffer.append(startLinks[i]+docIcons[i]+endLinks[i]);
+	}
+	
+	return buffer.toString();
+    }
+
     
     public static String tidyWhitespace(String original) {
Index: /main/trunk/greenstone3/web/interfaces/default/transform/config_format.xsl
===================================================================
--- /main/trunk/greenstone3/web/interfaces/default/transform/config_format.xsl	(revision 24218)
+++ /main/trunk/greenstone3/web/interfaces/default/transform/config_format.xsl	(revision 24219)
@@ -77,5 +77,38 @@
     </xsl:choose>
   </xsl:template>
-  
+
+  <!-- calls a template in icons.xsl in order to avoid xsl vs xslt issue -->
+  <xsl:template match="gsf:equivlinkgs3">
+    <xslt:call-template name="equivDocLinks">
+      <xslt:with-param name="count" select="0"/>
+    </xslt:call-template>
+  </xsl:template>
+
+  <!-- Another way: build all the equivalent document links for the current document in one go. No looping necessary: handled in function call. -->
+  <!--<xsl:template match="gsf:equivlinkgs3">
+	<xslt:variable name="docicon" select="metadataList/metadata[contains(@name, 'equivDocIcon')]"/>	
+	<xslt:variable name="docStartlink" select="metadataList/metadata[contains(@name, 'all_*,*_equivDocLink')]"/>	
+	<xslt:variable name="docEndlink" select="metadataList/metadata[contains(@name, '/equivDocLink')]"/>
+
+	<xslt:variable name="equivDocLinks" select="java:org.greenstone.gsdl3.util.XSLTUtil.getEquivDocLinks(',',$docicon, $docStartlink, $docEndlink, ' ')" />
+	<xslt:value-of disable-output-escaping="yes" select="$equivDocLinks"/>
+  </xsl:template>-->
+
+<!--
+In the collection's format statement, could have the following javascript+XSLT in place of
+the gsf:equivlinkgs3 element (which resolves to the XSLT in config_format.xsl and icons.xsl).
+<xsl:text disable-output-escaping="yes">&lt;script&gt;var equivDocIcon= [ &quot;
+</xsl:text>
+<gsf:metadata name="equivDocIcon" separator="&quot;, &quot;" multiple="true"/>
+<xsl:text disable-output-escaping="yes">&quot;];var equivDocStartLink= [ &quot;
+</xsl:text>
+<gsf:metadata name="equivDocLink" separator="&quot;,&quot;" multiple="true"/>
+<xsl:text disable-output-escaping="yes">&quot;];var equivDocEndLink= [ &quot;
+</xsl:text>
+<gsf:metadata name="/equivDocLink" separator="&quot;,&quot;" multiple="true"/>
+<xsl:text disable-output-escaping="yes">&quot;];for (var i=0; i&lt;equivDocIcon.length; i++) { document.write(equivDocStartLink[i]+ equivDocIcon[i] + equivDocEndLink[i]); }&lt;/script&gt;
+</xsl:text>
+-->
+
   <xsl:template match="gsf:metadata[@format]">
     <xslt:value-of disable-output-escaping="yes"><xsl:attribute name="select">java:org.greenstone.gsdl3.util.XSLTUtil.<xsl:value-of select="@format"/>(metadataList/metadata[@name='<xsl:apply-templates select="." mode="get-metadata-name"/>'], /page/@lang )</xsl:attribute></xslt:value-of>
Index: /main/trunk/greenstone3/web/interfaces/default/transform/icons.xsl
===================================================================
--- /main/trunk/greenstone3/web/interfaces/default/transform/icons.xsl	(revision 24218)
+++ /main/trunk/greenstone3/web/interfaces/default/transform/icons.xsl	(revision 24219)
@@ -119,4 +119,30 @@
   </xsl:template>
 
+  <!-- builds up links to available document types equivalent to the default source
+       document with as anchor the equivalent documents' doctype icons. -->
+  <xsl:template name="equivDocLinks">
+    <xsl:param name="count"/>
+
+      <xsl:variable name="docicon" select="metadataList/metadata[contains(@name, 'equivDocIcon')]"/>	
+      <xsl:variable name="docStartlink" select="metadataList/metadata[contains(@name, 'all_*,*_equivDocLink')]"/>	
+      <xsl:variable name="docEndlink" select="metadataList/metadata[contains(@name, '/equivDocLink')]"/>
+
+      <xsl:variable name="equivDocIcon" select="java:org.greenstone.gsdl3.util.XSLTUtil.getNumberedItem($docicon, $count)" />
+      <xsl:variable name="equivStartlink" select="java:org.greenstone.gsdl3.util.XSLTUtil.getNumberedItem($docStartlink, $count)" />
+      <xsl:variable name="equivEndlink" select="java:org.greenstone.gsdl3.util.XSLTUtil.getNumberedItem($docEndlink, $count)" />
+
+      <xsl:if test="$equivDocIcon != ''">
+        <xsl:value-of disable-output-escaping="yes" select="$equivStartlink"/>
+        <xsl:value-of disable-output-escaping="yes" select="$equivDocIcon"/>
+        <xsl:value-of disable-output-escaping="yes" select="$equivEndlink"/>
+
+        <!-- recursively call this template to get multiple entries -->
+        <xsl:call-template name="equivDocLinks">
+          <xsl:with-param name="count"><xsl:value-of select="$count + 1"/></xsl:with-param>
+        </xsl:call-template>
+      </xsl:if>
+
+  </xsl:template>
+
 </xsl:stylesheet>
 
