diff software/mpdl-services-new/mpiwg-mpdl-cms-web/src/de/mpg/mpiwg/berlin/mpdl/servlets/lt/GetDictionaryEntries.java @ 25:e9fe3186670c default tip

letzter Stand eingecheckt
author Josef Willenborg <jwillenborg@mpiwg-berlin.mpg.de>
date Tue, 21 May 2013 10:19:32 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/software/mpdl-services-new/mpiwg-mpdl-cms-web/src/de/mpg/mpiwg/berlin/mpdl/servlets/lt/GetDictionaryEntries.java	Tue May 21 10:19:32 2013 +0200
@@ -0,0 +1,485 @@
+package de.mpg.mpiwg.berlin.mpdl.servlets.lt;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.StringEscapeUtils;
+
+import de.mpg.mpiwg.berlin.mpdl.exception.ApplicationException;
+import de.mpg.mpiwg.berlin.mpdl.lt.dict.app.Lexica;
+import de.mpg.mpiwg.berlin.mpdl.lt.dict.app.Lexicon;
+import de.mpg.mpiwg.berlin.mpdl.lt.dict.app.LexiconEntry;
+import de.mpg.mpiwg.berlin.mpdl.lt.dict.db.LexHandler;
+import de.mpg.mpiwg.berlin.mpdl.lt.general.Language;
+import de.mpg.mpiwg.berlin.mpdl.lt.morph.app.Form;
+import de.mpg.mpiwg.berlin.mpdl.lt.morph.app.Lemma;
+import de.mpg.mpiwg.berlin.mpdl.lt.text.norm.Normalizer;
+import de.mpg.mpiwg.berlin.mpdl.servlets.util.ServletUtil;
+
+public class GetDictionaryEntries extends HttpServlet {
+  private static final long serialVersionUID = 1L;
+  private LexHandler lexHandler;
+
+  public GetDictionaryEntries() {
+    super();
+  }
+
+  public void init(ServletConfig config) throws ServletException  {
+    super.init(config);
+    try {
+      lexHandler = LexHandler.getInstance();
+    } catch (ApplicationException e) {
+      throw new ServletException(e);
+    }
+  }
+
+  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+    Date begin = new Date();
+    request.setCharacterEncoding("utf-8");
+    response.setCharacterEncoding("utf-8");
+    String query = request.getParameter("query");
+    String queryDisplay = request.getParameter("queryDisplay");
+    String language = request.getParameter("language");
+    String inputType = request.getParameter("inputType");
+    String outputFormat = request.getParameter("outputFormat");
+    String[] outputTypesArray = request.getParameterValues("outputType");
+    String dictionary = request.getParameter("dictionary");
+    String normalization = request.getParameter("normalization");
+    String normalizationType = request.getParameter("normalizationType");
+    String resultPageNumber = request.getParameter("resultPageNumber");
+    String resultPageSize = request.getParameter("resultPageSize");
+    if (query == null) 
+      query = "a*";
+    boolean isRangeQuery = false; 
+    if (query.endsWith("*"))
+      isRangeQuery = true;
+    if (queryDisplay == null)
+      queryDisplay = query;
+    if (language == null)
+      language = "eng";
+    if (inputType == null || ! (inputType.equals("form") || inputType.equals("lemma")))
+      inputType = "form";
+    if (outputFormat == null || ! (outputFormat.equals("xml") || outputFormat.equals("html") || outputFormat.equals("htmlFragment")))
+      outputFormat = "xml";
+    ArrayList<String> outputTypes = new ArrayList<String>();
+    if (outputTypesArray == null) {
+      outputTypes.add("allCompact");
+    } else if (isRangeQuery) {
+      outputTypes.add("dictCompact");
+    } else {
+      outputTypes = new ArrayList<String>(Arrays.asList(outputTypesArray));
+    }
+    if (normalization == null || ! (normalization.equals("none") || normalization.equals("reg") || normalization.equals("reg norm")))
+      normalization = "norm";
+    if (normalizationType == null || ! (normalizationType.equals("display") || normalizationType.equals("dictionary")))
+      normalizationType = "dictionary";
+    String xmlDict = "all";
+    if (dictionary != null)
+      xmlDict = dictionary;
+    int pageNumber = 1;
+    int pageSize = 50;
+    if (resultPageNumber != null) 
+      pageNumber = new Integer(resultPageNumber);
+    if (resultPageSize != null) 
+      pageSize = new Integer(resultPageSize);
+    String xmlQueryString = "<query>";
+    xmlQueryString = xmlQueryString + "<name>" + query + "</name>";
+    xmlQueryString = xmlQueryString + "<display>" + queryDisplay + "</display>";
+    xmlQueryString = xmlQueryString + "<language>" + language + "</language>";
+    xmlQueryString = xmlQueryString + "<inputType>" + inputType + "</inputType>";
+    xmlQueryString = xmlQueryString +  "<outputFormat>" + outputFormat + "</outputFormat>";
+    xmlQueryString = xmlQueryString + "<outputTypes>" + outputTypes + "</outputTypes>";
+    xmlQueryString = xmlQueryString + "<dictionary>" + xmlDict + "</dictionary>"; 
+    xmlQueryString = xmlQueryString + "<normalization>" + normalization + "</normalization>";
+    xmlQueryString = xmlQueryString + "<normalizationType>" + normalizationType + "</normalizationType>";
+    if (isRangeQuery) {
+      xmlQueryString = xmlQueryString + "<resultPageNumber>" + pageNumber + "</resultPageNumber>";
+      xmlQueryString = xmlQueryString + "<resultPageSize>" + pageSize + "</resultPageSize>";
+    }
+    xmlQueryString = xmlQueryString + "</query>";
+    try {
+      if (outputFormat.equals("xml"))
+        response.setContentType("text/xml");
+      else if (outputFormat.equals("html") || outputFormat.equals("htmlFragment"))
+        response.setContentType("text/html");
+      else 
+        response.setContentType("text/xml");
+      PrintWriter out = response.getWriter();
+      if (query == null || query.isEmpty()) {
+        out.print("request parameter \"query\" is empty. Please specify a query.");
+        out.close();
+        return;
+      }
+      ArrayList<Lemma> lemmas = null;
+      ArrayList<Lexicon> dictionaries = null;
+      if (isRangeQuery) {
+        String queryTmp = query.substring(0, query.length() - 1); // without last star
+        if (dictionary != null)
+          dictionaries = lexHandler.getLexEntriesByLexiconBeginningWith(dictionary, queryTmp, pageNumber, pageSize);
+        else 
+          dictionaries = lexHandler.getLexEntriesBeginningWith(language, queryTmp, pageNumber, pageSize);
+      } else {
+        String lang = language;
+        if (dictionary != null) {
+          Lexicon lexicon = Lexica.getInstance().getLexicon(dictionary);
+          if (lexicon != null)
+            lang = lexicon.getSourceLanguage();
+        }
+        int normMode = Normalizer.DICTIONARY;
+        if (normalization.equals("none"))
+          normMode = Normalizer.NONE;
+        else if (normalizationType.equals("display"))
+          normMode = Normalizer.DISPLAY;
+        lemmas = lexHandler.getLemmas(query, inputType, lang, normMode, true);
+        dictionaries = lexHandler.getLexEntries(lemmas, lang, dictionary, query);
+      }
+      String baseUrl = ServletUtil.getInstance().getBaseUrl(request);
+      Date end = new Date();
+      String elapsedTime = String.valueOf(end.getTime() - begin.getTime());
+      String result = "";
+      if (outputFormat == null || outputFormat.equals("xml"))
+        result = createXmlOutputString(query, lemmas, dictionaries, outputTypes, baseUrl, xmlQueryString, elapsedTime);
+      else if (outputFormat.equals("html") || outputFormat.equals("htmlFragment"))
+        result = createHtmlOutputString(query, queryDisplay, language, lemmas, dictionaries, pageNumber, pageSize, isRangeQuery, outputFormat, outputTypes, elapsedTime);
+      else 
+        result = createXmlOutputString(query, lemmas, dictionaries, outputTypes, baseUrl, xmlQueryString, elapsedTime);
+      out.print(result);
+      out.close();
+    } catch (ApplicationException e) { 
+      throw new ServletException(e);
+    }
+  }
+
+  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+    doGet(request, response);
+  }  
+  
+  private String createXmlOutputString(String query, ArrayList<Lemma> lemmas, ArrayList<Lexicon> lexicons, ArrayList<String> outputTypes, String baseUrl, String xmlQueryString, String elapsedTime) {
+    boolean outputTypeMorphCompact = false; 
+    if (outputTypes.contains("allCompact") || outputTypes.contains("morphCompact"))
+      outputTypeMorphCompact = true;
+    boolean outputTypeMorphFull = false; 
+    if (outputTypes.contains("allFull") || outputTypes.contains("morphFull"))
+      outputTypeMorphFull = true;
+    boolean outputTypeDictCompact = false; 
+    if (outputTypes.contains("allCompact") || outputTypes.contains("dictCompact"))
+      outputTypeDictCompact = true;
+    boolean outputTypeDictFull = false; 
+    if (outputTypes.contains("allFull") || outputTypes.contains("dictFull"))
+      outputTypeDictFull = true;
+    boolean outputTypeWikiCompact = false; 
+    if (outputTypes.contains("allCompact") || outputTypes.contains("wikiCompact"))
+      outputTypeWikiCompact = true;
+    boolean outputTypeWikiFull = false; 
+    if (outputTypes.contains("allFull") || outputTypes.contains("wikiFull"))
+      outputTypeWikiFull = true;
+    String result = "<result>";
+    result = result + "<provider>" + "MPIWG MPDL language technology service (see: " + "" + baseUrl + "), Max Planck Institute for the History of Science, Berlin." + "</provider>";
+    result = result + xmlQueryString;
+    result = result + "<elapsed-time-ms>" + elapsedTime + "</elapsed-time-ms>";
+    if ((outputTypeMorphCompact || outputTypeMorphFull) && lemmas != null && ! lemmas.isEmpty()) {
+      result = result + "<morphology>";
+      for (int i=0; i<lemmas.size(); i++) {
+        Lemma lemma = lemmas.get(i);
+        String lemmaName = lemma.getLemmaName();
+        String language = lemma.getLanguage();
+        result = result + "<lemma>";
+        result = result + "<name>" + lemmaName + "</name>";
+        if (outputTypeMorphFull) {
+          String lemmaProvider = lemma.getProvider();
+          result = result + "<provider>" + lemmaProvider + "</provider>";
+          result = result + "<language>" + language + "</language>";
+        }
+        if (Language.getInstance().isArabic(language) || Language.getInstance().isLatin(language)) {
+          String remoteUrl = "http://www.perseus.tufts.edu/hopper/morph?l=" + lemmaName + "&amp;la=" + language;
+          result = result + "<remoteUrl>" + remoteUrl + "</remoteUrl>";
+        } else if (Language.getInstance().isGreek(language)) {
+          String remoteUrl = "http://www.perseus.tufts.edu/hopper/morph?l=" + lemmaName + "&amp;la=" + "greek";
+          result = result + "<remoteUrl>" + remoteUrl + "</remoteUrl>";
+        }
+        if (outputTypeMorphFull) {
+          ArrayList<Form> forms = lemma.getFormsList();
+          Collections.sort(forms);
+          if (forms != null && ! forms.isEmpty()) {
+            result = result + "<forms>";
+            for (int j=0; j<forms.size(); j++) {
+              result = result + "<form>";
+              Form f = forms.get(j);
+              String formName = f.getFormName();
+              String formProvider = f.getProvider();
+              result = result + "<provider>" + formProvider + "</provider>";
+              result = result + "<language>" + language + "</language>";
+              result = result + "<name>" + formName + "</name>";
+              result = result + "</form>";
+            }
+            result = result + "</forms>";
+          }
+        }
+        result = result + "</lemma>";
+      }
+      result = result + "</morphology>";
+    }
+    if ((outputTypeDictCompact || outputTypeDictFull) && lexicons != null) {
+      result = result + "<dictionaries>";
+      for (int i=0; i<lexicons.size(); i++) {
+        Lexicon lexicon = lexicons.get(i);
+        if (outputTypeDictFull)
+          result = result + lexicon.toXmlString();
+        else if (outputTypeDictCompact)
+          result = result + lexicon.toXmlStringCompact();
+      }
+      result = result + "</dictionaries>";
+    }
+    if ((outputTypeWikiCompact || outputTypeWikiFull) && lemmas != null && ! lemmas.isEmpty()) {
+      result = result + "<wikipedia>";
+      String language = null;
+      for (int i=0; i<lemmas.size(); i++) {
+        Lemma lemma = lemmas.get(i);
+        String lemmaName = lemma.getLemmaName();
+        language = Language.getInstance().getLanguageId(lemma.getLanguage());
+        result = result + "<article>";
+        result = result + "<name>" + lemmaName + "</name>";
+        String wikiHrefExact = "http://" + language + ".wikipedia.org/wiki/" + lemmaName;
+        String wikiHrefSearch = "http://" + language + ".wikipedia.org/wiki/index.php?search=" + lemmaName;
+        result = result + "<remoteUrl>" + wikiHrefExact + "</remoteUrl>";
+        result = result + "<remoteUrlSearch>" + wikiHrefSearch + "</remoteUrlSearch>";
+        result = result + "</article>";
+      }
+      if (language != null && Language.getInstance().isGerman(language) && query != null) {
+        String[] queryFormNames = query.split(" ");
+        for (int j=0; j<queryFormNames.length; j++) {
+          String queryFormName = queryFormNames[j];          
+          result = result + "<article>";
+          result = result + "<name>" + queryFormName + "</name>";
+          String wikiHrefExact = "http://" + language + ".wikipedia.org/wiki/" + queryFormName;
+          String wikiHrefSearch = "http://" + language + ".wikipedia.org/wiki/index.php?search=" + queryFormName;
+          result = result + "<remoteUrl>" + wikiHrefExact + "</remoteUrl>";
+          result = result + "<remoteUrlSearch>" + wikiHrefSearch + "</remoteUrlSearch>";
+          result = result + "</article>";
+        }
+      }
+      result = result + "</wikipedia>";
+    }
+    result = result + "</result>";
+    return result;
+  }
+  
+  private String createHtmlOutputString(String query, String queryDisplay, String language, ArrayList<Lemma> lemmas, ArrayList<Lexicon> lexicons, int pageNumber, int pageSize, boolean isRangeQuery, String outputFormat, ArrayList<String> outputTypes, String elapsedTime) {
+    boolean outputTypeMorphCompact = false; 
+    if (outputTypes.contains("allCompact") || outputTypes.contains("morphCompact"))
+      outputTypeMorphCompact = true;
+    boolean outputTypeMorphFull = false; 
+    if (outputTypes.contains("allFull") || outputTypes.contains("morphFull"))
+      outputTypeMorphFull = true;
+    boolean outputTypeDictCompact = false; 
+    if (outputTypes.contains("allCompact") || outputTypes.contains("dictCompact"))
+      outputTypeDictCompact = true;
+    boolean outputTypeDictFull = false; 
+    if (outputTypes.contains("allFull") || outputTypes.contains("dictFull"))
+      outputTypeDictFull = true;
+    boolean outputTypeWikiCompact = false; 
+    if (outputTypes.contains("allCompact") || outputTypes.contains("wikiCompact"))
+      outputTypeWikiCompact = true;
+    boolean outputTypeWikiFull = false; 
+    if (outputTypes.contains("allFull") || outputTypes.contains("wikiFull"))
+      outputTypeWikiFull = true;
+    String result = "";
+    result = result + "<html>";
+    result = result + "<head>";
+    result = result + "<title>WordInfo for: \"" + queryDisplay + "\"</title>";
+    result = result + "<link rel=\"stylesheet\" type=\"text/css\" href=\"/mpiwg-mpdl-cms-web/css/getDictionaryEntries.css\"/>";
+    result = result + getJavascriptFunctions();
+    result = result + "</head>";
+    result = result + "<body class=\"body\">";
+    result = result + "<table align=\"right\" valign=\"top\">";
+    result = result + "<td>[<i>This is a MPIWG MPDL language technology service</i>] <a href=\"/mpiwg-mpdl-cms-web/index.html\"><img src=\"/mpiwg-mpdl-cms-web/images/info.png\" valign=\"bottom\" width=\"15\" height=\"15\" border=\"0\" alt=\"MPIWG MPDL language technology service\"/></a></td>";
+    result = result + "</table>";
+    result = result + "<p/>";
+    result = result + "<div class=\"title\">WordInfo</div>";
+    
+    result = result + "<form name=\"getDictionaryEntries\" action=\"GetDictionaryEntries\" method=\"get\">";
+    result = result + "Query: <input name=\"query\" class=\"query\" type=\"text\" size=\"20\" value=\"" + query + "\"/>";
+    String htmlSelectBox = Language.getInstance().getHtmlSelectBox(language);
+    result = result + " Language: " + htmlSelectBox;
+    result = result + "<input type=\"hidden\" name=\"outputFormat\" value=\"" + outputFormat + "\"/>";
+    for (int i=0; i<outputTypes.size(); i++) {
+      String type = outputTypes.get(i);
+      result = result + "<input type=\"hidden\" name=\"outputType\" value=\"" + type + "\"/>";
+    }
+    result = result + " <button type=\"submit\" onclick=\"var query = document.getDictionaryEntries.query.value; if(query.substring(query.length-1, query.length) == '*') {document.getDictionaryEntries.outputType.value = 'dictCompact';}\">Query</button>";
+    result = result + "</form>";
+    result = result + "<hr/>";
+
+    if ((outputTypeMorphCompact || outputTypeMorphFull) && lemmas != null && ! lemmas.isEmpty()) {
+      result = result + "<span class=\"inputType\">Morphology</span>";
+      result = result + "<span  class=\"tree\">";
+      result = result + "<ul>";
+      result = result + "<li>" + "<b>" + "Lemmata" + "</b>";
+      result = result + "<ul>";
+      for (int i=0; i<lemmas.size(); i++) {
+        Lemma lemma = lemmas.get(i);
+        String lemmaName = lemma.getLemmaName();
+        String providerText = "";
+        String externalLinkText = "";
+        String formsText = "";
+        if (outputTypeMorphFull) {
+          String lemmaProvider = lemma.getProvider();
+          providerText = " (data provider: " + lemmaProvider + ")";
+        }
+        if (Language.getInstance().isArabic(language) || Language.getInstance().isLatin(language))
+          externalLinkText = " (external link: <a href=\"http://www.perseus.tufts.edu/hopper/morph?l=" + lemmaName + "&amp;la=" + language + "\">" + lemmaName + "</a>)";
+        else if (Language.getInstance().isGreek(language))
+          externalLinkText = " (external link: <a href=\"http://www.perseus.tufts.edu/hopper/morph?l=" + lemmaName + "&amp;la=" + "greek" + "\">" + lemmaName + "</a>)";
+        ArrayList<Form> forms = lemma.getFormsList();
+        Collections.sort(forms);
+        if (forms != null && ! forms.isEmpty()) {
+          formsText = formsText + "<ul>";
+          formsText = formsText + "<b>" + "Forms: " + "</b>";
+          for (int j=0; j<forms.size(); j++) {
+            Form f = forms.get(j);
+            String formName = f.getFormName();
+            String formProvider = f.getProvider();
+            formsText = formsText + formName + " (data provider: " + formProvider + "), ";
+          }
+          formsText = formsText.substring(0, formsText.length() - 2);  // without last comma and blank
+          formsText = formsText + "</ul>";
+        }
+        if (outputTypeMorphFull) {
+          result = result + "<li><input type=\"checkbox\" checked=\"checked\"/><label>" + lemmaName + providerText + externalLinkText + "</label>" + formsText + "</li>";
+        } else if (outputTypeMorphCompact) { 
+          result = result + "<li><input type=\"checkbox\"/><label>" + "<a href=\"GetDictionaryEntries?query=" + lemmaName + "&language=" + language + "&inputType=lemma" + "&outputFormat=html" + "&outputType=morphFull" + "\">" + lemmaName + "</a>" + providerText + externalLinkText + "</label>" + formsText + "</li>";
+        }
+      }
+      result = result + "</ul>";
+      result = result + "</li>";
+      result = result + "</ul>";
+      result = result + "</span>";
+    }
+    if ((outputTypeDictCompact || outputTypeDictFull) && lexicons != null && ! lexicons.isEmpty()) {
+      if (isRangeQuery) {
+        int pageNumberUp = 1;
+        if (pageNumber > 1)
+          pageNumberUp = pageNumber - 1;
+        int pageNumberDown = pageNumber + 1;
+        int from = (pageNumber * pageSize) - pageSize + 1;
+        int to = pageNumber * pageSize;
+        result = result + "<table align=\"right\">";
+        result = result + "<tr>";
+        result = result + "<td valign=\"middle\">Page: </td>";
+        result = result + "<td valign=\"middle\"><a href=\"/mpiwg-mpdl-cms-web/lt/GetDictionaryEntries?query=" + query + "&amp;language=" + language + "&amp;resultPageNumber=" + pageNumberUp + "&amp;outputFormat=html\"><img alt=\"page up\" src=\"/mpiwg-mpdl-cms-web/images/left.gif\" height=\"20\" width=\"20\"></a></td>";
+        result = result + "<td valign=\"middle\">" + pageNumber + "</td>";
+        result = result + "<td valign=\"middle\"><a href=\"/mpiwg-mpdl-cms-web/lt/GetDictionaryEntries?query=" + query + "&amp;language=" + language + "&amp;resultPageNumber=" + pageNumberDown + "&amp;outputFormat=html\"><img alt=\"page down\" src=\"/mpiwg-mpdl-cms-web/images/right.gif\" height=\"20\" width=\"20\"></a></td>";
+        result = result + "<td valign=\"middle\">(" + from + " - " + to + ")</td>";
+        result = result + "</tr>";
+        result = result + "</table>";
+      } 
+      result = result + "<span class=\"inputType\">Dictionary</span>";
+      result = result + "<span  class=\"tree\">";
+      result = result + "<ul>";
+      for (int i=0; i<lexicons.size(); i++) {
+        Lexicon lexicon = lexicons.get(i);
+        result = result + "<li>";
+        result = result + "<b>" + lexicon.getDescription() + "</b>";
+        result = result + "<ul>";
+        ArrayList<LexiconEntry> entries = lexicon.getEntries();
+        for (int j=0; j<entries.size(); j++) {
+          String entryContent = "";
+          LexiconEntry entry = entries.get(j);
+          if (lexicon.isLocalLexicon()) {
+            if (entry.isXmlValid()) {
+              String repairedEntry = entry.getRepairedEntry();
+              repairedEntry = repairedEntry.replaceAll("<repaired-entry>", "");
+              repairedEntry = repairedEntry.replaceAll("</repaired-entry>", "");
+              entryContent = entryContent + repairedEntry;  // valid unicode content of the original entry
+            } else {
+              entryContent = entryContent + "[Remark: <i> this dictionary entry has no valid XML/HTML content in database so a text version of this entry is shown.</i>]: <br/>";
+              String originalEntry = entry.getOriginalEntry();
+              originalEntry = originalEntry.replaceAll("<original-entry>", "");
+              originalEntry = originalEntry.replaceAll("</original-entry>", "");
+              originalEntry = StringEscapeUtils.escapeXml(originalEntry); // create text version of the invalid xml content
+              entryContent = entryContent + originalEntry;  
+            }
+            if (entry.getRemoteUrl() != null) {
+              entryContent = entryContent + "<div>(external link: <a href=\"" + entry.getRemoteUrl() + "\">" + entry.getFormName() + "</a>)</div>";          
+            }
+          } else {
+            if (entry.getRemoteUrl() != null) {
+              entryContent = entryContent + "external link: <a href=\"" + entry.getRemoteUrl() + "\">" + entry.getFormName() + "</a>";          
+            }
+          }
+          String formName = entry.getFormName();
+          String dictName = lexicon.getName();
+          if (outputTypeDictFull) {
+            result = result + "<li><input type=\"checkbox\" checked=\"checked\"/><label><b>" + formName + "</b></label><ul><li>" + entryContent + "</li></ul></li>";
+          } else if (outputTypeDictCompact) {
+            result = result + "<li><input type=\"checkbox\"/><label>" + "<a href=\"GetDictionaryEntries?query=" + formName + "&language=" + language + "&dictionary=" + dictName + "&inputType=lemma" + "&outputFormat=html" + "&outputType=dictFull" + "\">" + formName + "</a>" + "</label><ul><li>" + entryContent + "</li></ul></li>";
+          }
+        }
+        result = result + "</ul>";
+        result = result + "</li>";  // lexicon entry
+      }
+      result = result + "</ul>";
+      result = result + "</span>";
+    }
+    if ((outputTypeWikiCompact || outputTypeWikiFull) && lemmas != null && ! lemmas.isEmpty()) {
+      String langId = Language.getInstance().getLanguageId(language);
+      String wikiUrl = langId + ".wikipedia.org";
+      result = result + "<span class=\"inputType\">Wikipedia</span>";
+      result = result + "<span  class=\"tree\">";
+      result = result + "<ul>";
+      result = result + "<li>" + "<b>" + wikiUrl + "</b>";
+      result = result + "<ul>";
+      for (int i=0; i<lemmas.size(); i++) {
+        Lemma lemma = lemmas.get(i);
+        String lemmaName = lemma.getLemmaName();
+        String wikiHrefExact = "http://" + wikiUrl + "/wiki/" + lemmaName;
+        String wikiHrefSearch = "http://" + wikiUrl + "/wiki/index.php?search=" + lemmaName;
+        result = result + "<li><input type=\"checkbox\" checked=\"checked\"/><label>" + "External link: <a href=\"" + wikiHrefExact + "\">" + lemmaName + "</a> (or search for <a href=\"" + wikiHrefSearch + "\">" + lemmaName + "</a>)" + "</label>" + "</li>";
+      }
+      if (language != null && Language.getInstance().isGerman(language) && query != null) {
+        String[] queryFormNames = query.split(" ");
+        for (int j=0; j<queryFormNames.length; j++) {
+          String queryFormName = queryFormNames[j];          
+          result = result + "<li>";
+          String wikiHrefExact = "http://" + wikiUrl + "/wiki/" + queryFormName;
+          String wikiHrefSearch = "http://" + wikiUrl + "/wiki/index.php?search=" + queryFormName;
+          result = result + "<li><input type=\"checkbox\" checked=\"checked\"/><label>" + "External link: <a href=\"" + wikiHrefExact + "\">" + queryFormName + "</a> (or search for <a href=\"" + wikiHrefSearch + "\">" + queryFormName + "</a>)" + "</label>" + "</li>";
+          result = result + "</li>";
+        }
+      }
+      result = result + "</ul>";
+      result = result + "</li>";
+      result = result + "</ul>";
+      result = result + "</span>";
+    }
+    result = result + "<p/>";
+    result = result + "[* external links may not function]";
+    result = result + "<hr/>";
+    result = result + "<p/>";
+    result = result + "Elapsed time: " + elapsedTime + " ms, see the <a href=\"/mpiwg-mpdl-cms-web/index.html\">service description</a> of this page, if you find a bug <a href=\"https://it-dev.mpiwg-berlin.mpg.de/tracs/mpdl-project-software/newticket\">let us know</a>";
+    result = result + "</body>";
+    result = result + "</html>";
+    return result;
+  }
+
+  private String getJavascriptFunctions() {
+    String result = "<script type=\"text/javascript\">";
+    result = result + "<!-- ";
+    result = result + "function strEndsWith(str, suffix) {";
+    result = result + "  return str.match(suffix + \"$\") == suffix;";
+    result = result + "}";
+    result = result + " -->";
+    result = result + "</script>";
+    return result;
+  }
+}