View

Conceptualization

The MyCoRe-directory (src/main/resources) contains all code needed for rendering the data to be displayed on the screen. So this corresponds to the view in an MVC approach. It is done by xsl-files that (unfortunately) contain some logic that really belongs to the controller. Thus, the division is not as clear as implied in theory. I will point at this issue more specifically in the relevant subsection below. Among the resources are all images, styles, and javascripts.

Implementation

The view component handles the visual representation in the form of an interface that allows interaction between the user and the task to be carried out by the machine. As a webservice in the present case, all interaction happens via a browser, i.e. webpages are visualized and responses are recognized by registering mouse or keyboard events. More specifically, a webpage is rendered by transforming xml documents to html pages. The MyCoRe repository framework uses an open source XSLT processor from Apache, Xalan. This engine transforms document nodes described by the XPath syntax into hypertext making use of a special form of template matching. All templates are collected in so called xml-encoded stylesheets. Since there are two data models with two different structures, it is good practice to define two stylesheet files one for each data model.

As a demonstration, in the listing below a short extract is given for rendering the word data.

word data rendering in morphilo.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xalan="http://xml.apache.org/xalan"
  xmlns:i18n="xalan://org.mycore.services.i18n.MCRTranslation"
  xmlns:acl="xalan://org.mycore.access.MCRAccessManager"
  xmlns:mcr="http://www.mycore.org/" xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:mods="http://www.loc.gov/mods/v3"
  xmlns:encoder="xalan://java.net.URLEncoder"
  xmlns:mcrxsl="xalan://org.mycore.common.xml.MCRXMLFunctions"
  xmlns:mcrurn="xalan://org.mycore.urn.MCRXMLFunctions" exclude-result-prefixes="xalan xlink mcr i18n acl mods mcrxsl mcrurn encoder" version="1.0">
  <xsl:param name="MCR.Users.Superuser.UserName"/>
   <xsl:template match="/mycoreobject[contains(@ID,'_morphilo_')]">
    <head>
     <link href="{$WebApplicationBaseURL}css/file.css" rel="stylesheet"/>
    </head>
    <div class="row">
     <xsl:call-template name="objectAction">
      <xsl:with-param name="id" select="@ID"/>
      <xsl:with-param name="deriv" select="structure/derobjects/derobject/@xlink:href"/>
     </xsl:call-template>
     <xsl:variable name="objID" select="@ID"/>
     <!-- Hier Ueberschrift setzen -->
     <h1 style="text-indent: 4em;">
      <xsl:if test="metadata/def.morphiloContainer/morphiloContainer/morphilo/w">
       <xsl:value-of select="metadata/def.morphiloContainer/morphiloContainer/morphilo/w/text()[string-length(normalize-space(.))>0]"/>
      </xsl:if>
     </h1>
     <dl class="dl-horizontal">
     <!-- (1) Display word -->
      <xsl:if test="metadata/def.morphiloContainer/morphiloContainer/morphilo/w">
       <dt>
        <xsl:value-of select="i18n:translate('response.page.label.word')"/>
       </dt>
       <dd>
        <xsl:value-of select="metadata/def.morphiloContainer/morphiloContainer/morphilo/w/text()[string-length(normalize-space(.))>0]"/>
       </dd>
      </xsl:if>
     <!-- (2) Display lemma -->
      ...
   </xsl:template>
    ...
   <xsl:template name="objectAction">
    ...
   </xsl:template>
...
</xsl:stylesheet>

This template matches with the root node of each MyCoRe object ensuring that a valid MyCoRe model is used and checking that the document to be processed contains a unique identifier, here a MyCoRe-ID, and the name of the correct data model, here morphilo. Then, another template, objectAction, is called together with two parameters, the ids of the document object and attached files. In the remainder all relevant information from the document is accessed by XPath, such as the word and the lemma, and enriched with hypertext annotations it is rendered as a hypertext document. The template objectAction is key to understand the coupling process in the software framework. It is therefore separately listed in template ObjectAction.

template ObjectAction
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<xsl:template name="objectAction">
<xsl:param name="id" select="./@ID"/>
<xsl:param name="accessedit" select="acl:checkPermission($id,'writedb')"/>
<xsl:param name="accessdelete" select="acl:checkPermission($id,'deletedb')"/>
<xsl:variable name="derivCorp" select="./@label"/>
<xsl:variable name="corpID" select="metadata/def.corpuslink[@class='MCRMetaLinkID']/corpuslink/@xlink:href"/>
<xsl:if test="$accessedit or $accessdelete">
<div class="dropdown pull-right">
  <xsl:if test="string-length($corpID) &gt; 0 or $CurrentUser='administrator'">
    <button class="btn btn-default dropdown-toggle" style="margin:10px" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-expanded="true">
      <span class="glyphicon glyphicon-cog" aria-hidden="true"></span> Annotieren
      <span class="caret"></span>
    </button>
  </xsl:if>
  <xsl:if test="string-length($corpID) &gt; 0">
    <xsl:variable name="ifsDirectory" select="document(concat('ifs:/',$derivCorp))"/>
      <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
        <li role="presentation">
          <a href="{$ServletsBaseURL}object/tag{$HttpSession}?id={$derivCorp}&amp;objID={$corpID}" role="menuitem" tabindex="-1">
            <xsl:value-of select="i18n:translate('object.nextObject')"/>
          </a>
        </li>
        <li role="presentation">
          <a href="{$WebApplicationBaseURL}receive/{$corpID}" role="menuitem" tabindex="-1">
            <xsl:value-of select="i18n:translate('object.backToProject')"/>
          </a>
        </li>
      </ul>
    </xsl:if>
    <xsl:if test="$CurrentUser='administrator'">
     <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
      <li role="presentation">
       <a role="menuitem" tabindex="-1" href="{$WebApplicationBaseURL}content/publish/morphilo.xed?id={$id}">
        <xsl:value-of select="i18n:translate('object.editWord')"/>
       </a>
      </li>
      <li role="presentation">
       <a href="{$ServletsBaseURL}object/delete{$HttpSession}?id={$id}" role="menuitem" tabindex="-1" class="confirm_deletion option" data-text="Wirklich loeschen">
        <xsl:value-of select="i18n:translate('object.delWord')"/>
       </a>
      </li>
     </ul>
    </xsl:if>
    </div>
    <div class="row" style="margin-left:0px; margin-right:10px">
     <xsl:apply-templates select="structure/derobjects/derobject[acl:checkPermission(@xlink:href,'read')]">
      <xsl:with-param name="objID" select="@ID"/>
     </xsl:apply-templates>
    </div>
   </xsl:if>
  </xsl:template>

The objectAction template defines the selection menu appearing – once manual tagging has started – on the upper right hand side of the webpage entitled Annotieren and displaying the two options next word or back to project. The first thing to note here is that in line 7 a simple test excludes all guest users from accessing the procedure. After ensuring that only the user who owns the corpus project has access (line 15), s/he will be able to access the drop down menu, which is really a url, e.g. line 19. The attentive reader might have noticed that the url exactly matches the definition in the web-fragment.xml as shown in listing Servlet Registering in the web-fragment.xml, line 17, which resolves to the respective java class there. Really, this mechanism is the data interface within the MVC pattern. The url also contains two variables, named derivCorp and corpID, that are needed to identify the corpus and file object by the java classes (see section Implementation).

The morphilo.xsl stylesheet contains yet another modification that deserves mention. In listing derobject template, line 18, two menu options – Tag automatically and Tag manually – are defined. The former option initiates ProcessCorpusServlet.java as can be seen again in listing Servlet Registering in the web-fragment.xml, line 7, which determines words that are not in the master data base. Still, it is important to note that the menu option is only displayed if two restrictions are met. First, a file has to be uploaded (line 19) and, second, there must be only one file. This is necessary because in the annotation process other files will be generated that store the words that were not yet processed or a file that includes the final result. The generated files follow a certain pattern. The file harboring the final, entire TEI-annotated corpus is prefixed by tagged, the other file is prefixed untagged. This circumstance is exploited for manipulating the second option (line 27). A loop runs through all files in the respective directory and if a file name starts with untagged, the option to manually tag is displayed.

derobject template
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<xsl:template match="derobject" mode="derivateActions">
 <xsl:param name="deriv" />
 <xsl:param name="parentObjID" />
 <xsl:param name="suffix" select="''" />
 <xsl:param name="id" select="../../../@ID" />
 <xsl:if test="acl:checkPermission($deriv,'writedb')">
  <xsl:variable name="ifsDirectory" select="document(concat('ifs:',$deriv,'/'))" />
  <xsl:variable name="path" select="$ifsDirectory/mcr_directory/path" />
 ...
   <div class="options pull-right">
    <div class="btn-group" style="margin:10px">
     <a href="#" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
      <i class="fa fa-cog"></i>
      <xsl:value-of select="' Korpus'"/>
      <span class="caret"></span>
     </a>
    <ul class="dropdown-menu dropdown-menu-right">
     <!-- Anpasssungen Morphilo -->|\label{ln:morphMenu}|
     <xsl:if test="string-length($deriv) &gt; 0">|\label{ln:1test}|
      <xsl:if test="count($ifsDirectory/mcr_directory/children/child) = 1">|\label{ln:2test}|
       <li role="presentation">
        <a href="{$ServletsBaseURL}object/process{$HttpSession}?id={$deriv}&amp;objID={$id}" role="menuitem" tabindex="-1">
         <xsl:value-of select="i18n:translate('derivate.process')"/>
        </a>
       </li>
      </xsl:if>
      <xsl:for-each select="$ifsDirectory/mcr_directory/children/child">|\label{ln:loop}|
       <xsl:variable name="untagged" select="concat($path, 'untagged')"/>
       <xsl:variable name="filename" select="concat($path,./name)"/>
       <xsl:if test="starts-with($filename, $untagged)">
        <li role="presentation">
         <a href="{$ServletsBaseURL}object/tag{$HttpSession}?id={$deriv}&amp;objID={$id}" role="menuitem" tabindex="-1">
          <xsl:value-of select="i18n:translate('derivate.taggen')"/>
         </a>
        </li>
       </xsl:if>
      </xsl:for-each>
     </xsl:if>
    ...
    </ul>
   </div>
  </div>
 </xsl:if>
</xsl:template>

Besides the two stylesheets morphilo.xsl and corpmeta.xsl, other stylesheets have to be adjusted. They will not be discussed in detail here for they are self-explanatory for the most part. Essentially, they render the overall layout (common-layout.xsl, skeleton_layout_template.xsl) or the presentation of the search results (response-page.xsl) and definitions of the solr search fields (searchfields-solr.xsl). The former and latter also inherit templates from response-general.xsl and response-browse.xsl, in which the navigation bar of search results can be changed. For the use of multilinguality a separate configuration directory has to be created containing as many .property-files as different languages want to be displayed. In the current case these are restricted to German and English (messages_de.properties and messages_en.properties). The property files include all i18n definitions. All these files are located in the resources directory.

Furthermore, a search mask and a page for manually entering the annotations had to be designed. For these files a specially designed xml standard (xed) is recommended to be used within the repository framework.