<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.2//EN" "http://apache.org/forrest/dtd/document-v12.dtd">
<document>
<header>
 <title>MyCoRe Programmer Guide 2.1</title> 
</header>

<body>

 <section>
  <title>Allgemeines zur Implementierung</title>
  
   <section class="Struktur der Gesamtanwendung">
    <title>Struktur der Gesamtanwendung</title>
    <p>
    MyCoRe ist entgegen anderen Projekten kein monolitisches Objekt. Vielmehr wurde ein mehrstufiger Ansatz gewählt, um 
    die Vielfalt der Einsatzgebiete sinnvoll abzudecken. Dabei wird strikt zwischen allgemeingültigen Kernbestandteilen und 
    Funktionalitäten und der schlussendlichen Anwendung, welche ggf. mehrstufig sein kann, unterschieden. Innerhalb 
	dieser Bereiche gibt es wieder Teile, welche unabdingbar erforderlich sind und solche, die im Bedarfsfall in die 
	Endanwendung integriert werden können. Ziel der Struktur ist es, in der Anwendung nur noch das Archiv <em>mycore.jar</em>
	sowie die erforderlichen weiteren externen <em>*.jar</em> Dateien in die Anwendung integrieren zu müssen. Damit
	ist die Schnittstelle zwischen dem MyCoRe-Kern und den Anwendungen klar definiert. Details des Aufbaus und der Struktur
	des MyCoRe-Kerns und der Anwendung werden im nächsten Abschnitt detailliert behandelt. Sowohl die benötigte 
	<em>mycore.jar</em> Datei in ihrer entsprechenden Version wie auch die erforderlichen weiteren <em>*.jar</em>-Bibliotheken
	anderer Hersteller in den passenden Versionen werden über Maven-Repositories durch die Anwendung angefordert und integriert. 
    </p>
    
	<center>
    <img src="images/progguide_globalstructure_2_1.png" alt="Grundstruktur" title="Grundstruktur MyCoRe"/>
    </center>
    <p class="klein"><center><strong>Abbildung:</strong> Grundstruktur des MyCoRe-Projektes</center></p>
	   
  </section>
  
  <section>
   <title>Benutzte externe Bibliotheken</title>
   <p>
   Das MyCoRe-Projekt bemüht sich, bereits etablierte Techniken und Implementationen zu benutzen, um einerseits den 
   eigenen Entwicklungsaufwand so gering wie möglich zu halten, andererseits dem Nachnutzer den Einstieg durch die 
   Verwendung bekannter Komponenten zu erleichtern. 
   </p>
   <p>
   Der Folgende Abschnitt beschreibt alle eingesetzten Bibliotheken. Dabei ist die Lizenzpolitik der Hersteller sehr 
   unterschiedlich. Gemeinsam ist allen jedoch, dass sie den Open Source Gedanken vertreten und für nichtkommerzielle 
   Einsätze frei verfügbar sind. Die Nutzung von MyCoRe unter wirtschaftlichen Aspekten bedarf also einer gesonderten 
   Betrachtung der Lizenzrechte durch den Anwender. Ob hier Rechte verletzt werden, ist im Einzelfall abzuklären.
   </p>
   <table>
   <tr>
   <th width="20%" colspan="1" rowspan="1">Files</th>
   <th colspan="1" rowspan="1">Beschreibung</th>
   <th width="10%" colspan="1" rowspan="1">Lizenz</th>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">activation.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">ant-antlr-xxx.jar</td>
   <td colspan="1" rowspan="1">ANother Tool for Language Recognition.</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">ant-contrib.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">antlr-xxx.jar</td>
   <td colspan="1" rowspan="1">ANother Tool for Language Recognition.</td>
   <td align="center" colspan="1" rowspan="1"/>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">asm.jar</td><td colspan="1" rowspan="1">A Java bytecode manipulation framework.</td>
   <td align="center" colspan="1" rowspan="1">ASM</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">asm-attrs.jar</td>
   <td colspan="1" rowspan="1">A Java bytecode manipulation framework.</td>
   <td align="center" colspan="1" rowspan="1">ASM</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">avalon-framework-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">axis.jar</td>
   <td colspan="1" rowspan="1">Apache Axis is an implementation of the SOAP for Web services support</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">axis-ant.jar</td>
   <td colspan="1" rowspan="1">Apache Axis is an implementation of the SOAP for Web services support</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">batik.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">c3p0-xxx.jar</td>
   <td colspan="1" rowspan="1">c3p0 is an easy-to-use library for making traditional JDBC drivers "enterprise-ready" by augmenting them with 
   functionality defined by the jdbc3 spec and the optional extensions to jdbc2.</td>
   <td align="center" colspan="1" rowspan="1">LGPL</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">cglib-xxx.jar</td>
   <td colspan="1" rowspan="1">Byte Code Generation Library is high level API to generate and transform JAVA byte code. It is used by AOP, 
   testing, data access frameworks to generate dynamic proxy objects and intercept field access.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-beanutils.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - ?</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-collections-xxx.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - Extends or augments the Java Collections Framework.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-discovery-xxx.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - ?</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-fileupload-xxx.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - File upload capability for your servlets and web applications.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-httpclient-xxx.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - Framework for working with the client-side of the HTTP protocol.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-io-xxx.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - ?</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-lang-xxx.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - Provides extra functionality for classes in java.lang.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-logging.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - Wrapper around a variety of logging API implementations.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-logging-adapters-xxx.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - ?</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-logging-api-xxx.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - ?</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-net-xxx.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - Collection of network utilities and protocol implementations.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">commons-vfs-xxx-dev.jar</td>
   <td colspan="1" rowspan="1">Apache Jakarta Common - Virtual File System component for treating files, FTP, SMB, ZIP and such like as a 
   single logical file system.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">connector.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">dom4j-xxx.jar</td>
   <td colspan="1" rowspan="1">dom4j is an easy to use, open source library for working with XML, XPath and XSLT on the Java platform using the 
   Java Collections Framework and with full support for DOM, SAX and JAXP.</td>
   <td align="center" colspan="1" rowspan="1">W3C</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">ehcache-xxx.jar</td>
   <td colspan="1" rowspan="1">Ehcache is a widely used java distributed cache for general purpose caching, J2EE and light-weight containers.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">ezmorph-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">fckEditor.zip</td>
   <td colspan="1" rowspan="1">This HTML text editor brings to the web many of the powerful functionalities of desktop editors like MS Word. 
   It's lightweight and doesn't require any kind of installation on the client computer.</td>
   <td align="center" colspan="1" rowspan="1">LGPL</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">fop.jar</td>
   <td colspan="1" rowspan="1">A library to transform formatting objects.</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">lib/ftp.jar</td>
   <td colspan="1" rowspan="1">Java FTP client library.</td>
   <td align="center" colspan="1" rowspan="1">LGPL</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">hibernate3.jar</td>
   <td colspan="1" rowspan="1">Hibernate is a powerful, high performance object/relational persistence and query service.</td>
   <td align="center" colspan="1" rowspan="1">LGPL</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">hsqldb_xxx.jar</td>
   <td colspan="1" rowspan="1">Lightweight 100% Java SQL Database Engine.</td>
   <td align="center" colspan="1" rowspan="1">HS</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">icu4j_xxx.jar</td>
   <td colspan="1" rowspan="1">ICU is a mature, widely used set of Java libraries for Unicode support, software internationalization and 
   globalization (i18n/g11n).</td>
   <td align="center" colspan="1" rowspan="1">IBM</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">jai_codec.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">jai_core.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">jaxen-xxx.jar</td>
   <td colspan="1" rowspan="1">The Jaxen Java XPath Engine is an open source cross-API (DOM, JDOM, dom4j, and ElectricXML) XPath library for 
   Java.</td>
   <td align="center" colspan="1" rowspan="1"/>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">jaxrpc.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">jcifs-1.2.0.jar</td>
   <td colspan="1" rowspan="1">JCIFS is an Open Source client library that implements the CIFS/SMB networking protocol in 100% Java.</td>
   <td align="center" colspan="1" rowspan="1">LGPL</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">jdom-1.0.jar</td>
   <td colspan="1" rowspan="1">To provide a complete, Java-based solution for accessing, manipulating, and outputting XML data from Java code.</td>
   <td align="center" colspan="1" rowspan="1">JDOM</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">jid3lib-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">joda-time-xxx.jar</td>
   <td colspan="1" rowspan="1">Joda-Time provides a quality replacement for the Java date and time classes.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">jsch-xxx.jar</td>
   <td colspan="1" rowspan="1">JSch allows you to connect to an sshd server and use port forwarding, X11 forwarding, file transfer, etc., and 
   you can integrate its functionality into your own Java programs.</td>
   <td align="center" colspan="1" rowspan="1">BSD</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">json-lib-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">jta.jar</td>
   <td colspan="1" rowspan="1">JTA specifies standard Java interfaces between a transaction manager 
   and the parties involved in a distributed transaction system: the resource manager, the application server, and 
   the transactional applications.</td>
   <td align="center" colspan="1" rowspan="1">SUN</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">jtidy.jar</td>
   <td colspan="1" rowspan="1">We have two primary goals. First, to provide a home where all the patches and fixes that folks contribute can be 
   collected and incorporated into the program. Second, a library form of Tidy has been created to make it easier to 
   incorporate Tidy into other software.</td>
   <td align="center" colspan="1" rowspan="1">W3C</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">junit-xxx.jar</td>
   <td colspan="1" rowspan="1">JUnit is a regression testing framework written by Erich Gamma and Kent Beck. </td>
   <td align="center" colspan="1" rowspan="1">CPL</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">log4j-xxx.jar</td>
   <td colspan="1" rowspan="1">Inserting log statements into your code is a low-tech method for debugging it.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">lucene-analyzers-xxx.jar</td>
   <td colspan="1" rowspan="1">Apache Lucene is a high-performance, full-featured text search engine library written entirely in Java.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">lucene-core-xxx.jar</td><td colspan="1" rowspan="1">Apache Lucene is a high-performance, full-featured text search engine library 
   written entirely in Java.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">lucene-queries-xxx.jar</td><td colspan="1" rowspan="1">Apache Lucene is a high-performance, full-featured text search engine library 
   written entirely in Java.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">mail.jar</td>
   <td colspan="1" rowspan="1">The JavaMail API provides a platform-independent and protocol-independent framework to build mail and messaging 
   applications. </td>
   <td align="center" colspan="1" rowspan="1">SUN</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">metadata-extractor-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">mlibwrapper_jai.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">mysql-connector-java.jar</td>
   <td colspan="1" rowspan="1">The JDBC connector for MySQL. This will be used only if MySQL is installed.</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">opensaml-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">PDFBox-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">saaj.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">saxpath.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">serializer_xxx.jar</td>
   <td colspan="1" rowspan="1">This is a part of Xalan.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">servlet-api-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">tm-extractors-0.4.jar</td>
   <td colspan="1" rowspan="1">tm-extractors wraps the Word extraction from POI in a nice API.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">wsdl4j-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">wss4j.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">xalan_xxx.jar</td><td colspan="1" rowspan="1">The Apache Xalan Project is a collaborative software development project dedicated to 
   providing robust, full-featured, commercial-quality, and freely available XSLT support on a wide variety of 
   platforms.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">xercesImpl_xxx.jar</td>
   <td colspan="1" rowspan="1">The Xerces Java Parser 1.4.4 supports the XML 1.0 recommendation and contains advanced parser functionality, such 
   as support for the W3C's XML Schema recommendation version 1.0, DOM Level 2 version 1.0, and SAX Version 2, in 
   addition to supporting the industry-standard DOM Level 1 and SAX version 1 APIs.</td>
   <td align="center" colspan="1" rowspan="1">AL 2.0</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">xmlsec-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">xmltask-xxx.jar</td>
   <td colspan="1" rowspan="1">?</td>
   <td align="center" colspan="1" rowspan="1">?</td>
   </tr>
   </table>
   <p class="klein"><strong>Tabelle:</strong> Übersicht der benutzten externen Bibliotheken</p>
   
   <p>Lizenzen:</p>
   <ul>
   <li><strong>AL 2.0</strong> - Apache License Version 2.0, January 2004 <br/>
       <a target="_blank" href="http://www.apache.org/licenses/">http://www.apache.org/licenses/</a>
   </li>
   <li><strong>ASM</strong> - Copyright (c) 2000-2005 INRIA, France Telecom <br/>
       <a target="_blank" href="http://asm.objectweb.org/license.html">http://asm.objectweb.org/license.html</a>
   </li>
   <li><strong>BSD</strong> - Copyright (c) 2002,2003,2004,2005,2006 Atsuhiko Yamanaka, Jcraft,Inc.</li>
   <li><strong>CPL</strong> – Common Public License Version 1.0 <br/>
       <a target="_blank" href="http://www.oopensource/licenses/cpl.php">http://www.oopensource/licenses/cpl.php</a> 
   </li>
   <li><strong>HS</strong> - Copyright (c) 1995-2000 by the Hypersonic SQL Group. <br/>
       <a target="_blank" href="http://www.hsqldb.org/web/hsqlLicense.html">http://www.hsqldb.org/web/hsqlLicense.html</a> 
   </li>
   <li><strong>IBM</strong> – Special license for Open Soucre of IBM like LGPL</li>
   <li><strong>JDOM</strong> - Copyright (C) 2000-2002 Brett McLaughlin &amp; Jason Hunter. <br/>
       <a target="_blank" href="http://www.jdom.org/">http://www.jdom.org</a>
   </li>
   <li><strong>LGPL</strong> - GNU Library or Lesser General Public License 2.1 </li>
   <li><strong>SUN</strong> – Sun.com Terms of Use - <br/>
       <a target="_blank" href="http://www.sun.com/termsofuse.html">http://www.sun.com/termsofuse.html</a>
   </li>
   <li><strong>W3C</strong> - W3C® SOFTWARE NOTICE AND LICENSE Copyright © 1994-2001 World <br/>
       <a target="_blank" href="http://www.w3.org/Consortium/Legal/copyright-software-19980720">http://www.w3.org/Consortium/Legal/copyright-software-19980720
       </a>
   </li>
   </ul>
  </section>
  
  <section>
   <title>Allgemeine Festlegungen zur Struktur des MyCoRe-Kerns und der Anwendung</title>

   <section>
    <title>Definitionen</title>
	<ul>
     <li><strong>Common parts</strong> sind die Teile des MyCoRe-Kerns, welche von vielen/allen Komponenten und Modulen 
		 verwendet werden und die elementaren Grundfunktionalitäten von MyCoRe bereitstellen. U. a. beinhaltet 
		 dies die APIs zur Speicherung der Daten, Klassifikationen, der ACLs und Nutzer, Store-Zugriffe und Klassen, 
		 die allgemeiner Natur sind und als API-Funktionalitäten bereitgestellt werden (MCRServlet, XML-Parser usw.).</li>
     <li><strong>Components</strong> sind Teile des MyCoRe-Kerns welche als Funktionalität in sich abgrenzbar sind. Sie bauen 
		 auf den <strong>Common parts</strong> auf und enthalten alle zur Funktionalität gehörenden Klassen und Dateien. Alle 
		 Komponenten haben eine fest vorgegebene Struktur (siehe unten) und können über ein Property ausgeschaltet 
		 werden (wie bisher bei den Modulen des Kerns). Die in den Komponenten enthaltenen Vorlagen (Templates) 
		 können durch anwendungsseitige Dateien überschrieben werden.  Komponenten werden vom Entwickler-Team 
		 bereitgestellt und sind Bestandteil von mycore.jar. Komponenten werden über einen automatischen Prozess 
		 in die Anwendung integriert, wenn sie nicht explizit deaktiviert wurden.</li> 
     <li><strong>Modules</strong> sind austauschbare/abschaltbare Teile der Nutzeranwendung, welche alle wichtigen Dinge zur 
		 Gestaltung konkreter Anwendungen enthalten, die nicht als generisch anzusehen sind (Datenmodelle, statische 
		 Seiten, Layouts usw.). Module werden von den Anwendern entwickelt und bauen auf dem mycore.jar auf. Module 
		 können auch Komponenten überschreiben bzw. ergänzen. Die Dateibaumstruktur vom Modulen und Komponenten soll 
		 analog zueinander sein.</li>
	</ul>
   </section>

   <section>
    <title>Aufbau der Datei <em>mycore.jar</em></title>
    <p>
     Die Datei mycore.jar ist die Schnittstelle des MyCoRe-Kerns zu den Anwendungen. Eine Anwendung integriert 
   <strong>NUR</strong> diese Datei! Externe JAR-Files werden direkt über Maven von der Anwendung nachgeladen. Alle 
     Komponenten werden per default integriert, auszuschaltende Komponenten müssen in der Anwendung spezifiziert 
   werden. Welche Teile dabei von einer Komponente bei Nennung in der Konfiguration kopiert werden, zeigt die 
   Tabelle.
  </p>
     
    <table>    
    <tr>
    <th colspan="1" rowspan="1">Komponententeil</th>
    <th colspan="1" rowspan="1">Kopieren</th>
    </tr>
  <tr>
  <td colspan="1" rowspan="1">Java-Klassen</td>
    <td colspan="1" rowspan="1">werden immer kopiert </td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1">Stylesheets, Web-Seiten</td>
    <td colspan="1" rowspan="1">werden nur bei Auswahl kopiert </td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1">web.xml, I18N, properties</td>
    <td colspan="1" rowspan="1">werden nur bei Auswahl eingebunden</td>
    </tr>
    </table>
    <p class="klein"><strong>Tabelle:</strong> Verwendung der Komponententeile</p>
     
  <p>
     Der Aufbau der JAR-Datei für die JAVA-Klassen ist von uns nicht änderbar, sondern ergibt sich aus der 
   Package-Struktur. Für Hibernate Mappings ist es gängiger Standard, dass diese genauso heißen wie die 
   Klassen - mit der Endung <em>.hbm.xml</em> und in dem gleichen Package liegen, also zusammen mit den 
   <em>*.class</em>-Dateien. Eine Komponente in MyCoRe enthält Klassen, Webseiten, I18N-Dateien, Properties,
     Hibernate-Mappings, Stylesheets, XSD- und DTD-Dateien.
  </p>     
  <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
     mycore.jar 
       \ META-INF 
       \ \ Manifest.mf (mit Datums- und Revisionangabe) 
       \ org.mycore (alle Klassen) 
       \ xsl (alle Stylesheets) 
       \ components 
       | \ [component] 
       |   \ config (Konfigurationen / Templates) 
       |   | \ mycore.properties 
       |   | \ messages_de.properties 
       |   | \ messages_en.properties 
       |   \ web 
       |   | \ css 
       |   | \ images 
       |   | \ js 
       |   \ integrate.xml 
       \ *.dtd | *.xsd (alle DTD- und XSD-Schema-Dateien) 
       \ license.txt 
       \ integrate.xml 
  ]]>
    </p><![CDATA[
    ]]></source>    
    <p>
     <strong>Festlegungen</strong>
     <ul>
      <li>Die Dateien <em>messages_xx.properties</em> und <em>mycore.properties</em> werden erst durch die 
      Anwendung abhängig von den verwendeten Komponenten zusammengefügt.</li>
      <li>Bei Updates von einer Version zur nächsten ist es notwendig alte Libs (inkl der alten MyCoRe-Version) zu 
      entfernen, dafuer ist ein eigenes ant-target <em>ant resolve</em> vorhanden.</li>
     </ul>
    </p>
   </section>

   <section>
    <title>Die Struktur des mycore-Verzeichnisses</title>
    <p>
	Die Struktur des mycore-Verzeichnisses ergibt sich aus der Struktur der MyCoRe-JAR-Datei und der eines Maven-Projektes.
    </p>


	<source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    #####################################################
    # The component mycore.property file
    #####################################################
    
    MCR.[component-name].propertyName = ...
    ]]>
    </p><![CDATA[
    ]]></source>
   </section>

   <section>
    <title>Festlegungen für den Aufbau der Anwendung</title>
	   
	<ul>
     <li>Alle Anwendungsmodule sollten sich in ihrer Struktur an den Vorgaben für Komponenten orientieren. </li>
     <li>Der Mechanismus zur Integration der Komponenten in die Anwendung wird über ANT Tasks und entsprechende 
		 Targets realisiert. </li>
     <li>Die unten stehende Tabelle beschreibt die Integrationspunkte an Hand der öffentliche Targets, die eine 
		 Anwendung haben muss. </li>
     <li>Komponenten muessen explizit ausgeschalten werden via <strong>MCR.Components.Exclude</strong>.</li>
     <li>Die ImageViewer-Komponente ist ebenfalls per default aktiviert und prüft selbst, ob die entsprechenden 
		 Klassen verfügbar sind oder nicht. </li>
     <li>Alle I18N Properties haben eine feste Namenskonvention (siehe oben). Zur Anpassung an ältere Codestände 
		 gibt es einen <em>deprecated.properties</em> Mechanismus, so dass die Umbenennung ohne zwingenden 
		 Migrationsaufwand machbar ist.</li>
     <li>Alle I18N-Properties eines Modules haben den Namen modul.[modul-name].xxx </li>
     <li>Alle Properties eines Modules haben den Namen MCR.[modul-name].xxx . </li>
	</ul>
	
	<table>
     <tr>
     <th width="20%" colspan="1" rowspan="1">Target</th>
     <th colspan="1" rowspan="1">Beschreibung</th>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">clean</td>
     <td colspan="1" rowspan="1">Löscht die Programmdaten der Anwendung.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">clean.data</td>
     <td colspan="1" rowspan="1">Löscht <strong>ALLE</strong> Daten der Anwendung.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">clean.libs</td>
     <td colspan="1" rowspan="1">Löscht alle benutzten *.jar Archive aus der Anwendung.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">create.class</td>
     <td colspan="1" rowspan="1">Initialisiert oder update der Klassifikationen.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">create.default-rules</td>
     <td colspan="1" rowspan="1">Setzt die Standard-ACLs (ist in create.users enthalten).</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">create.jar </td>
     <td colspan="1" rowspan="1">Läd und erzeugt alle erforderlichen *.jar Dateien.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">create.schema</td>
     <td colspan="1" rowspan="1">Erzeugt alle XML-Schema Dateien.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">create.scripts</td>
     <td colspan="1" rowspan="1">Zusammensetzen der Konfigurationen und Zusammenbau aller für die Arbeit mit dem CLI wichtigen Teile.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">create.searchmask</td>
     <td colspan="1" rowspan="1">Generiert eine Suchmaske.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">create.users </td>
     <td colspan="1" rowspan="1">Initialisiert das Benutzersystem. (Nur einmal verwenden!)</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">create.war</td>
     <td colspan="1" rowspan="1">Erzeugt ein WAR-Archiv der Anwendung.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">create.webapp</td>
     <td colspan="1" rowspan="1">Baut die Web-Anwendung zusammen.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">info</td>
     <td colspan="1" rowspan="1">Listet allgemeine Informationen zum Build-Prozess.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">javadoc</td>
     <td colspan="1" rowspan="1">Erzeugt Javadocs.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">resolve</td>
     <td colspan="1" rowspan="1">Löscht alle Bibliotheken und installiert mittels Maven und der config/pom.xml alle neu</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">usage</td>
     <td colspan="1" rowspan="1">Listet öffentliche Targets (diese hier).</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">webservice.deploy</td>
     <td colspan="1" rowspan="1">Macht die WebServices bekannt.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">webservice.undeploy</td>
     <td colspan="1" rowspan="1">Entfernt die WebServices.</td>
     </tr>
	</table>
    <p class="klein"><strong>Tabelle:</strong> Application integration targets</p>
	
	<table>
     <tr>
     <th width="20%" colspan="1" rowspan="1">Target</th>
     <th colspan="1" rowspan="1">Beschreibung</th>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">init</td>
     <td colspan="1" rowspan="1">Initialisiert Build-Umgebung.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">compile</td>
     <td colspan="1" rowspan="1">Compiliert alle Java-Programme.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">config</td>
     <td colspan="1" rowspan="1">Kopiert wichtige Konfigurationen nach build/config.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">i18n</td>
     <td colspan="1" rowspan="1">Zusammenfügen der Properties für einzelne Sprachen.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">genkey</td>
     <td colspan="1" rowspan="1">Erzeugt die Signatur für Applets - wird implizit von create.webapp aufgerufen.</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"/>
     <td colspan="1" rowspan="1">weitere Targest zur Unterstützung von SVN </td>
     </tr>
	</table>
    <p class="klein"><strong>Tabelle:</strong> Application internal targets</p>
   </section>
   
   <section>
    <title>Antwendungs-Module als JAR-Datei</title>
    <p>
      Anwendungsmodule können seit DocPortal 2.1 nicht nur im "modules"-Verzeichnis existieren, sondern
      auch als JAR-Datei eingebunden werden. Das geschieht über das "maven"-Modul, dass dafür in der
      <code>mycore.private.properties</code> Datei unter <code>MCR.Modules.Application</code> eingetragen
      werden muss.
    </p>
    <p>
      Die Anwendungs-Module sind im Aufbau ähnlich den MyCoRe-Komponenten, d.h. sie enthalten alle Dateien
      die zur Build-Zeit und zur Laufzeit benötigt werden. Erkannt werden die JAR-Dateien an ihrem Manifest
      und Eigenschaft <code>MCR-Application-Module</code>, die den Namen des Moduls enthält.
      Über <code>ant resolve</code> werden alle Module unter <code>build/modules</code> entpackt.
      Dort werden aber nur die Verzeichnisse <code>classifications</code>, <code>config</code> und <code>web</code> entpackt.
    </p>
  <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
     application-module.jar 
       \ META-INF 
       \ \ Manifest.mf (mit Datums- und Revisionangabe) 
       \ (alle Klassen) 
       \ xsl (alle Stylesheets)
       \ classifications (evtl. Klassifikationen) 
       \ config 
       | \ [module] 
       |   \ mycore.properties 
       |   \ messages_de.properties 
       |   \ messages_en.properties
       |   \ build.xml
       |   \ build.properties
       \ web 
       \ *.dtd | *.xsd (alle DTD- und XSD-Schema-Dateien) 
  ]]>
    </p><![CDATA[
    ]]></source>
    
    <p>
     Die <code>build.xml</code> wird nur benötigt, wenn die targets <code>create.users</code>,
     <code>create.default-rules</code> erweitert werden sollen oder wenn <code>create.webapp</code>
     zusätzlich zum einfachen Kopieren der Daten aus dem <code>web</code>-Verzeichnis noch Aktionen
     ausführen soll.
    </p>
    
    <p>
      In <code>build.properties</code> können Properties definiert werden, die beim Einbinden
      von Kommandos und XSL-Dateien helfen:
      <table>
        <tr>
          <td colspan="1" rowspan="1">internal.commands</td>
          <td colspan="1" rowspan="1">
           Kommaseparierte Liste von Kommandoklassen
          </td>
        </tr>
        <tr>
          <td colspan="1" rowspan="1">xsl.include</td>
          <td colspan="1" rowspan="1">
           Kommaseparierte Liste von XSL-Dateien, die bei jeder Web-Seite eingebunden werden sollen
          </td>
        </tr>
      </table>
    </p>
    <p>
     Ein großer Unterschied zu Modulen im moduldes-Verzeichnis ist, dass bei der JAR-Datei kein
     Build-Prozess mehr laufen muss, sondern nur noch ein Integrationsprozess, weswegen Java-Class- und
     Schema-Dateien schon fertig erzeugt in der JAR-Datei liegen.
    </p>
    <p>Beispiele für Anwendungsmodule, die mittels Maven erstellt werden, finden sie hier:
    <ul>
     <li><a href="http://www.mycore.de/viewvc/viewvc.cgi/maven/iview2-preview/trunk/?pathrev=19149">ImageViewer 2 Vorschau</a></li>
     <li><a href="http://dev.thulb.uni-jena.de/viewvc/archive/trunk/maven-modules/archive/?pathrev=3086">Archiv-Anwendung der Thüringer Universitäts- und Landesbibliothek</a></li>
    </ul>
    </p>
   </section>

  </section>
  
	  
  <section>
   <title>Das Datenmodell-Konzept allgemein</title>
   <p>
    Das MyCoRe-Datenmodell kennt im seiner Grundkonzeption drei Komponenten. Zum einen gibt es <strong>Metadaten</strong>. Sie 
    enthalten nur beschreibende Daten sowie ggf. strukturelle und organisatorische Informationen zu einem Datenobjekt. 
    Dabei ist es nicht relevant, ob die Metadaten alleine stehen oder mit einem Anhang eines digitalen Objektes versehen 
    werden sollen. Beispielsweise können Personendaten alleine existieren und die sie referenzierenden Dokumente 
    besitzen noch zugeordnete digitale Objekte (Bilder, Dokumente, Videos usw.). Diese digitalen Objekte werden in MyCoRe als 
    <strong>Derivate</strong> bezeichnet, da ein Objekt ggf. in mehreren Darstellungsvarianten an den selben Metadatensatz angebunden 
    werden kann. Ein Derivat seinerseits besteht aus einem XML-Datensatz, welcher für den Im- und Export sowie die
	Präsentation der digitalen Objekte benötigt wird sowie den eigentlichen Daten in Form von Einzeldateien oder Dateibäumen.
	Im XML der Derivate wird zukünftig auch optional das METS-Format als Tag mit abgelegt. So wird eine direkte Nutzung von
	Bildbetrachtern wie dem DFG-Viewer einfach integrierbar sein. Die dritte Art von Daten stellen <strong>Klassifikationen</strong> (in Bibliothekskreisen auch als Normdateien bezeichnet) dar. Sie 
    definieren Sammlungen feststehender Begriffe auf die seitens der anderen Metadaten referenziert werden kann. 
    </p>
    <p>
    Die Verknüpfung der Metadaten untereinander und zu den Klassifikationen erfolgt mittels einer einheitlichen ID. Für 
    Klassifikationen kommt hierzu noch die Kategorie-ID. Der Syntax einer MyCoReID - im Programmiergebrauch die Klasse
	MCRObjectID - hat folgenden Syntax:
    </p>
	<p>
	<center><strong><code>ProjectID_Type_Number</code></strong></center>
	</p>
	<p>
	<center>
	<table>
	<tr><td colspan="1" rowspan="1">ProjectID</td><td colspan="1" rowspan="1">String</td><td colspan="1" rowspan="1">It describes the special project type like MyProject, CollectionA or so.</td></tr>
	<tr><td colspan="1" rowspan="1">Type</td><td colspan="1" rowspan="1">String</td><td colspan="1" rowspan="1">This is the datamodel type like document, author, ... The types <strong>class</strong> and <strong>derivate</strong> ar fix.</td></tr>
	<tr><td colspan="1" rowspan="1">Number</td><td colspan="1" rowspan="1">Integer</td><td colspan="1" rowspan="1">This is the dataset number. It is a number as String and it is a good idea to use leading zeros like 00000001. In practices we use 8 digits.</td></tr>
	</table>
	<p class="klein"><strong>Tabelle:</strong> Syntax of the MCRObjectID</p>
	</center>
	</p>
    <p>
    Das Datenmodell ist durch seine Gestaltung in XML-Strukturen so angelegt, dass es leicht möglich ist, Informationen 
    in mehreren Sprachen gemeinsam abzulegen. Hierfür wird konsequent eine Kodierung mit UTF-8 angewendet. Bei 
    zunehmender Globalisierung ist die Mehrsprachigkeit für viele Projekte zwingend erforderlich. Auch die 
    Klassifikationen können mehrsprachig gespeichert werden. 
    </p>
    
     <img src="images/datenmodell.png" alt="Datenmodell-Graphik" title="Grundstruktur MyCoRe"/>
           
   </section>
   
   <section>
    <title>Das Vererbungsmodell</title>
     <p>
     In MyCoRe ist innerhalb des Datenmodells für die Metadaten die Möglichkeit einer Vererbung vorgesehen. Diese ist 
     fest in den Kern implementiert und wird ausschließlich durch die steuernden Metadaten des jeweiligen Datensatzes 
     festgelegt. Das heißt, für eine Datenmodell-Definition (z.B. document) können Datensätze mit (Buch mit Kapiteln) 
     und ohne (Dokument) nebeneinander eingestellt werden. Wichtig ist nur, dass die Vererbung nur innerhalb eines 
     Datenmodells oder eines, welches die gleiche Struktur aufweist, jedoch andere Pflichtfelder hat, funktioniert. 
     Vererbung zwischen Datenmodellen mit verschieden Metadaten ist ausgeschlossen.
     </p>
     <p>
     Im Folgenden soll die Vererbung anhand der XML-Syntax zweier Metadaten-Objekte verdeutlicht werden. Beim Laden der 
     Daten wird dann eine Eltern-Kind-Beziehung im System aufgebaut und abgespeichert.
     </p>
     <p>
     Die beiden Datensätze (Abbildung 1.2 und 1.3) sollen folgendes Szenario widerspiegeln:
     </p>
     <ul>
     <li>Der Titel soll für die Kind-Daten übernommen werden und durch diese um die Kapitelüberschriften ergänzt werden.</li>
     <li>Die Autorendaten sind an alle Kinder zu vererben.</li>
     <li>Der Umfang des Werkes ist je nach Stufe anzugeben, also für das gesamte Buch die Gesamtzahl der Seiten und für 
     ein Kapitel die Anzahl dessen Seiten.</li>
     </ul>
     
     <img src="images/metadata.png" alt="Metadaten-Objekt-Auszug" title="Metadaten-Objekt-Auszug"/>
     <p class="klein"><strong>Abbildung 1.2:</strong> Auszug aus dem Metadaten-Objektes des Elternsatzes</p>  
    
     <p>Entscheidend für die Umsetzung sind folgende Dinge:</p>
     <ul>
     <li>Das Attribut <code>heritable</code> sagt, ob ein Metadatum vererbbar (<code>true</code>) oder nicht 
     (<code>false</code>) sein soll.</li>
     <li>Das Attribut <code>notinherit</code> sagt, ob das Metadatum von dem Elterndatensatz nicht geerbt werden soll 
     (<code>true</code>). Andernfalls wird geerbt (<code>false</code>).</li>
     <li>Es muss erst der Elterndatensatz eingespielt werden. Anschließend können die Kinddatensätze der nächsten 
     Vererbungsebene eingespielt werden. Enkeldatensätze folgen darauf, usw. Bitte beachten Sie das unbedingt beim 
     Restore von Sicherungen in das System. MyCoRe ergänzt intern die Daten der Kind-Datensätze für die Suchanfragen um 
     die geerbten Daten.</li>
     <li>Das Attribut <code>inherited</code> ist per Default auf <code>0</code> gesetzt und beschreibt die Anzahl der 
     geerbten Daten. Das Attribut wird vom System automatisch gesetzt. Kinder erhalten, wenn sie Daten geerbt haben, 
     <code>inherited=1</code> usw., je nach Stufe.</li>
     </ul>
     
     <img src="images/metadata_children.png" alt="Metadatenobjekt-Auszug" title="Metadaten-Objekt-Auszug"/>
     <p class="klein"><strong>Abbildung 1.3:</strong> Auszug aus dem Metadaten-Objektes des Kindsatzes</p>  
    
     
     <p>
     Die Ausgabe des Eltern-Datensatzes nach einer Query entspricht dem der Dateneingabe, lediglich im 
     XML-<code>structure</code>-Teil wurde ein Verweis auf die Kinddaten eingetragen (siehe XML-Syntax im User Guide).
     </p>
     
     <img src="images/metadata_query.png" alt="Metadaten-Objekt-Auszug" title="Metadaten-Objekt-Auszug"/>
     <p class="klein"><strong>Abbildung 1.4:</strong> XML-Syntax eines Kind-Datensatzes als Query-Resultat</p>  
    
     
     <p>
     Die Abbildung 1.4 zeigt den Kind-Datensatz, wie er vom System nach einer erfolgreichen Anfrage im 
     Resultats-Container zurückgegeben wird. Dabei ist deutlich die Funktionalität der MyCoRe-Vererbungsmechanismen 
     zu erkennen.
     </p>
    </section>
    
   </section>
   
 <section>
  <title>Funktionsprinzipien und Implementierungen von Kernkomponenten</title>
  
  <section>
   <title>Allgemeine Klassen / Exception-Modell / MCRCache</title>
   
   <section>
    <title>Allgemeine Klassen</title>
    <p>
    Wie in jedem Projekt, so gibt es auch in MyCoRe allgemein verwendete Klassen. Diese sind im Paket 
    <code>org.mycore.common</code> und den dort befindlichen Unterpaketen platziert. Hier finden Sie Klassen für
    </p>
    <ul>
    <li>die Behandlung des MyCoRe-internen EventHandler-Systems,</li>
    <li>die Behandlung und den Umgang mit XML-Daten,</li>
    <li>Ausnahmebehandlungen,</li>
    <li>Caches,</li>
    <li>MyCoRe-Sessions und</li>
    <li>weitere nützliche Funktionen.</li>
    </ul>
    <p>
    In den JavaDocs können Sie sich leicht einen Überblick der implementierten Klassen und Methoden verschaffen.
    </p>
   </section>
   
   <section>
    <title>Exception Modell</title>
     <p>
     MyCoRe nutzt zwei verschiedene Exception-Modelle, die hier kurz erläutert werden sollen. Hinsichtlich der 
     Funktionen und Methoden der Exceptions sollten Sie die JavaDocs des MyCoRe-Projektes konsultieren.
     </p>
     <ul>
     <li>MCRException und alle davon abgeleiteten Klassen. Diese Exception-Klasse ist von der Java-Klasse 
         RuntimeException abgeleitet und kann damit Ausnahmezustände nach außen tragen.
     </li>
     <li>Die MCRCatchException ist hingegen von der Java-Klasse Exception abgeleitet und muss auch jeden Fall 
         abgefangen werden.
     </li>
     </ul>
    </section>
    
   </section>
   
    <anchor id="session_2_1"/>
    <section>
     <title>Die Session-Verwaltung</title>
     <p>Mehrere BenutzerInnen (oder allgemeiner Prinzipale) können gleichzeitig Sitzungen mit dem MyCoRe-Softwaresystem 
     eröffnen. Während einer Sitzung werden in der Regel nicht nur eine, sondern mehrere Anfragen bearbeitet. Es ist 
     daher sinnvoll, kontextspezifische Informationen wie die UserID, die gewünschte Sprache usw. für die Dauer der 
     Sitzung mitzuführen. Da das MyCoRe-System mit mehreren gleichzeitigen Sitzungen konfrontiert werden kann, die zudem 
     über verschiedene Zugangswege etabliert sein können (z.B. Servlets, Kommandozeilenschnittstelle oder Webservices), 
     muss das System einen allgemein verwendbaren Kontextwechsel ermöglichen.
     </p>
     <p>
     Bei der Bearbeitung einer Anfrage oder Transaktion muss nicht jede einzelne Methode oder Klasse Kenntnis über die 
     Kontextinformationen besitzen. Daher ist es sinnvoll, die Übergabe des Kontextes als Parameter von Methode zu 
     Methode bzw. von Klasse zu Klasse zu vermeiden. Eine Möglichkeit, dies zu bewerkstelligen ist der Einsatz von sog. 
     Thread Singletons oder thread-local Variablen. Die Idee dabei ist, den Thread der den Request bearbeitet als 
     Repräsentation des Request selbst anzusehen. Dazu müssen die Kontextinformationen allerdings an den Thread 
     angebunden werden, was seit Java 1.2 mit Hilfe der Klassen <code>java.lang.ThreadLocal</code> bzw. 
     <code>java.lang.InheritableThreadLocal</code> möglich ist. Jeder Thread hat dabei seine eigene unabhängig 
     initialisierte Kopie der Variable. Die <code>set()</code> und <code>get()</code> Methoden der Klasse 
     <code>ThreadLocal</code> setzen bzw. geben die Variable zurück, die zum gerade ausgeführten Thread gehört. Die 
     Klassen der Sessionverwaltung von MyCoRe sind auf Basis dieser Technologie implementiert (siehe Abbildung 1.5).
     </p>
     
     <img src="images/progguide_2session_classes.jpg" alt="Sessionverwaltungs-Klassen" title="Sessionverwaltungs-Klassen"/>
     <p class="klein"><strong>Abbildung 1.5:</strong> Die Klassen der Sessionverwaltung</p>  
         
     <p>
     Klienten der Sessionverwaltung sind alle Klassen, die Kontextinformationen lesen oder modifizieren wollen, wie zum 
     Beispiel <code>MCRCommandLineInterface</code> und <code>MCRServlet</code>. Kontextinformationen werden als Instanzen 
     der Klasse <code>MCRSession</code> abgelegt. Diese Klasse bietet Methoden zum Setzen und Lesen der Informationen, 
     wie z.B. der UserID der aktuellen Benutzerin, der gewünschten Sprache usw.
     </p>
     <p>
     Die Klasse <code>MCRSession</code> besitzt einen statischen Cache, realisiert durch die Klasse <code>MCRCache</code>. 
     Bei der Konstruktion einer Instanz von <code>MCRSession</code> wird zunächst über die Methode 
     <code>buildSessionID()</code> eine eindeutige Id erzeugt und diese als Schlüssel zusammen mit dem Session-Objekt 
     selbst im Cache abgelegt. Auf diese Weise hat man über die statische Methode <code>getSession()</code> Zugriff auf 
     die zu einer bestimmten SessionID gehörende Instanz.
     </p>
     <p>
     Damit die Instanzen von <code>MCRSession</code> als thread-local Variablen an den aktuellen Thread angebunden 
     werden können, werden sie nicht direkt, sondern über die statische Methode <code>getCurrentSession()</code> der 
     Klasse <code>MCRSessionMgr</code> erzeugt und später gelesen. Beim ersten Aufruf von <code>getCurrentSession()</code> 
     in einem Thread wird über die von <code>java.lang.ThreadLocal</code> erbende, statische innere Klasse 
     <code>ThreadLocalSession</code> gewährleistet, dass eine eindeutige Instanz von <code>MCRSession</code> erzeugt und 
     als thread-local Variable abgelegt wird. Der Zugriff auf die thread-local Variablen eines Threads kann nur über die 
     Klasse <code>ThreadLocal</code> (bzw. <code>InheritableThreadLocal</code>) erfolgen. Auf diese Weise ist 
     sichergestellt, dass bei nachfolgenden Aufrufen von <code>getCurrentSession()</code> genau die zum aktuellen Thread 
     gehörende Referenz auf die Instanz von <code>MCRSession</code> zurückgegeben wird.
     </p>
     <p>
     Mit der statischen Methode <code>MCRSessionMgr.setCurrentSession()</code> ist es möglich, ein bereits vorhandenes 
     Session-Objekt explizit als thread-local Variable an den aktuellen Thread zu binden. Dies ist z.B. In einer 
     Servlet-Umgebung notwendig, wenn die Kontextinformationen in einem Session-Objekt über eine http-Session mitgeführt 
     werden. (Aktuelle Servlet-Engines verwenden in der Regel zwar Thread-Pools für die Bearbeitung der Requests, aber 
     es ist in keiner Weise sichergestellt, dass aufeinanderfolgende Requests mit dem selben Kontext wieder den selben 
     Thread zugewiesen bekommen. Daher muss der Kontext in einer http-Session gespeichert werden.)
     </p>
     <p>
     Die Methode <code>MCRSessionMgr.releaseCurrentSession()</code> sorgt dafür, dass das thread-local Session-Objekt 
     eines Threads durch ein neues, leeres Objekt ersetzt wird. Dies ist in Thread-Pool-Umgebungen wichtig, weil es 
     sonst möglich bzw. sogar wahrscheinlich ist, dass Kontextinformationen an einem Thread angebunden sind, dieser 
     Thread aber bei seiner Wiederverwendung in einem ganz anderen Kontext arbeitet. Code-Beispiele zur Verwendung der 
     Session-Verwaltung finden sich in <code>org.mycore.frontend.servlets.MCRServlet.doGetPost()</code>.
     </p>
     
     <section>
      <title>Variablenwerte in der Session speichern</title>
      <p>
      Sie können über den Webclient (Browser) Werte in der aktuellen Session speichern. Sie können so über einen Link 
      (URL, HTTP GET) oder das Absenden eines Formulars (HTTP POST) einen Wert an den Server senden, der dann in der 
      Session abgelegt wird. Dazu muss die folgende Syntax für den HTTP Request Parameter verwendet werden:
      </p>
      <p class="break"><code>XSL.&lt;name&gt;.SESSION=&lt;wert&gt;</code></p>
      <p>z.B.</p>
      <p class="break"><code>http://.../seite.xml?XSL.mode.SESSION=active</code></p>
      <p>In der MCRSession wird so z.B. der Variablenwert mode=active abgelegt. Sie können dann in Java-Code über</p>
      <p class="break"><code>MCRSessionMgr.getCurrentSession().get(“mode“)</code></p>
      <p>
      darauf zugreifen, oder in einem beliebigen Stylesheet diese Variable verwenden. Dazu muss sie im Kopf des 
      Stylesheets deklariert werden:
      </p>
      <p class="break"><code>&lt;xsl:param name=“mode“ /&gt;</code></p>
     </section>
     
    </section>
    
    <section>
     <title>Das EventHandler-Modell</title>
     <p>
     Mit Version 1.2 wurde in die MyCoRe-Implementierung ein EventHandler-Basispaket integriert. Ziel ist es, eine 
     bessere Trennung der Code-Schichten des Datenmodells und der Backends zu erreichen. Im Datenmodell sollen nur noch 
     Ereignisse ausgelöst werden (z.B. create, delete usw.), welche dann bestimmt durch die Konfiguration in den 
     Property-Dateien verarbeitet werden. Es soll ein allgemein gültiges Template-Modell existieren, welches für die 
     erforderlichen Anwendungsfälle ausgebaut werden kann. Ein singleton-Manager-Prozess nimmt nur ein Ereignis 
     entgegen, wählt die dafür bestimmte Konfiguration aus und startet die Methode 
     <code>doHandleEvent(MCREvent evt)</code>. Dies geschieht in der Reihenfolge, welche in der Konfiguration angegeben 
     ist und stellt ein Pipeline-Verfahren dar. Das Event-Objekt wird dabei nacheinander an die Handler durchgereicht. 
     Änderungen an den im Event-Objekt gespeicherten Daten werden also für alle folgenden Handler wirksam. Kommt es bei 
     einem Handler zu einer Ausnahme, so wird diese vom Manager aufgefangen und es wird für alle in der Pipeline davor 
     liegenden Handler die Methode <code>undoHandleEvent(MCREvent evt)</code> initiiert. Somit ist ein Rollback möglich. 
     Je nach Anwendung ist es möglich, verschiedene Pipelines für unterschiedliche Abläufe unabhängig voneinander zu 
     implementieren, z.B. eine Pipeline für die Verarbeitung der Metadaten und eine andere für die Volltextindizierung 
     der Dokumente. Die Pipelines und die damit verbundenen Ereignisse unterscheiden sich am Namen der jeweiligen 
     Pipeline.
     </p>
     
     <section>
      <title>Das EventHandler-Modell am Beispiel der Metadaten-Objekte</title>
      <p>
      Das EventHandler-Modell wird beispielsweise eingesetzt, um Objekte vom Typ MCRObject persistent zu speichern. 
      Das Klassendiagramm (Abbildung 1.6) verdeutlicht die Zusammenhänge.
      </p>
      <ol>
      <li>Das <code>MCRObject</code> ruft in MyCoRe-Version 1.2 zuerst eine Persistence-Layer-Implementierung nach alter 
      Konzeption auf. Hier wurde zur Nutzung des EventHandlers eine Dummy-Klasse <code>MCRDummySearchStore</code> 
      geschaffen, welche keine Funktionalität ausführt.</li>
      <li>Anschließend wird von <code>MCRObject</code> ein neues Ereignis erzeugt, welches in diesem Fall die 
      vordefinierte Pipeline <code>OBJECT_TYPE</code> und das vordefinierte Ereignis <code>CREATE_EVENT</code> nutzt. 
      Es können aber auch beliebige Strings eingetragen werden. Dabei ist aber auf die Konsistenz zu achten.<br/>
      <code>MCREvent evt = new MCREvent(MCREvent.OBJECT_TYPE, MCREvent.CREATE_EVENT);</code></li>
      <li>Nun wird dem neuen Ereignis das Datum übergeben, welches an die Handler weitergereicht werden soll. Ein 
      Ereignis kann auch mehrere Daten beinhalten.<br/>
      <code>evt.put("object",this);</code>      
      <img src="images/progguide_eventhandler.png" alt="Klassendiagramm" title="Klassendiagramm"/>
      <p class="klein"><strong>Abbildung 1.6:</strong> Klassendiagramm des EventHandler-Modells</p>  
      </li>      
      <li>Die folgende Zeile ruft abschließend den MCREventManager auf und stößt die Handler für die Pipeline an.<br/>
      <code>MCREventManager.instance().handleEvent(evt);</code></li>
      </ol>
     </section>
     
     <section>
      <title>Die Konfiguration des EventHandler-Managers</title>
      <p>
      Alle Konfigurationen befinden sich im Verzeichnis der Applikation (z.B. DocPortal) in der Datei 
      mycore.private.properties (bzw. mycore.private.properties.template). 
      </p>
      <p>
      In der Version 1.2 von MyCoRe ist es noch erforderlich, für den jeweiligen SearchStore die dummy-Klasse anzugeben:
      </p>
      <p><code>MCR.persistence_jdom_class_name=org.mycore.common.events.MCRDummySearchStore</code></p>
      <p>
      Nun müssen noch die EventHandler für jede Pipeline (in diesem Fall ist es 
      <code>MCRObject = MCREvent.OBJECT_TYPE</code>) in der Reihenfolge ihrer Ausführung angegeben werden. Jeder 
      Handler bekommt dabei eine aufsteigende Nummer.
      </p>
      <p><code>MCR.EventHandler.MCRObject.1.class=org.mycore.backend.jdom.MCRJDOMEventHandlerIndexMeta</code></p>
      <p>
      Wollen Sie eigene EventHandler schreiben und diese einbinden, so ist es ratsam diese direkt von 
      <code>MCREventHandler</code> abzuleiten und analog zu den bestehenden Handlern einzubinden. Sie können dafür auch 
      neue Pipelines und Ereignisse definieren. Den <code>MCREventManager</code> können Sie nun an beliebiger 
      Code-Stelle einbauen und ihm ein von Ihnen definiertes Ereignis übergeben. Diese Komponente ist allgemein 
      verwendbar und nicht auf das MyCoRe-Datenmodell festgelegt.
      </p>
     </section>
     
    </section>
   
  <section>
   <title>Das Datenmodell</title>
   
   <section>
    <title>Klassifikationen</title>
    <p class="fett">Allgemeines</p>
    <p>
    Klassifikationen sind wie bereits angedeutet Sammlungen fest stehender Begriffe, welche noch ggf. hierarchisch 
    strukturiert sein können. In Bereichen des Bibliothekswesens werden sie auch als Normdateien bezeichnet. Der 
    Vorteil ist, dass bei einer interaktiven Suche immer die richtigen und eindeutigen Begriffe angezeigt und 
    gefunden werden. Für den Import und Export solcher Klassifikationen wurde in MyCoRe eine XML-Darstellung festgelegt, 
    welche intern in SQL-Tabellen abgelegt wird. Als Schnittstelle dient hier ein Interface, welches durch 
    verschiedene Persistence Layer implementiert werden kann. Standard ist dabei die Hibernate-Implementierung. 
    </p>
    <p class="fett">Elemente einer Klassifikation</p>
    <p>
    Klassifikationen haben immer ein Grundgerüst, welches die ID, das Datenmodellschema und einen oder mehrere Label 
    enthält. Ein Label wiederum enthält Informationen zur Sprache sowie einen Text und ein optionales Beschreibungsfeld. 
    Alle Elemente einer Klassifikation sind in Kategoriefeldern gespeichert. Jede Kategorie hat wiederum eine ID als 
    Attribut. Weiterhin enthält eine Kategorie Labels mit den Attributen Sprache, Text und Beschreibung (optional). 
    Eine weitere Option ist ein Element URL welches eine URL als Referenz für die Kategorie enthält. Die ist z.B. bei 
    Listen von Einrichtungen sehr interessant. Kategorien können ineinander geschachtelt auftreten.
    </p>
    
    <img src="images/mycore_klassifikationen_uml.jpg" alt="Datenmodell-Graphik" title="Datenmodell-Graphik"/>
    
   </section>
   
   <section>
    <title>Struktur der Metadaten</title>
    <p>ist in Arbeit</p>
   </section>
   
   <section>
    <title>Struktur der Derivate</title>
    <p>ist in Arbeit</p>
   </section>
   
   <section>
    <title>Die API des Datenmodells</title>
    <p>ist in Arbeit</p>
   </section>
   <section>
    <title>Erstellen eigener Datenmodelle aus den Grundkomponenten</title>
    <p>ist in Arbeit</p>
   </section>
   
   <section>
    <title>Erweiterung des Datenmodells</title>
    <p>ist in Arbeit</p>
   </section>
   
  </section>
  
  <section>
   <title>Suchen und Finden: MyCoRe Query Service</title>
   
    <section>
     <title>Datenmodell der Suche</title>
     <p>
     Aufgabe des MyCoRe Query Service ist es, gespeicherte Daten durchsuchbar zu machen. MyCoRe Anwendungen suchen 
     dabei nicht direkt in den Metadaten von Dokumenten bzw. deren XML-Darstellung, oder den Volltexten der zugehörigen 
     Dateien, sondern in daraus abgeleiteten Suchfeldern. Die Definition dieser Suchfelder wird für jede MyCoRe 
     Anwendung in der Konfigurationsdatei <code>searchfields.xml</code> vorgenommen 
     (vgl. <code>docportal/config/searchfields.xml</code>). Das XML Schema dieser Datei ist in der 
     Datei <code>searchfields.xsd</code> definiert.
     </p>
     <p>
     Mehrere Suchfelder werden zu einem Index logisch zusammengefasst. In DocPortal fasst z.B. der Index 
     <code>metadata</code> alle Felder zusammen, die Dokumenten- und Personen-Metadaten durchsuchbar machen. Der 
     Index <code>content</code> enthält alle Felder, die Dateien (deren Volltexte, Dateinamen, Dateigröße etc.) 
     durchsuchbar machen. In jeder MyCoRe Anwendung ist ein Index oder mehrere solcher Indizes in der Datei 
     <code>searchfields.xml</code> definiert. Jeder Index besitzt eine eindeutige ID und besteht aus einem oder mehreren 
     Suchfeldern, die jeweils einen innerhalb der Datei <code>searchfields.xml</code> eindeutigen Namen besitzen.
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     <searchfields>
       <index id="metadata">
         <field name="title" ... />
         <field name="dateCreated" ... />
         ... 
       </index>
       <index id="content">
         <field name="fulltext" ... />
         <field name="size" ... />
         <field name="numPages" ... />
       </index>
     </searchfields>
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     Jedem Index muss ein Searcher zugeordnet werden, der die Felder dieses Index mit Hilfe eines zugrundeliegenden 
     Datenbanksystems (z.B. SQL) oder einer Suchmaschine (z.B. Lucene) durchsuchbar macht. Ein 
     Searcher wird durch eine Java-Klasse implementiert und ist somit zur Laufzeit eine Instanz dieser Klasse. 
     </p>
     
     <img src="images/searcher.png" alt="Searcher" title="Searcher"/>
     
     <p>
     Searcher und Index sind prinzipiell unabhängig, d.h. es ist möglich, je nach Anwendung für den gleichen Index 
     zwischen verschiedenen Searcher-Implementierungen zu wählen, die jeweils Vor- und Nachteile besitzen. Die gleiche 
     Java-Klasse, z.B. die auf Apache Lucene basierende Implementierung eines Searchers, kann auch für mehrere Indizes 
     verwendet werden, so dass zur Laufzeit mehrere Instanzen der Java-Klasse verwendet werden.
     </p>
     <p>
     Die Zuordnung von Searchern zu Indizes wird in den <code>mycore.properties</code>-Konfigurationsdateien vorgenommen. 
     Jedem Index wird ein Searcher zugeordnet. Jeder Searcher besitzt wiederum eine eindeutige ID. Dazu ein Beispiel:
     </p>
     <p class="kasten">
     # Searcher mit ID <code>'jdom-metadata'</code> sucht im Index <code>'metadata'</code><br/>
     <code>MCR.Searcher.jdom-metadata.Index=metadata</code><br/>
     # Searcher mit ID <code>'lucene-content'</code> sucht im Index <code>'content'</code><br/>
     <code>MCR.Searcher.lucene-content.Index=content</code><br/>
     also allgemein<br/>
     <code>MCR.Searcher.[SearcherID].Index=[IndexID]</code>
     </p>
     <p>
     Durch die Trennung von Searcher und Index kann man den für einen bestimmten Index verwendeten Searcher durch 
     Änderung nur einer Konfigurationszeile wechseln (z.B. von Lucene auf JDOM). Sie können so in Ihrer Anwendung 
     zu einem späteren Zeitpunkt die Suchimplementierung wechseln, ohne die Daten neu laden zu müssen.
     </p>
    </section>
    
    <section>
     <title>Implementierungen der Suche</title>
     <p>
     Jeder Searcher wird durch eine bestimmte Java-Klasse implementiert. Derzeit sind zwei Implementierungen der Suche 
     verfügbar.
     </p>
     <ul>
     <li><strong><code>org.mycore.backend.lucene.MCRLuceneSearcher</code></strong><br/>
     verwendet die Apache Lucene Suchmaschine. Dies ist die für Produktionssysteme derzeit empfohlene Implementierung, 
     die sich sowohl für die Metadatensuche, als auch für die Suche in Volltexten eignet.</li>
     <li><strong><code>org.mycore.backend.jdom.MCRJDOMSearcher</code></strong><br/>
     verwendet einen Suchindex im Hauptspeicher, so dass keinerlei Daten auf der Festplatte bzw. einem Datenbanksystem 
     gespeichert werden. Diese Implementierung dient als Referenz zur Entwicklung eigener Suchimplementierungen und hat 
     den Vorteil, dass niemals Daten neu indiziert oder geladen werden müssen, eine Änderung der Suchfeld-Konfiguration 
     ist nach Neustart der Anwendung unmittelbar wirksam. Gut geeignet für die Suche in Metadaten bei der Entwicklung 
     einer Anwendung.</li>
     </ul>
     <p>
     Die gleiche Implementierung (Java-Klasse) kann auch für verschiedene Searcher-Instanzen mit unterschiedlicher 
     Konfiguration verwendet werden. Jeder Searcher kann eine eigene, individuelle Konfiguration haben, deren Parameter 
     abhängig von der Implementierung sind. Im folgenden Beispiel wird der Searcher mit der ID <code>lucene-content</code> 
     durch die Klasse <code>MCRLuceneSearcher</code> implementiert. Diese Searcher-Instanz verwendet das Verzeichnis 
     <code>lucene-index4content/,</code> um die Daten des Suchindex zu speichern:
     </p>
     <p class="kasten">
     # Konfiguration des Searchers <code>'lucene-content'</code><br/>
     <code>MCR.Searcher.lucene-content.Class= </code><br/> 
     <code>org.mycore.backend.lucene.MCRLuceneSearcher</code><br/>
     <code>MCR.Searcher.lucene-content.IndexDir=/repository/lucene-index4content/</code><br/>
     <br/>
     # Konfiguration des Searchers <code>'jdom-metadata'</code><br/>
     <code>MCR.Searcher.jdom-metadata.Class=</code><br/>
     <code>org.mycore.backend.jdom.MCRJDOMSearcher</code><br/>
     <code>MCR.Searcher.jdom-metadata.Index=metadata</code><br/>
     also allgemein<br/>
     <code>MCR.Searcher.[SearcherID].Class=[ImplementierendeJavaKlasse]</code><br/>
     <code>MCR.Searcher.[SearcherID].[KonfigurationsEigenschaft]=[Wert]</code>
     </p>
    </section>
    
    <section>
     <title>Abbildung von Daten auf Suchfelder</title>
     <p>
     Damit die Metadaten bzw. die Dateien der in einer MyCoRe Anwendung gespeicherten Dokumente durchsuchbar sind, 
     müssen diese Daten auf logische Suchfelder abgebildet werden. Diese Abbildung kann je nach Implementierung an sich 
     auf beliebige Weise erfolgen, in der Regel werden aber aus den XML-Darstellungen der Daten die Inhalte der 
     Suchfelder mittels XPath-Anweisungen abgeleitet. Die hierarchische XML-Struktur wird dabei quasi „verflacht“. 
     Mittels Filter (PDF, HTML,OpenOffice etc.) können die Volltexte aus Textdateien extrahiert und einem logischen 
     Suchfeld zugeordnet werden. 
     </p>
     <p>
     Typischerweise werden nicht alle Inhalte auf Suchfelder abgebildet. Ein Suchfeld kann auch eine Aggregation von 
     Daten mehrerer Metadatenfelder sein. Suchfelder sind grundsätzlich auch wiederholbar, da evtl. die zugrunde 
     liegenden Metadatenfelder oder Inhalte wiederholt auftreten. Auch kann das gleiche Metadatenfeld auf mehrere 
     Suchfelder abgebildet werden. Dazu einige Beispiele: 
     </p>
     <table>
     <tr>
     <th colspan="1" rowspan="1">Suchfeld</th>
     <th colspan="1" rowspan="1">Entsprechung in den Metadaten bzw. Dateien</th>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">title</td>
     <td colspan="1" rowspan="1">/mycoreobject/metadata/titles/title</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">creator</td>
     <td colspan="1" rowspan="1">/mycoreobject/metadata/creators/creator</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">author</td>
     <td colspan="1" rowspan="1">/mycoreobject/metadata/creators/creator | /mycoreobject/metadata/publishers/publisher</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">content</td>
     <td colspan="1" rowspan="1">Volltext der Dateien des Dokumentes</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1">fileSize</td>
     <td colspan="1" rowspan="1">/file/@size </td>
     </tr></table>
     <p>
     Suchfelder können nicht nur aus Dokument-Metadaten und Volltexten gebildet werden. Derzeit werden die folgenden 
     Datenquellen unterstützt: 
     </p>
     <p class="break">
     <strong>Metadaten der Dokumente</strong> (Titel, Autor usw. je nach Datenmodell)
     </p>
     <p class="break"><strong>Metadaten der Dateien</strong> (Dateiname, Größe, Typ etc.)
     </p>
     <p class="break">
     <strong>Volltext der Dateien:</strong><br/>
     Dabei wird mittels der in MyCoRe bereitgestellten Filter der Volltext extrahiert und indiziert (z.B. OpenOffice, 
     TXT, HTML, PDF Dateien).
     </p>
     <p class="break">
     <strong>XML-Inhalt der Dateien: </strong><br/>
     Wenn eine gespeicherte Datei eine XML-Datei ist (z.B. eine Excel-Tabelle, als XML gespeichert, oder eine 
     SCORM-Manifest-Datei eines E-Learning Moduls), können deren XML-Elemente qualifiziert durchsuchbar gemacht 
     werden.</p>
     <p class="break"><strong>Zusatzdaten der Dateien:</strong><br/>
     In speziellen Anwendungen können damit z.B. extrahierte ID3-Tags aus MP3-Dateien, EXIF-Daten aus Bildern und 
     ähnliche Quellen durchsucht werden).
     </p>
     <p class="break">
     <strong>Beliebige XML-Quellen:</strong><br/>
     Eigene Anwendungen können die Inhalte beliebiger XML-Quellen indizieren, ohne dass diese XML-Quellen Teil des 
     MyCoRe Datenmodells sein müssen.
     </p>
     <p>
     In der Datei <code>searchfields.xml</code> wird für jedes Feld über das Attribut <code>source</code> angegeben, aus 
     welcher Quelle es gebildet wird:</p>
     <table>
     <tr>
     <th colspan="1" rowspan="1"><code>source = </code></th>
     <th colspan="1" rowspan="1"><code>MCRFieldDef</code> Konst.</th>
     <th colspan="1" rowspan="1">Quelle der Feldwerte</th>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>objectMetadata</code></td>
     <td colspan="1" rowspan="1"><code>OBJECT_METADATA</code></td>
     <td colspan="1" rowspan="1"><code>MCRObject.createXML()</code></td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>objectCategory</code></td>
     <td colspan="1" rowspan="1"><code>OBJECT_CATEGORY</code></td>
     <td colspan="1" rowspan="1">alle Klassifikationskategorien</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>fileMetadata</code></td>
     <td colspan="1" rowspan="1"><code>FILE_METADATA</code></td>
     <td colspan="1" rowspan="1"><code>MCRFile.createXML()</code></td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>fileAdditionalData</code></td>
     <td colspan="1" rowspan="1"><code>FILE_ADDITIONAL_DATA</code></td>
     <td colspan="1" rowspan="1"><code>MCRFile.getAdditionalData()</code></td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>fileXMLContent</code></td>
     <td colspan="1" rowspan="1"><code>FILE_XML_CONTENT</code></td>
     <td colspan="1" rowspan="1"><code>MCRFile.getContentAsJDOM()</code></td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>fileTextContent</code></td>
     <td colspan="1" rowspan="1"><code>FILE_TEXT_CONTENT</code></td>
     <td colspan="1" rowspan="1"><code>MCRFile.getContent()</code> &amp; PlugIn</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>xml</code></td>
     <td colspan="1" rowspan="1"><code>XML</code></td>
     <td colspan="1" rowspan="1">beliebiges <code>org.jdom.Document</code></td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>searcherHitMetadata</code></td>
     <td colspan="1" rowspan="1"><code>SEARCHER_HIT_METADATA</code></td>
     <td colspan="1" rowspan="1">durch <code>MCRSearcher</code> ergänzt</td>
     </tr>
     </table>
     <p>
     In allen Fällen außer <code>fileTextContent</code> und <code>searcherHitMetadata</code> (also immer, wenn der 
     Feldwert aus einer XML-Quelle abgeleitet wird) wird über die Attribute <code>xpath</code> und <code>value</code> 
     definiert, wie der Feldwert zustande kommt. Beispiele:
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     <field name="title" type="text" source="objectMetadata"
       xpath="/mycoreobject/metadata/titles/title" value="text()" />
     <field name="fileSize" type="integer" source="fileMetadata"
       xpath="file/@size" value="." />
     <field name="content" type="text" source="fileTextContent" />
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     Das Attribut <strong>xpath</strong> kann Werte enthalten, wie sie in einem <strong>xsl:select</strong>- oder 
     <strong>xsl:match</strong>- Attribut erlaubt sind. Die in <code>searchfields.xml</code> definierten Felder sind 
     grundsätzlich wiederholbar, d. h. wenn etwa ein Objekt mehrere Titel enthält, werden auch mehrere Feldwerte erzeugt 
     und einzeln indiziert.
     </p>
     <p>
     Ein Sonderfall stellt die Quelle <code>objectCategory</code> dar. Sie muss verwendet werden, wenn nach den 
     Kategorien einer Klassifikation gesucht werden soll. In diesem Fall gibt das <code>xpath</code>-Attribut an, 
     welches Element in den Objektmetadaten den Link auf die Klassifikationskategorien enthält. Das 
     <code>value</code>-Attribut gibt an, ob die ID oder die Labels der Klassifikationskategorie indiziert werden 
     sollen. Beispiel:
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     <field name="origin" type="identifier" source="objectCategory"
       objects="document" xpath="/mycoreobject/metadata/origins/origin"
       value="@ID" />
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     Felder mit der Quellangabe <code>searcherHitMetadata</code> werden nicht aus den gespeicherten Daten gebildet, 
     sondern erst bei Zusammenstellen der Trefferliste der Suche von der Suchimplementierung dynamisch ergänzt. Dieser 
     Feldtyp ist für technische Metadaten eines Treffers (score, rank etc.) gedacht. Damit dieses Feld z.B. auch 
     sortierbar ist, muss es in der Datei <code>searchfields.xml</code> definiert sein. 
     </p>
    </section>
    
    <section>
     <title>Die Attribute sortable und objects</title>
     <p>
     Suchfelder, nach denen man die Trefferliste der Suche sortieren können möchte, müssen explizit über das 
     Attribut <code>sortable='true'</code> gekennzeichnet werden.
     </p>
     <p>
     Manche Suchfelder sollen bzw. können nur für bestimmte Objekttypen oder Dateitypen gebildet werden. Über das 
     Attribut <code>objects</code> kann definiert werden, dass ein Suchfeld nur für bestimmte Typen von 
     Metadatenobjekten oder für bestimmte Typen von Dateien (z.B nur denen, für die ein Volltextfilter vorliegt) 
     gebildet werden. Beispiel:
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     <field name="title" type="text" source="objectMetadata"
       objects="document" sortable="true"
       xpath="/mycoreobject/metadata/titles/title" value="text()" /&gt;
     
       field name="content" type="text" source="fileTextContent"  
       objects="html pdf ps txt xml msword95 msword97 msppt rtf otd sxw" />
     ]]>
     </p><![CDATA[
     ]]></source>
    </section>
    
    <section>
     <title>Datentypen und Operatoren</title>
     <p>
     Jedem Suchfeld ist ein definierter Datentyp zugeordnet. Der Datentyp bestimmt die möglichen Operatoren für 
     Suchanfragen und legt implizit fest, wie Inhalte dieses Typs behandelt werden (Normalisierung von Umlauten, 
     Stammwortbildung statt exakter Suche etc.). Für jeden Datentyp gibt es eine festgelegte Menge vordefinierter 
     Standard-Operatoren, die jede Searcher-Implementierung unterstützen muss. Darüber hinaus kann eine Implementierung 
     aber auch eigene Datentypen und eigene Operatoren mit erweiterten Suchmöglichkeiten definieren.
     </p>
     <p>
     Die Definition der Standard-Datentypen und Operatoren erfolgt in der Datei <code>mycore/config/fieldtypes.xml</code>.
     Das XML Schema dieser Datei befindet sich in <code>mycore/schema/fieldtypes.xsd</code>. Hier ein Auszug als 
     Beispiel:
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     <fieldtypes>
       <type name="text">
         <operator token="="/>
         <operator token="&gt;"/>
         <operator token="&lt;"/>
         <operator token="&gt;="/>
         <operator token="&lt;="/>
         <operator token="like"/>        <!-- wildcard search using * and ? -->
         <operator token="contains"/>    <!-- words at any position -->
         <operator token="phrase"/>      <!-- a phrase at any position -->
       </type/>
       ...
     </fieldtypes>
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     In zukünftigen Versionen von MyCoRe wird diese Datei auch proprietäre Datentypen (etwa GIS-Koordinaten) und 
     Operatoren (z.B. proximity-Suche in Lucene) definieren und diese als nur durch bestimmte Implementierungen 
     unterstützte Operatoren kennzeichnen. Diese Funktionalität ist derzeit noch nicht implementiert.
     </p>
     <p>
     Bei der Konfiguration der Suchfelder ist insbesondere auf die richtige Wahl der Textdatentypen zu achten. Es wird 
     zwischen drei verschiedenen Datentypen für Textfelder unterschieden: <code>identifier</code>, <code>name</code> 
     und <code>text</code>. Die folgenden Standard-Datentypen sind derzeit implementiert:
     </p>
     <table>
     <tr>
     <td colspan="1" rowspan="1">Datentyp</td>
     <td colspan="1" rowspan="1">Suchoperatoren</td>
     <td colspan="1" rowspan="1">Beschreibung</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>identifier</code></td>
     <td colspan="1" rowspan="1">=, &lt;, &gt;, &lt;=, &gt;=,<code>like</code></td>
     <td colspan="1" rowspan="1">ID, URN, Dateiname etc., also für exakte Werte, keine Normalisierung oderStemming</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>name</code></td>
     <td colspan="1" rowspan="1">=, &lt;, &gt;, &lt;=, &gt;=,<code>like</code>, <code>contains</code></td>
     <td colspan="1" rowspan="1">Personen- oder Ortsnamen etc., Umlaut-normalisierung, aber kein Stemming</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>text</code></td><td colspan="1" rowspan="1">=, &lt;, &gt;, &lt;=, &gt;=,<code>like</code>, <code>contains</code>,<code>phrase</code></td>
     <td colspan="1" rowspan="1">Volltext, Abstract, freier Text, Umlautnormalisierung, Stemming </td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>date</code></td>
     <td colspan="1" rowspan="1">=, &lt;, &gt;, &lt;=, &gt;=</td>
     <td colspan="1" rowspan="1">Datum, vollständig im Format yyyy-MM-dd</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>time</code></td>
     <td colspan="1" rowspan="1">=, &lt;, &gt;, &lt;=, &gt;=</td>
     <td colspan="1" rowspan="1">Uhrzeit oder zeitliche Dauer, im Format HH:mm:ss</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>timestamp</code></td>
     <td colspan="1" rowspan="1">=, &lt;, &gt;, &lt;=, &gt;=</td>
     <td colspan="1" rowspan="1">Zeitpunkt, im Format 'yyyy-MM-dd HH:mm:ss'</td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>boolean</code></td>
     <td colspan="1" rowspan="1">=</td><td colspan="1" rowspan="1">'true' oder 'false' </td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>decimal</code></td>
     <td colspan="1" rowspan="1">=, &lt;, &gt;, &lt;=, &gt;=</td>
     <td colspan="1" rowspan="1">Gleitkommazahl,"." als Trennzeichen </td>
     </tr>
     <tr>
     <td colspan="1" rowspan="1"><code>integer</code></td>
     <td colspan="1" rowspan="1">=, &lt;, &gt;, &lt;=, &gt;=</td>
     <td colspan="1" rowspan="1">Ganzzahl</td>
     </tr>
     </table>
     <p>
     Es ist Aufgabe der Suchimplementierung, diese Datentypen auf möglichst geeignete Suchstrukturen (Lucene-/SQL-Typen 
     etc) abzubilden und die Standard-Operatoren in der späteren Suche umzusetzen. Zu beachten ist, dass für Datums-, 
     Zeit- und Boolean-Werte das Format für die Indizierung (wie werden die Felder zur Indizierung übergeben) und die 
     spätere Suche (wie wird ein Wert in einer Query formatiert) exakt festgelegt ist (siehe Formate in obiger Tabelle). 
     </p>
    </section>
    
    <section>
     <title>Suchanfragen formulieren</title>
     <p>
     Eine Suchanfrage kann als XML-Dokument oder als Textausdruck formuliert werden. Für Programmierer besteht weiterhin 
     die Möglichkeit, eine Suche als zusammengesetztes Java-Objekt zu formulieren. 
     </p>
     <p>
     Eine einfache Suchbedingung enthält das zu durchsuchende Feld, einen Suchoperator und den Vergleichswert, z.B. 
     Suche nach dem Wort „Optik“ im Titel:
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     title contains "Optik"
     
     <condition field="title" operator="contains" value="Optik" />
     
     MCRFieldDef titleField = MCRFieldDef.getDef("title"); 
     new MCRQueryCondition( titleField, "contains", "Optik" );
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     Die Klassen <code>MCRQueryParser</code> und <code>MCRQueryCondition</code> implementieren die Java-Darstellung einer 
     Query bzw. den Parser, um aus der String- oder XML-Darstellung die Java-Darstellung zu gewinnen und zwischen den 
     Darstellungen zu wechseln.
     </p>
     <p>
     Einfache Suchbedingungen können über <code>and/or/not</code>-Ausdrücke miteinander verknüpft und so zu komplexeren 
     Suchanfragen zusammengesetzt werden:
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     ( not (title contains "Optik") ) and ( date &gt; "2006-02-22" )
     
     <boolean operator="AND">
       <boolean operator="NOT">
         <condition field="title" operator="contains" value="Optik" />
       </boolean>
       <condition field="date" operator="&amp;gt;" value="2006-02-22" />
     </boolean>
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     Solche komplexen Suchbedingungen können über die Klassen <code>MCRAndCondition</code>, <code>MCROrCondition</code> 
      und <code>MCRNotCondition</code> aus dem Paket <code>org.mycore.parsers.bool</code> auch als Java-Objekte gebildet 
      werden. 
      </p>
     </section>
     
     <section>
      <title>Normalisierung von Suchanfragen</title>
      <p>
      Suchanfragen werden vor der Ausführung normalisiert. Insbesondere werden Datumsangaben in Suchausdrücken vom 
      eingegebenen Format z.B. 22.04.1971 automatisch in das ISO8601-Format transformiert also 1971-04-22.
      </p>
      <p>
      Suchbedingungen, die den Operator <code>contains</code> verwenden, werden automatisch in einzelne 
      <code>contains/like/phrase/not-</code>Bedingungen zerlegt. Beispiel:
      </p>
      <source xml:space="preserve"><![CDATA[
      ]]><p class="kastensource">  
      <![CDATA[ 
      title contains "-Optik Mecha* 'Lineare Algebra'"
      
      wird normalisiert zu
      
      (not (title contains Optik)) and (title like Mech*) 
      and (title phrase 'Lineare Algebra')
      ]]>
      </p><![CDATA[
      ]]></source>
      <p>
      In der Konsequenz bedeutet das, dass man bei der Textsuche in aller Regel den Operator <code>contains</code> 
      verwenden kann. Die Umwandlung in eine <code>like</code>- und/oder <code>contains</code>- und/oder 
      <code>phrase</code>-Suche erfolgt automatisch. 
      </p>
      <ul>
      <li>Worte beginnend mit einem Minuszeichen werden zu einer <code>not</code>-Bedingung.</li>
      <li>Worte, die <code>*</code> oder <code>?</code> enthalten, werden zu einer <code>like</code>-Bedingung.</li>
      <li>Wortgruppen in einfachen Anführungszeichen werden zu einer <code>phrase</code>-Bedingung.</li>
      </ul>
      <p>
      Eine Suchbedingung kann auch gleichzeitig für mehrere Suchfelder definiert werden. Dazu werden die einzelnen 
      Feldnamen durch Kommata getrennt. Beispiel:
      </p>
      <source xml:space="preserve"><![CDATA[
      ]]><p class="kastensource">  
      <![CDATA[ 
      title,author contains Goethe
      
      entspricht
      
      (title contains Goethe) or (author contains Goethe)
      ]]>
      </p><![CDATA[
      ]]></source>
      <p>
      Diese Funktionalität kann z.B. verwendet werden, um in einer Suchmaske über nur ein Eingabefeld parallel in 
      mehreren Suchfeldern suchen zu können.
      </p>
     </section>
     
     <section>
     <title>Suchen mit MCRSearchServlet</title>
     <p>
     Das Servlet MCRSearchServlet führt Suchanfragen aus und stellt die resultierenden Trefferlisten dar. Die 
     Suchanfrage wird auf verschiedene Weisen akzeptiert:
     </p>
     <ul>
     <li><strong>Suche in einem vordefinierten Feld:</strong><br/>
     In diesem Fall wird nur ein Parameter übergeben, z.B. <code>search=Optik</code>.<br/>
     Es wird in einem vordefiniertem Feld mit vordefiniertem Operator gesucht, entsprechend der Konfiguration in 
     <code>mycore.properties</code>:<br/>
     <code>MCR.SearchServlet.DefaultSearchField=allMeta</code><br/>
     <code>MCR.SearchServlet.DefaultSearchOperator=contains</code><br/>
     Ein Aufruf mit <code>search=Optik</code> sucht dann nach <code>allMeta contains Optik</code>.</li>
     <li><strong>Suche mit komplexem Suchausdruck:</strong><br/>
     Die Suchanfrage wird dabei im Parameter <code>query</code> übergeben, z.B. <br/>
     <code>query=title contains Optik</code></li>
     <li><strong>Suche über Namens- und Operator-Parametern:</strong><br/>
     Es können mehrere Parameter übergeben werden, deren Namen den definierten Suchfeldern entsprechen müssen. Die 
     einzelnen Bedingungen werden mit UND verknüpft. Beispiel:<br/>
     <code>title=Optik&amp;author=Kupferschmidt</code><br/>
     entspricht einer Suche nach<br/>
     <code>(title contains Optik) and (author contains Kupferschmidt)</code>.<br/>
     Wenn, wie im obigen Beispiel, kein Suchoperator angegeben ist, wird der in 
     <code>MCR.SearchServlet.DefaultSearchOperator</code> definierte Wert verwendet. Alternativ kann auch ein Operator 
     angegeben werden:<br/>
     <code>title=Opti*&amp;title.operator=like</code><br/>
     entspricht einer Suche nach<br/>
     <code>title like Opti*</code><br/>
     Wenn mehrere Werte für ein Suchfeld angegeben werden, werden diese mit dem Operator <code>or</code> verknüpft:<br/>
     <code>title=Optik&amp;title=Magnetismus</code><br/>
     entspricht einer Suche nach<br/>
     <code>(title contains Optik) or (title contains Magnetismus)</code></li>
     </ul>
     <p>
     Mit den drei zuvor beschriebenen Methoden kann jede Suche als statischer Link in einer Webseite eingebunden werden. 
     Als weitere HTTP-Request-Parameter können die Anzahl Treffer pro Seite (<code>numPerPage</code>) und die maximale 
     Anzahl auszugebender Treffer (<code>maxResults</code>) angegeben werden. Beispiel:
     </p>
     <p class="break"><code>/servlets/MCRSearchServlet?title=Optik&amp;maxResults=100&amp;numPerPage=5</code></p>
     <p>
     Die Sortierung der Trefferliste kann über einen weiteren Parameter festgelegt werden, durch Anhängen des 
     Suffixes <code>.sortField</code> an den Feldnamen, mit den möglichen Werten <code>ascending</code> und <code>descending</code>:
     </p>
     <p class="break"><code>/servlets/MCRSearchServlet?title=Optik&amp;...&amp;created.sortField=descending</code></p>
     <p>
     Wenn Sie nach mehr als einem Kriterium sortieren möchten, können Sie die sortField Parameter im Suffix nummerieren, um die
     Sortierreihenfolge zu bestimmen, z. B.
     </p>
     <p class="break"><code>/servlets/MCRSearchServlet?title=Optik&amp;...&amp;created.sortField.1=descending&amp;author.sortField.2=ascending</code></p>
     <ul>
     <li><strong>Suchanfrage als XML-Dokument:</strong><br/>
     Hier ist dem <code>MCRSearchServlet</code> ein MyCoRe Editor-Formular vorgeschaltet, das eine Suchmaske darstellt. 
     Nach Abschicken der Suchmaskeneingaben durch den Benutzer generiert das Editor Framework daraus ein XML-Dokument, 
     das die Suchanfrage enthält. Die Syntax dieses XML-Dokumentes entspricht der im vorangehenden Kapitel beschriebenen 
     Syntax für Suchanfragen. Das Wurzelelement <code>query</code> enthält drei Attribute:
     <dl>
     <dt><code>mask</code></dt>
     <dd> Dateiname der Suchmaske</dd>
     <dt><code>maxResults</code></dt>
     <dd> maximale Trefferzahl</dd>
     <dt><code>numPerPage</code></dt> 
     <dd>Anzahl Treffer pro Seite</dd>
     </dl>
     Das Element <code>conditions</code> enthält die eigentliche Suchbedingung, entweder formuliert als Menge von 
     verschachtelten XML-Elementen (<code>format=xml</code>) oder als textueller Suchausdruck (<code>format=text</code>). 
     Beispiel:</li>
     </ul>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     <query 
       mask='editor_form_search-simpledocument.xml'
       maxResults='100' numPerPage='10'> 
       <conditions format='xml'>
         <boolean operator='and'>
           <condition field='title' operator='contains' value='Optik' />
           <condition field='author' 
                 operator='contains' value='Kupferschmidt' /> 
         </boolean>
       </conditions>
     </query>
     ]]>
     </p><![CDATA[
     ]]></source>
    </section>
    
    <section><title>Indizierung von Feldern</title>
    <p>Der Query Service ist logisch von der Speicherung der Inhalte unabhängig, so dass Persistenz- und 
    Suchimplementierungen sehr flexibel kombinierbar und austauschbar sind. Dies bedeutet jedoch nicht, dass eine 
    bestimmte Implementierung nicht dennoch beide Dienste gemeinsam realisieren kann. In einer reinen Open Source 
    Umgebung kann z.B. zur Speicherung von Metadaten und Dateien ein lokales Dateisystem dienen, zur Suche in Metadaten 
    und Dateien kann Lucene verwendet werden. 
    </p>
    <p>
    Jedem Index (Menge von Suchfeldern) ist ein <code>Searcher</code> zugeordnet, der diese Felder durchsuchbar macht. 
    Es gibt nun drei Fälle, auf welche Weise diese Felder für eine spezielle Implementierung des Searchers durchsuchbar 
    werden:
    </p>
    <ul>
    <li>
    Es ist keine separate Indizierung notwendig, weil schon durch die Art und Weise der Speicherung der Daten 
    automatisch eine Durchsuchbarkeit gegeben ist (Ausnahmefall), oder: </li>
    <li>Wenn sich ein <code>MCRObject</code> (Metadaten eines Dokumentes) oder <code>MCRFile</code> (Datei mit Volltext) 
    ändert, wird bei diesem Ereignis über einen speziellen <code>EventHandler</code>, dem <code>Indexer</code>, die 
    Feldwerte aus den Daten extrahiert und in einer eigenen Struktur zwecks Durchsuchbarkeit abgelegt. In der 
    Implementierung gibt es dann zwei Varianten:
    <ul><li>Der <code>Indexer</code> tut dies selbst, indem er die entsprechenden Event-Methoden überschreibt 
        (Ausnahmefall), oder: </li>
        <li>Der <code>Indexer</code> wird als Unterklasse von <code>MCRSearcher</code> implementiert und überschreibt 
        die Methoden <code>addToIndex</code> und <code>removeFromIndex</code> (Regelfall). Alle Feldwerte werden dann 
        automatisch durch die Hilfsklasse <code>MCRData2Fields</code> anhand der Konfiguration aus den Daten gebildet. </li>
        </ul>
    </li>
    </ul>
    <p>Aufgabe eines <code>Indexers</code> ist es also, Inhalte auf Suchfelder abzubilden und diese in geeigneten 
    Strukturen in einer Datenbank oder einer Suchmaschine durchsuchbar zu machen. Im Regelfall ist daher nach der 
    Speicherung der Inhalte eine Abbildung von Suchfeldinhalten auf geeignete Backend-Strukturen (SQL-Tabellen, 
    Lucene Index etc). erforderlich. Die Trennung von Such- und Persistenzdiensten und der Aufruf der Indexer erfolgt 
    über den MyCoRe-EventManager. Bei <code>create/update/delete</code> Operationen auf <code>MCRObject</code> 
    (Metadaten) und <code>MCRFile</code> (Dateien) Objekte wird über den Event Manager ein Ereignis ausgelöst, das ein 
    oder mehrere konfigurierte <code>Indexer</code> aufruft. Der <code>Indexer</code> ist dafür verantwortlich, auf die 
    für ihn relevanten Änderungen an Inhalten zu reagieren und ggf. seine Suchfeldeinträge zu aktualisieren.
    </p>
    <p>Jeder <code>Searcher</code> muss als Unterklasse der abstrakten Klasse <code>MCRSearcher</code> implementiert 
    werden. <code>MCRSearcher</code> implementiert bereits das <code>MCREventHandler</code> Interface. Es sind daher 
    drei Fälle realisierbar:
    </p>
    <ul>
    <li>Searcher ohne Indexer: Es ist nichts weiter zu tun </li>
    <li>Searcher mit Indexer, wobei die Indizierung mit eigenen Mitteln erfolgt:<br/>
    Die MCRSearcher-Unterklasse überschreibt dann die <code>MCREventHandlerBase</code> Methoden </li>
    <li>Searcher mit Indexer, wobei die Feldwerte automatisch gebildet werden sollen: Die MCRSearcher-Unterklasse 
    überschreibt die Methoden <code>addToIndex()</code> und <code>removeFromIndex()</code>. </li>
    </ul>
    <p>Eine Searcher-Implementierung mit Indexer (die also Event Handler ist) kann z.B. wie folgt in den 
    Event-Mechanismus eingebunden werden:
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    MCR.EventHandler.MCRFile.1.Indexer=lucene-content
    MCR.EventHandler.MCRObject.4.Indexer=lucene-metadata
    
    also allgemein:
    
    MCR.EventHandler.[MCRObject|MCRFile].[Nr].Indexer=[SearcherID]]]><![CDATA[
    ]]>
    </p><![CDATA[
    ]]></source>
    <p>
    Nun werden bei <code>create/update/&gt;delete</code> Ereignissen auf Metadaten bzw. Dateien die 
    EventHandler-Methoden der implementierenden Klassen aufgerufen. Der typische Ablauf sieht dann in der 
    Implementierung wie in Abbildung 2.1 dargestellt aus.    
    </p>
    
    <img src="images/event.png" alt="Event-Ablauf" title="Event-Ablauf"/>
    <p class="klein"><strong>Abbildung 2.1:</strong> Typischer Event-Ablauf bei der Suche</p>
    
   </section>
   
   <section>
    <title>Suche über Referenzen</title>
    <p>
    In diesem Abschnitt geht es um die Rückgabe von Suchergebnissen über interne Referenzen. Damit ist gemeint, dass in 
    einem Datensatz vom Typ B ein Verweis in Form des Datentyps <code>MCRMetaLinkID</code> auf den Datensatz vom Typ 
    A vorhanden ist. Wird nun im Datensatz B z.B. über eine Klassifikation gesucht, so sollen in der Trefferliste die 
    ID's des referenzierten Datensätze vom Typ A erscheinen.
    </p>
    <p>Um dies zu realisieren, muss die Klasse <code>org.mycore.services.fieldquery.MCRSearcher</code> in den 
    Source-Zweig der betreffenden Applikation kopiert werden. Dort sind die Methoden <code>handleObjectCreated</code> 
    und <code>handleObjectUpdated</code> wie folgend umzugestalten.
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
   ...
    String returnID = entryID;
    if (obj.getId().getTypeId().equals("text")) {
      MCRMetaInterface inter =  
              obj.getMetadataElement("te43s").getElement(0);
      if (inter != null) {
        returnID = ((MCRMetaLinkID)inter).getXLinkHref();
      }
    addToIndex(entryID, returnID, fields);
    ...
    ]]>
    </p><![CDATA[
    ]]></source>
   </section>
   
  </section>
  
  <section>
    <title>Metadaten aus Dateien extrahieren</title>
    <p>
      Die Klassen des Paketes
      <code>org.mycore.datamodel.ifs.extractors</code>
      extrahieren beim Importieren oder Aktualisieren einer
      gespeicherten Derivatdatei Metadaten aus dem Inhalt. Derzeit sind
      die folgenden Implementierungen verfügbar:
    </p>
    <ul>
      <li>
        <code>MCRDataExtractorJPEG</code>
        extrahiert EXIF- und IPTC-Daten aus JPEG-Bilddateien
      </li>
      <li>
        <code>MCRDataExtractorMP3</code>
        extrahiert ID3- und Lyrics-Daten aus MP3-Audiodateien
      </li>
      <li>
        <code>MCRDataExtractorPDF</code>
        extrahiert Metadaten aus PDF-Dokumenten
      </li>
    </ul>
    <p>
      Um die Datenextraktion zu nutzen, müssen die Klassen als Event
      Handler in der
      <code>mycore.properties</code>
      konfiguriert werden. Damit die extrahierten Daten auch durchsucht
      werden können, müssen diese der Event Handler vor dem Event
      Handler laufen, der die Suchdaten indiziert. Alle anderen Event
      Handler rücken entsprechend eine Nummer nach hinten:
    </p>
    <source xml:space="preserve"><![CDATA[
     MCR.EventHandler.MCRFile.1.Class=org.mycore.datamodel.ifs.extractors.MCRDataExtractorJPEG
     MCR.EventHandler.MCRFile.1.Class=org.mycore.datamodel.ifs.extractors.MCRDataExtractorMP3
     MCR.EventHandler.MCRFile.1.Class=org.mycore.datamodel.ifs.extractors.MCRDataExtractorPDF
     
     MCR.EventHandler.MCRFile.4.Indexer=lucene-content
     MCR.EventHandler.MCRFile.5.Class=org.mycore.services.imaging.MCRImgCacheEventHandler
     MCR.EventHandler.MCRFile.6.Class=org.mycore.frontend.iview.MCRIViewEventHandler
    ]]></source>
    <p>
      Bei jedem Laden oder Aktualisieren einer Datei werden die
      Metadaten nun automatisch extrahiert und intern im XML-Format
      gespeichert. Nach Erweiterung der
      <code>searchfields.xml</code>
      um entsprechende Suchfelder können diese Metadaten auch durchsucht
      werden. Um die Daten auch im Directory Listing des Derivates
      auszugeben, muss das Stylesheet
      <code>mcr_directory.xsl</code>
      in Ihrer Anwendung erweitert werden.
    </p>
    <section>
      <title>Metadaten aus JPEG-Grafikdateien extrahieren</title>
      <p>
        Die Klasse
        <code>MCRDataExtractorJPEG</code>
        ist in der Lage, EXIF- und IPTC-Metadaten aus JPEG-Dateien zu
        extrahieren. Abhängig von der Eingabedatei sehen diese Daten z.
        B. wie folgt aus:
      </p>
      <source xml:space="preserve"><![CDATA[
        <MCRDataExtractorJPEG>
          <directory name="Exif">
            ...
            <tag name="Model">Canon PowerShot A40</tag>
            ...
            <tag name="Date/Time Original">2008:07:24 09:30:36</tag>
            <tag name="Date/Time Digitized">2008:07:24 09:30:36</tag>
            ...
          </directory>
          <directory name="Canon Makernote">
            ...
            <tag name="Owner Name">Frank Lützenkirchen</tag>
          </directory>
          <directory name="Jpeg">
            ...
            <tag name="Image Height">1600 pixels</tag>
            <tag name="Image Width">1200 pixels</tag>
            ...
          </directory>
        </MCRDataExtractorJPEG>
      ]]></source>
      <p>
        Um die Daten auch durchsuchbar zu machen, muss die
        searchfields.xml um entsprechende Felddefinitionen erweitert
        werden, z. B.
      </p>
      <source xml:space="preserve"><![CDATA[
        <index id="content">
          ...
          <field name="exifOwnerName" type="name" source="fileAdditionalData" objects="jpeg" 
            xpath="/additionalData/MCRDataExtractorJPEG/directory/tag[@name='Owner Name']" value="text()" />
          <field name="exifWidth" type="integer" source="fileAdditionalData" objects="jpeg" 
            xpath="/additionalData/MCRDataExtractorJPEG/directory/tag[@name='Image Width']" value="substring-before(text(),' pixels')" />
          <field name="exifDate" type="date" source="fileAdditionalData" objects="jpeg" 
            xpath="/additionalData/MCRDataExtractorJPEG/directory/tag[@name='Date/Time Original']" value="translate(text(),': ','-T')" />
        </index>
      ]]></source>
    </section>
    <section>
      <title>Metadaten aus MP3-Audiodateien extrahieren</title>
      <p>
        Die Klasse
        <code>MCRDataExtractorMP3</code>
        extrahiert ID3v1, ID3v1.1, Lyrics3v1, Lyrics3v2, ID3v2.2, ID3v2.3 und ID3v2.4 Metadaten
        aus MP3-Dateien. Abhängig von der Eingabedatei sehen diese Daten z.B. wie folgt aus:
      </p>
      <source xml:space="preserve"><![CDATA[
        <MCRDataExtractorMP3>
          <ID3v1>
            <album>Viva Club Rotation 37</album>
            <artist>Cosmic Gate feat. Denise River</artist>
            <yearReleased>2007</yearReleased>
            <albumTitle>Viva Club Rotation 37</albumTitle>
            <songGenre>18</songGenre>
            <leadArtist>Cosmic Gate feat. Denise River</leadArtist>
            <trackNumberOnAlbum>7</trackNumberOnAlbum>
            <year>2007</year>
            <songTitle>Body Of Conflict (Radio Edit)</songTitle>
            <title>Body Of Conflict (Radio Edit)</title>
          </ID3v1>
          <ID3v2>
            <trackNumberOnAlbum>7</trackNumberOnAlbum>
          </ID3v2>
        </MCRDataExtractorMP3>
      ]]></source>
      <p>
        Um die Daten auch durchsuchbar zu machen, muss die
        searchfields.xml um entsprechende Felddefinitionen erweitert
        werden, z. B.
      </p>
      <source xml:space="preserve"><![CDATA[
        <index id="content">
          ...
          <field name="mp3AlbumTitle" type="text" source="fileAdditionalData" objects="mp3" 
            xpath="/additionalData/MCRDataExtractorMP3/**/albumTitle" value="text()" />
          <field name="mp3Artist" type="name" source="fileAdditionalData" objects="mp3" 
            xpath="/additionalData/MCRDataExtractorMP3/**/artist" value="text()" />
          <field name="mp3SongTitle" type="text" source="fileAdditionalData" objects="mp3" 
            xpath="/additionalData/MCRDataExtractorMP3/**/songTitle" value="text()" />
        </index>
      ]]></source>
    </section>
    <section>
      <title>Metadaten aus PDF-Dokumenten extrahieren</title>
      <p>
        Die Klasse
        <code>MCRDataExtractorPDF</code>
        extrahiert Seitenzahl, Autor, Titel etc. und das Inhaltsverzeichnis aus PDF-Dokumenten. 
        Abhängig von der Eingabedatei sehen diese Daten z.B. wie folgt aus:
      </p>
      <source xml:space="preserve"><![CDATA[
        <MCRDataExtractorPDF>
          <numPages>370</numPages>
          <producer>FOP 0.20.5</producer>
          <author>Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato</author>
          <outline>
            <item title="Version Control with Subversion" />
            <item title="Table of Contents" />
            <item title="Foreword" />
            <item title="Preface">
              <item title="Audience" />
              <item title="How to Read this Book" />
              ...
        </MCRDataExtractorPDF>
      ]]></source>
      <p>
        Um die Daten auch durchsuchbar zu machen, muss die
        searchfields.xml um entsprechende Felddefinitionen erweitert
        werden, z. B. wie folgend. Sie können dann z. B. nach Dokumenten mit einer Mindestanzahl von
        Seiten suchen, oder gezielt nur im Inhaltsverzeichnis von PDF-Dateien suchen.
      </p>
      <source xml:space="preserve"><![CDATA[
        <index id="content">
          ...
          <field name="pdfNumPages" type="integer" source="fileAdditionalData" objects="pdf" 
            xpath="/additionalData/MCRDataExtractorPDF/numPages" value="text()" />
          <field name="pdfAuthor" type="name" source="fileAdditionalData" objects="pdf" 
            xpath="/additionalData/MCRDataExtractorPDF/author" value="text()" />
          <field name="pdfTOC" type="name" source="fileAdditionalData" objects="pdf" 
            xpath="/additionalData/MCRDataExtractorPDF/**/item" value="title" />
        </index>
      ]]></source>
    </section>
  </section>

  <section>
   <title>Die Link Tabellen</title>   
   <section>
    <title>Allgemeines</title>
    <p>
    Neben der Indizierung der Metadaten zur Suche wird auch über einen entsprechenden Event-Handler 
    (<strong>MCRLinkTableEventHandler</strong>) dafür gesorgt, dass Verweise zwischen den einzelnen Metadaten-Objekten 
    gesondert in einer Datenbanktabelle gespeichert werden. Über entsprechende Zugriffe sind so Abfragen von 
    Referenzen und Zählungen möglich. Die Definition des Tabellennamens erfolgt in der Konfigurationsdatei 
    <code>mycore.private.properties</code>
    </p>
    <p class="kasten"><code>MCR.Persistence.LinkTable.Store.Table=MCRLINKHREF</code></p>
    <p>Die Tabelle enthält die Spalten MCRFROM, MCRTO, MCRTYPE, MCRATTR.</p>
    <ul>
    <li>MCRFROM enthält die Quelladresse (Source) des Link (i.d.R. eine MCRObjectID).</li>
    <li>MCRTO enthält die Zieladresse (Target/Destination) des Link. Dies kann u. a. eine MCRObjectID sein. Links auf 
    Kategorien von Klassifikationen werden in der Form {classid}##{categid} abgespeichert.</li>
    <li>MCRTYPE enthält den Typ des Links. Derzeit sind folgende Typen vorgesehen:
    <ul><li>parent – Link zu einem Elternobjekt</li>
        <li>child – Link zu einem Kindobjekt</li>
        <li>derivate – Link zu einem Derivate</li>
        <li>classid – Link zu einer Kategorie einer Klassifikation</li>
        <li>reference – Link zu einem anderen Metadaten-Objekt</li>
    </ul>
    </li>
    <li>MCRATTR – derzeit nicht belegt</li>
    </ul>
   </section>
   
   <section>
    <title>Zugriff via API</title>
    <p>
    Der Zugriff auf die Link-Tabellen mittels API erfolgt über die Klasse 
    <code>org.mycore.datamodel.metadata.MCRLinkTableManager.</code> Diese organisiert auch den Zugiff auf die 
    Persistenz-Schicht durch Nutzung eines Interface.
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    MCRLinkTableManager LTM = MCRLinkTableManager.instance();
    ArrayList to = LTM.getSourceOf(from,“reference“);
    ]]>
    </p><![CDATA[
    ]]></source>
    
    <img src="images/progguide_linktable.jpg" alt="Klassendiagramm" title="Klassendiagramm"/>
    <p class="klein"><strong>Abbildung 2.2:</strong> Klassendiagramm für die Link Tables</p>
    
   </section>
   
   <section>
    <title>Zugriff über die Web-Schnittstellen</title>
    <p>
    Für den Zugriff via Web stellt das System ein Servlet bereit. Dieses liefert als Rückgabewert ein 
    mcr.results-XML-Objekt. Abhängig von der Angabe der Parameter from oder to enthält das Ergebnis die ID's der 
    Ziel- oder Quellobjekte. Wird der Parameter type weggelassen, so ist 'reference' der Standardwert. 
    </p>
    <p>
    <code>http://myhost/servlets/MCRLinkServlet?XSL.Style=xml&amp;from=DocPortal_Document_00000001&amp;type=derivate</code>
    </p>
    <p>
    Alternativ kann der Zugriff über den WebService erfolgen. Dies geschieht entweder über den URIResolver
    (Siehe Beschreibung des URIResolvers in diesem Handbuch) oder direkt als URL. Die WebService URL 
    lautet dazu beispielsweise:
    </p>
    <p><code>http://localhost:8481/services/MCRWebService?method=MCRDoRetrieveLinks&amp;to=TestPapyri_schrift_00000001</code></p>
   </section>
  </section>
  
  <section>
   <title>Die Benutzerverwaltung</title>
   <p>Dieser Teil der Dokumentation beschreibt Funktionalität, Design, Implementierung und Nutzung des MyCoRe 
   Subsystems für die Benutzerverwaltung.
   </p>
   <section>
    <title>Die Geschäftsprozesse der MyCoRe Benutzerverwaltung</title>
    <p>
    Das Benutzermanagement ist die Komponente von MyCoRe, in der die Verwaltung derjenigen Personen geregelt wird, 
    welche mit dem System umgehen (zum Beispiel als Autoren Dokumente einstellen). Zu dieser Verwaltung gehört auch die 
    Organisation von Benutzern in Gruppen. Eine weitere Aufgabe dieser Komponente ist das Ermöglichen einer An- und 
    Abmeldeprozedur.
    </p>
    <p>Ein UseCase-Diagramm (siehe Abbildung 2.3) zeigt eine Reihe typischer Geschäftsprozesse des Systems (ohne dabei 
    den Anspruch zu haben, alle Akteure zu benennen oder alle Assoziationen der Akteure mit den Geschäftsprozessen zu 
    definieren). 
    </p>
    <p>
    Offensichtlich dürfen nicht alle Akteure des Systems über die Berechtigungen verfügen, alle Geschäftsprozesse 
    durchführen zu können. Daher musste ein System von Permissions und Regeln implementiert werden: BenutzerInnen 
    haben Privilegien (z.B. die Berechtigung, neue BenutzerInnen zu erstellen). Die Vergabe der Permissions wird durch 
    die Mitgliedschaft der BenutzerInnen in Gruppen geregelt. Darüber hinaus muss das System definierten Regel gehorchen. 
    So genügt z.B. die Permission '<code>add user to group</code>' allein nicht, um genau das Hinzufügen eines Benutzers 
    zu einer Gruppe definieren zu können. Die Regel ist in diesem Fall, jeder Benutzer mit dieser Permission kann die 
    Zugehörigkeit nur zu Gruppen vergeben, in denen er oder sie selbst Mitglied ist. Auf diese Weise wird verhindert, 
    dass sich ein Benutzer oder eine Benutzerin selbst höhere Privilegien zuweisen kann. Die Privilegien und Regeln der 
    MyCoRe-Benutzerverwaltung werden weiter unten ausgeführt.
    </p>
    
    <img src="images/progguide_2user_usecase.jpg" alt="Geschäftsprozesse" title="Geschäftsprozesse"/>
    <p class="klein"><strong>Abbildung 2.3:</strong> Geschäftsprozesse der Benutzerverwaltung in MyCoRe</p>
    
   </section>
   
   <section>
    <title>Benutzer und Gruppen</title>
    <p> 
    Die Attribute von Benutzern/innen des Systems können in drei Bereiche klassifiziert werden, Account-Informationen 
    wie ID, Passwort, Beschreibung usw., Address-Informationen wie Name, Anrede, Fakultätszugehörigkeit usw. sowie 
    Informationen über die Mitgliedschaft in Gruppen. Die aktuell implementierten Benutzerattribute kann man an 
    folgender beispielhafter XML-Darstellung erkennen:<br/>
    <code>[ToDo]: to be continued ...</code>
    </p>
   </section>
  </section>
  
  <section>
   <title>Access Control List (ACL) Integration</title>
   <section>
    <title>Allgemeines</title>
   </section>
   
   <section>
    <title>Strategien der Validierung</title>
    <p>
    Das ACL-System ist nur lose an das Datenmodell von MyCoRe gekoppelt und so sind ACL-Regeln nicht zwangsweise an 
    <code>MCRObjectID</code>s gebunden, sondern nehmen als ID jeden String entgegen. Diese Flexibilität kann man sich 
    zu Nutze machen, wenn es um die Überprüfung der Zugriffsrechte geht. Bei MyCoRe gibt es drei vordefinierte Methoden, 
    die über Properties ausgewählt werden.
    </p>
    <p class="fett">Methode 1: ObjectID</p>
    <p>
    Diese Methode ist der Standardfall von DocPortal. Zu jeder ObjectID wird die ACL-Regel mit gleicher ID genommen. 
    Existiert diese nicht, wird der Zugriff verweigert. Die Pflege der ACL-Regeln, z.B. die Integration von 
    Standardregeln, übernimmt das SimpleWorkFlow-Modul, das im User Guide beschrieben wird. Dabei wird jedem neu 
    angelegten Objekt eine objektspezifische Regel angehängt. Beim Einstellen in den MyCoRe-Server, entfernt ein 
    Eventhandler die dort vorhandene Regeldefinition und legt eine entsprechende Regel für das Dokument an. Methode 1 
    ähnelt in diesem Zusammenhang der Unix-Rechteverwaltung und dem dort benutzten Befehl <code>umask</code>. Änderungen 
    an den Standardregeln gelten für neu eingestellte Objekte. Folgende Properties sind für Methode 1:
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    MCR.EventHandler.MCRObject.1.class=org.mycore.access.MCRAccessEventHandler
    MCR.EventHandler.MCRDerivate.1.class=org.mycore.access.MCRAccessEventHandler
    MCR.Access.Strategy.Class=org.mycore.access.strategies.MCRObjectIDStrategy
    ]]>
    </p><![CDATA[
    ]]></source>
    <p class="fett">Methode 2: Objekt-Typ</p>
    <p>
    Diese Methode arbeitet wie Methode 1, nutzt jedoch einen anderen Eventhandler, der nicht für jedes Objekt eine Regel 
    anlegt, sondern diese ignoriert. Das bedeutet, dass man für einzelne Objekte explizit eine Regel anlegen muss oder 
    es tritt beim Überprüfen die erweiterte Behandlung in Kraft. Diese sieht ein Zurückfallen auf die Regel des 
    Objekttyps vor und notfalls die Anwendung einer Standardregel. Die Regel für einen Objekttyp lässt sich über die 
    Kommandozeile anlegen.
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    update permission read for id default_&lt;objekttyp&gt; with rulefile grant-all.xml
    update permission writedb for id default_&lt;objekttyp&gt; with rulefile grant-editors.xml
    update permission deletedb for id default_&lt;objekttyp&gt; with rulefile grant-admin.xml
    ]]>
    </p><![CDATA[
    ]]></source>
    <p>Heißt der Objekttyp <code>document</code>, so lautet die ID für das ACL-System <code>default_document</code>. Die 
    Standardregel, die notfalls nach der Objekttyp-Regel überprüft wird, lautet <code>default</code>. Beispiele für die 
    oben genannten Regeldateien (<code>grant-*.xml</code>), finden sich in DocPortal unter <code>config/acl</code>. 
    Methode 2 reduziert gegenüber Methode 1 den Verwaltungsaufwand, sowohl auf Administratorseite als auch auf 
    Datenbankseite, wegen der reduzierten Zahl an Regelzuweisungen. So treten Änderungen an den Standardregeln sofort 
    für alle entsprechenden Objekte in Kraft.
    </p>
    <p>
    Folgende Properties sind für die Methode 2:</p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    MCR.EventHandler.MCRObject.1.class=org.mycore.access.MCRRemoveAclEventHandler
    MCR.EventHandler.MCRDerivate.1.class=org.mycore.access.MCRRemoveAclEventHandler
    MCR.Access.Strategy.Class=org.mycore.access.strategies.MCRObjectTypeStrategy
    ]]>
    </p><![CDATA[
    ]]></source>
    <p class="fett">Methode 3: Vererbung von Regeln</p>
    <p>
    Diese Methode arbeitet wie Methode 1, nutzt jedoch wieder den Eventhandler von Methode 2. Entsprechend müssen Regeln 
    für MCRObjectIDs selbst angelegt und gepflegt werden. Sollte für eine MCRObjectID keine ACL-Regel hinterlegt sein, 
    so wird Methode 3 rekursiv mit der MCRObjectID des Vaterobjekts angewandt, bis zu einer MCRObjectID eine ACL-Regel 
    existiert. Sollte es keine ACL-Regel geben, wird der Zugriff verweigert. Methode 3 ähnelt also dem Vererbungsmodell 
    von MyCoRe. Folgende Properties sind für die Methode 3:
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    MCR.EventHandler.MCRObject.1.class=org.mycore.access.MCRRemoveAclEventHandler
    MCR.EventHandler.MCRDerivate.1.class=org.mycore.access.MCRRemoveAclEventHandler
    MCR.Access.Strategy.Class=org.mycore.access.strategies.MCRParentRuleStrategy
    ]]>
    </p><![CDATA[
    ]]></source>
   </section>
  </section>
  
  <section>
   <title>Die Backend-Stores</title>
   <p>
   <table>
   <tr>
   <th colspan="1" rowspan="1">Backend</th>
   <th colspan="1" rowspan="1">Organisation</th>
   <th colspan="1" rowspan="1">Suche</th>
   <th colspan="1" rowspan="1">Ablage</th>
   <th colspan="1" rowspan="1">Volltexte</th>
   <th colspan="1" rowspan="1">Bemerkung</th>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">HSQLDB</td>
   <td colspan="1" rowspan="1">x</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">frei verfügbar; für kleine Lösungen</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">MySQL</td>
   <td colspan="1" rowspan="1">x</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">frei verfügbar; für mittlere Lösungen</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">IBM DB2</td>
   <td colspan="1" rowspan="1">x</td>
   <td colspan="1" rowspan="1"/><td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">kommerzielles Produkt; für große Lösungen</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">JDOM-Tree</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">x</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">in MyCoRe enthalten; für kleine Lösungen</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">nativ SQL</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">x</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">benötigt ein SQL / Hibernate-Backend; je nach Backend</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">Lucene</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">x</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">x</td>
   <td colspan="1" rowspan="1">frei verfügbar; für mittlere bis große Lösungen</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">FileSystem</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">x</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">je nach Plattenplatz</td>
   </tr>
   <tr>
   <td colspan="1" rowspan="1">Helix</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">x</td>
   <td colspan="1" rowspan="1"/>
   <td colspan="1" rowspan="1">kommerzielles Produkt; für Audio-/Video-Lösungen</td>
   </tr>
   </table>
   <p class="klein"><strong>Tabelle 2.1:</strong> Übersicht der MyCoRe-Backends</p>
   </p>
   <p>
   Im Backend-Bereich muss zwischen den verschieden Aufgaben der Stores unterschieden werden. Es gib Stores für die 
   Speicherung organisatorischer Informationen (z.B. User-Daten, XML-Daten usw.), Stores für die Suche und für die 
   Ablage der eigentlichen digitalen Objekte und deren Volltexte. Dabei kann die genutzte Backend-Software ggf. auch für 
   mehrere Stores verwendet werden. Eine Übersicht gibt Tabelle 2.1.
   </p>
   
   <section>
    <title>Hibernate oder nativ SQL?</title>
    <p>
    MyCoRe in der Version 1.2 bietet 2 Möglichkeiten, die Stores für die organisatorischen Daten einzubinden. 
    </p>
    <p>
    Zum einen wird über das Package <code>org.mycore.backend.sql</code> ein direkter Zugriff auf relationale Datenbanken 
    via JDBC realisiert. Der Vorteil davon sind optimale Zugriffszeiten. Nachteilig kann sich auswirken, dass nur 
    einige der am Markt verfügbaren Datenbanken integriert und getestet wurden. Es kann also bei Verwendung anderer 
    Datenbanken ggf. zu Problemen kommen (besonders beim automatischen Anlegen der Tabellen).
    </p>
    <p>
    Der zweite Weg ist die Nutzung der Hibernate-Integration. Hier übernimmt das freie Paket „Hibernate“ die Anpassung 
    an die jeweils darunter liegende Datenbank. Es wird also der gesamte Zugriff über ein fest definiertes API geregelt. 
    Der Nachteil ist ein leichter Performance-Verlust, da alle Daten durch das API verwaltet werden. Die Klassen zur 
    Arbeit mit Hibernate stehen in <code>org.mycore.backend.hibernate</code>.
    </p>
    <p>
    Welche der beiden Zugriffsarten nun in Ihrem konkreten Projekt genommen wird hängt von den ganz spezifischen 
    Eigenschaften der Anwendung und deren Umgebung sowie den personellen Ressourcen ab. Das MyCoRe-System wurde mit 
    beiden Varianten getestet. 
    </p>
    <note label="Hinweis"> 
    Während es in der nativ-SQL-Anwendung möglich ist, für jeden XML-Daten-Store eine eigene Tabelle anzugeben, werden 
    die XML-Daten unter Hibernate immer in einer gemeinsamen Tabelle gehalten (Property <code>MCR.xml_store_sql_table</code>.
    </note>
   </section>
   
   <section>
    <title>Das Search-Backend JDOM-Tree</title>
    <p>
    Das MyCoRe-Paket bietet eine simple Standard-Lösung für die Suche in kleinen Beispielanwendungen, ohne dass 
    zusätzliche externe Produkte verwendet werden müssen. Die XML-Daten werden im JDOM-Tree zum Startzeitpunkt der 
    Applikation direkt aus der XML-SQL-Tabelle gelesen, teilweise hinsichtlich der Umlaute normalisiert und im weiteren 
    Verlauf der Anwendung im Hauptspeicher verwaltet. <code>Create</code>, <code>Update</code>, <code>Delete</code> auf 
    die XML-SQL-Tabellen wird direkt mit dem im Speicher befindlichen Datenbaum synchronisiert.
    </p>
    <p>
    Die XPath-Suchanfrage wird in ein XSL-Stylesheet umgewandelt, welches gegen die XML-Daten im Hauptspeicher läuft. 
    Als Ergebnis wird die Liste der Treffer-IDs zurückgegeben. Für die Datumssuche wurde eine zusätzliche XSL-Funktion 
    implementiert. Suchdaten im Operator <code>contains</code> werden hinsichtlich der Umlaute normalisiert 
    (z.B. <code>contains("Eindrücke") → contains("eindruecke")</code>).
    </p>
    <table>
    <tr>
    <th colspan="1" rowspan="1">Metadaten-Typ</th>
    <th colspan="1" rowspan="1">Felder</th>
    </tr>
    <tr>
    <td colspan="1" rowspan="1">MCRMetaLangText</td>
    <td colspan="1" rowspan="1">tag/subtag/text()</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1">MCRMetaPersonName</td>
    <td colspan="1" rowspan="1">tag/subtag/firstname/text()tag/subtag/callname/text()tag/subtag/surname/text()tag/subtag/fullname/text()</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1">MCRMetaInstitutionName</td>
    <td colspan="1" rowspan="1">tag/subtag/fullname/text()</td>
    </tr>
    </table>
    <p class="klein"><strong>Tabelle 2.2:</strong> Felder mit Umlautnormalisierung im Search-Store</p>
    
    <note label="Hinweis">
    Dieser Search-Store ist nur bis zu einigen 100 Datensätzen performant und nicht für Produktionssysteme gedacht.
    </note>
   </section>
   
  </section>
  
  <section>
   <title>Die Frontend Komponenten</title>
   <section>
   <title>Erweiterung des Commandline-Tools</title>
   <p>
   Dieser Abschnitt beschäftigt sich mit der Struktur des Commandline-Tools und dessen Erweiterung mit eigenen 
   Kommandos. Dem Leser sei vorab empfohlen, den entsprechenden Abschnitt im MyCoRe-UserGuide durchzuarbeiten. 
   </p>
   
   <img src="images/progguide_commandlinetool.jpg" alt="Java-Klassen" title="Java-Klassen"/>
    <p class="klein"><strong>Abbildung 2.4:</strong> Zusammenhang der Java-Klassen</p>
    
    <p>
    Das Commandline-Tool ist die Schnittstelle für eine interaktive Arbeit mit dem MyCoRe-System auf 
    Kommandozeilen-Basis. Sie können dieses System ebenfalls dazu verwenden, mittels Skript-Jobs ganze Arbeitsabläufe 
    zu automatisieren. Dies ist besonders bei der Massendatenverarbeitung sehr hilfreich. In DocPortal werden Ihnen 
    schon in den Verzeichnissen unixtools bzw. dostools eine ganze Reihe von hilfreichen Skripts für Unix bzw. MS 
    Windows mitgegeben. 
    </p>
    <p>
    All diese Skripte basieren auf dem Shell-Skript <code>bin/mycore.sh</code> bzw. <code>bin/mycore.cmd</code>, 
    welches im Initialisierungsprozess der Anwendung via ant mit gebaut wird (<code>ant create.unixtools</code> bzw. 
    <code>ant create.dostools</code>). Sollten Sie zu einem späteren Zeitpunkt eventuell einmal 
    <code>*.jar</code>-Dateien in den <code>lib</code>-Verzeichnissen ausgetauscht haben oder sonstige Änderungen 
    hinsichtlich des Java-CLASSPATH durchgeführt haben, so führen Sie für ein Rebuild des MyCoRe-Kommandos ein 
    <code>ant scripts</code> durch.</p><p>Die Abbildung 2.4 soll einen Überblick über die Zusammenhänge der einzelnen 
    Java-Klassen im Zusammenhang mit der nutzerseitigen Erweiterung des Commandline-Tools geben.
    </p>
    <p>
    Es ist relativ einfach, weitere Kommandos hinzuzufügen. In DocPortal sind bereits alle nötigen Muster vorhanden.
    </p>
    <ol>
    <li>Im Verzeichnis <code>~/docportal/sources/org/mycore/frontend/cli</code> finden Sie eine Java-Klasse 
    <code>MCRMyCommand.java</code>. Diese ist ein Muster, kopieren Sie sie in eine Java-Klasse z.B. 
    <code>MCRTestCommand.java</code>. Die Klasse kann im Package <code>org.mycore.frontend.cli</code> liegen, sie können 
    Sie aber auch in den Bereich tun, zu dem es logisch gehört.</li>
    <li>Ersetzen Sie alle <code>MCRMyCommand</code>-String durch <code>MCRTestCommand</code>.</li>
    <li>Im Konstruktor werden nun alle neuen Kommandos definiert. Hierzu werden der <code>ArrayList command</code> 
    jeweils zwei weitere Zeilen hinzugefügt. Die erste enthält den Text-String für das Kommando. Stellen, wo Parameter 
    eingefügt werden sollen, sind mit {...} zu markieren, wobei ... eine fortlaufende Nummer beginnend mit 0 ist 
    (siehe Beispielcode). In der zweiten Zeile ist nun der Methodenaufruf anzugeben. Für jeden Parameter ist das 
    Schlüsselwort <code>String</code> anzugeben.</li>
    <li>Nun muss das eigentliche Kommando als Methode dieser Kommando-Klasse implementiert werden. Orientieren Sie sich 
    dabei am mitgelieferten Beispiel. (Die Methode <code>convertData</code> sollten Sie in Ihrer Klasse löschen. Ebenso 
    die Definition in der commands-ArrayList.)</li>
    <li>Compilieren Sie nun die neue Klasse mit <code>cd ~/docportal</code>; <code>ant jar</code></li>
    <li>Als letztes müssen Sie die Klasse in das System einbinden. Die mit dem MyCoRe-Kern mitgelieferten Kommandos sind 
    bis auf die Basis-Kommandos über die Property-Variable <code>MCR.internal_command_classes</code> in 
    <code>~/docportal/mycore.properties</code> dem System bekannt gemacht. Für externe Kommandos steht hierfür in der 
    Konfigurationsdatei <code>mycore.properties.application</code> die Variable <code>MCR.external_command_classes</code> 
    zur Verfügung. Hier können Sie eine mit Komma getrennte Liste Ihrer eigenen Kommando-Java-Klassen angeben.</li>
    <li>Wenn Sie nun <code>mycore.sh</code> bzw. <code>mycore.cmd</code> starten und DEBUG für den Logger eingeschaltet 
    haben, so sehen Sie Ihre neu integrierten Kommandos.</li>
    </ol>
   </section>
   
   <section>
    <title>Das Zusammenspiel der Servlets mit dem MCRServlet</title>
    <p>
    Als übergeordnetes Servlet mit einigen grundlegenden Funktionalitäten dient die Klasse <code>MCRServlet</code>. Die 
    Hauptaufgabe von <code>MCRServlet</code> ist dabei die Herstellung der Verbindung zur Sessionverwaltung 
    (siehe Abschnitt <a href="site:sessions_2_1">Die Session-Verwaltung</a>). Das Zusammenspiel der relevanten Klassen ist im Klassendiagramm 
    (Abbildung 2.5) verdeutlicht.
    </p>
    
    <img src="images/progguide_2frontend_mcrservlet.jpg" alt="Java-Klassen" title="Java-Klassen"/>
    <p class="klein"><strong>Abbildung 2.5:</strong> Klassendiagramm <code>Common Servlets</code></p>
    
    <p>
    Wie an anderen Stellen im MyCoRe-System auch, kann auf Konfigurationsparameter wie zum Beispiel den Einstellungen 
    für das Logging über das statische Attribut <code>MCRConfiguration</code> zugegriffen werden.
    </p>
    <p>
    <code>MCRServlet</code> selbst ist direkt von <code>HttpServlet</code> abgeleitet. Sollen andere Servlets im 
    MyCoRe-Softwaresystem die von MCRServlet angebotenen Funktionen automatisch nutzen, so müssen sie von 
    <code>MCRServlet</code> abgeleitet werden. Im Klassendiagramm ist das durch die stellvertretende Klasse 
    <code>MCRAnyOtherServlet</code> angedeutet. Es wird empfohlen, dass die abgeleiteten Servlets die Methoden 
    <code>doGet()</code> und <code>doPost()</code> nicht überschreiben, denn dadurch werden bei einem eingehenden 
    Request auf jeden Fall die Methoden von <code>MCRServlet</code> ausgeführt.
    </p>
    <p>
    Der Programmablauf innerhalb von <code>MCRServlet</code> ist im folgenden Sequenzdiagramm (siehe Abbildung 2.6) 
    dargestellt. Bei einem eingehenden Request (<code>doGet()</code> oder <code>doPost()</code>) wird zunächst 
    an <code>MVRServlet.doGetPost()</code> delegiert. (Bei dieser Delegation wird ein Parameter mitgeführt, über den 
    feststellbar ist, ob es sich um einen GET- oder POST-Request gehandelt hat.)
    </p>
    
    <img src="images/progguide_2frontend_mcrservletsequenz.jpg" alt="Common Servlets" title="Common Servlets"/>
    <p class="klein"><strong>Abbildung 2.6:</strong> Sequenzdiagramm <code>Common Servlets</code></p>
    
    <p>
    Falls nicht schon aus vorhergehenden Anfragen an das <code>MCRServlet</code> bekannt, werden in 
    <code>doGetPost()</code> die Base-URL und die Servlet-URL des Systems bestimmt. Dabei besteht die Servlet-URL 
    aus der Base-URL und dem angehängten String '<code>servlets/</code>'. Darauf folgend wird die für diese Session 
    zugehörige Instanz von <code>MCRSession</code> bestimmt. Das Verfahren dazu ist im Ablaufdiagramm (Abbildung 2.7) 
    dargestellt.
    </p>
    <p>
    Die Session kann bereits durch vorhergehende Anfragen existieren. Falls dies der Fall ist, kann das zugehörige 
    Session-Objekt entweder über eine im <code>HttpServletRequest</code> mitgeführte SessionID identifiziert oder 
    direkt der HttpSession entnommen werden. Existiert noch keine Session, so wird ein neues Session-Objekt über den 
    Aufruf von <code>MCRSessionMgr.getCurrentSession()</code> erzeugt. Nachfolgend wird das Session-Objekt an den 
    aktuellen Thread gebunden und zusätzlich in der HttpSession abgelegt.
    </p>
    <p>Im Sequenzdiagramm gehen wir davon aus, dass die Sitzung neu ist und deswegen ein Session-Objekt über 
    <code>MCRSessionMgr.getCurrentSession()</code> erzeugt werden muss. Schließlich wird eine Instanz von 
    <code>MCRServletJob</code> erzeugt. Diese Klasse ist nichts weiter als ein Container für die aktuellen 
    HttpServletRequest und HttpServletResponse Objekte und hat keine weitere Funktionalität (siehe Klassendiagramm, 
    Abbildung 2.5). (Das Speichern des Session-Objekts in der HttpSession ist notwendig, weil in einer typischen 
    Servlet-Engine mit Thread-Pool Umgebung nicht davon ausgegangen werden darf, dass bei aufeinander folgenden Anfragen 
    aus demselben Kontext auch derselbe Thread zugewiesen wird.)
    </p>
    
    <img src="images/progguide_2frontend_mcrservletfluss.jpg" alt="MCRServlet.doGetPost()" title="MCRServlet.doGetPost()"/>
    <p class="klein"><strong>Abbildung 2.7:</strong> Ablaufdiagramm für MCRServlet.doGetPost()</p>
    
    <p>
    An dieser Stelle wird der Programmfluss an das abgeleitete Servlet (in diesem Beispiel 
    <code>MCRAnyOtherServlet</code>) delegiert. Dazu muss das Servlet eine Methode mit der Signatur
    </p>
    <p class="break"><code>public void doGetPost(MCRServletJob job) {}</code></p>
    <p>
    implementieren. Wie das Sequenzdiagramm beispielhaft zeigt, kann <code>MCRAnyOtherServlet</code> danach 
    gegebenenfalls auf das Session-Objekt und damit auf die Kontextinformationen zugreifen. Der Aufruf an den 
    SessionManager dazu wäre:
    </p>
    <p class="break"><code>MCRSession mcrSession=MCRSessionMgr.getCurrentSession();</code></p>
    <p>
    Es sei bemerkt, dass dies nicht notwendigerweise genau so durchgeführt werden muss, da wegen der geschilderten 
    Probleme mit <code>threadlocal</code> Variablen in Servlet-Umgebungen das Session-Objekt auch in der HttpSession 
    abgelegt sein muss, könnte man die Kontextinformationen auch aus der übergebenen Instanz von 
    <code>MCRServletJob</code> gewinnen.
    </p>
   </section>
   
   <section>
    <title>Das Login-Servlet und MCRSession</title>
    <p>
    Das <code>LoginServlet</code>, implementiert durch die Klasse <code>MCRLoginServlet</code>, dient zum Anmelden 
    von Benutzern und Benutzerinnen über ein Web-Formular. Die Funktionsweise ist wie folgt: Wie in Abschnitt 3.7.2 
    empfohlen, überschreibt <code>MCRLoginServlet</code> nicht die von <code>MCRServlet</code> geerbten 
    Standard-Methoden <code>doGet()</code> und <code>doPost()</code>. Meldet sich ein Benutzer oder eine Benutzerin 
    über das <code>MCRLoginServlet</code> an, so wird daher zunächst die Funktionalität von <code>MCRServlet</code> 
    ausgenutzt und die in Abschnitt 3.7.2 beschriebene Verbindung zur Sessionverwaltung herstellt. Wie dort ebenfalls 
    beschrieben, wird der Programmfluss an das Login-Servlet über die Methode <code>MCRLoginServlet.doGetPost()</code> 
    delegiert. Der Ablauf in <code>doGetPost()</code> wird im Diagramm auf Abbildung 2.8 dargestellt und ist 
    selbsterklärend.
    </p>
    
    <img src="images/progguide_2frontend_mcrloginservletfluss.jpg" alt="MCRServlet.doGetPost()" title="MCRServlet.doGetPost()"/>
    <p class="klein"><strong>Abbildung 2.8:</strong> Ablaufdiagramm für MCRServlet.doGetPost()</p>
    
    <p>
    Der resultierende XML Output-Stream muss vom zugehörigen Stylesheet verarbeitet werden und hat die in 
    Abbildung 2.9 gezeigte Syntax.
    </p>
    
    <img src="images/loginservletsoutput.jpg" alt="MCRServlet.doGetPost()" title="MCRServlet.doGetPost()"/>
    <p class="klein"><strong>Abbildung 2.9:</strong> XML Output des LoginServlets</p>
    
    
    <p>Bei einer missglückten Anmeldung wird der Grund dafür in Form eines Attributes gespeichert. Das Stylesheet kann 
    dann die entsprechende Meldung ausgeben. Die Gast-User-ID und das Gast-Passwort werden aus einer Konfigurationsdatei 
    gelesen. Die URL schließlich wird dem Http-Request entnommen und sollte dort von der aufrufenden Seite bzw. vom 
    aufrufenden Servlet gesetzt sein. Ist sie nicht gesetzt, so wird die Base-URL des MyCoRe-Systems verwendet.
    </p> 
   </section>
   
   <section>
    <title>Generieren von Zip-Dateien</title>
    <p>
    Das Zip-Servlet, implementiert durch die Klasse <code>MCRZipServlet</code>, dient dem Ausliefern der Derivate und 
    der Objektmetadaten als gepackte Zip-Datei. Aus der Konfigurationsdatei <code>mycore.properties.zipper</code> holt 
    sich das Servlet über die Variable <code>MCR.zip.metadata.transformer</code> den Namen des Stylesheets, welches die 
    Metadatentransformation in das gewünschte Auslieferungsformat vornimmt. In DocPortal verwenden wir hierfür Qualified 
    Dublin Core.
    </p>
    <p>Aufrufmöglichkeiten des Servlets:</p>    
    <p class="breaksource">  
    <source xml:space="preserve"><![CDATA[
     
    $ServletsBaseURL/MCRZipServlet?id=MCRID
    
    $ServletsBaseURL/MCRZipServlet?id=MCRID/foldername
    ]]><![CDATA[
    ]]></source>
    </p>    
    <p>
    MCRID ist die ID eines Objekts vom Typ <code>&lt;mycoreobject&gt;</code> oder <code>&lt;mycorederivate&gt;</code>. 
    Im Fall von <code>&lt;mycoreobject&gt;</code> werden die Dateien aller dem Objekt zugeordneten Derivate und ein 
    XML-File mit den Metadaten des Objekts zusammengepackt. Im Fall von <code>&lt;mycorederivate&gt;</code> werden alle 
    Dateien des angegebenen Derivates zusammengepackt. Die Option <code>MCRID/foldername</code> ist nur zulässig, wenn 
    <code>MCRID</code> ein Objekt vom Typ <code>&lt;mycorederivate&gt;</code> bezeichnet. Dann wird nur der mit 
    <code>foldername</code> angegebene Ordner des betreffenden Derivats gezippt.
    </p>
    <p>
    Wer geschützte Inhalte anbietet, sollte das Zip-Servlet erst dann in seine Anwendung integrieren, wenn die 
    Zugriffskontrolle in MyCoRe gewährleistet werden kann. Dies ist momentan (04.2005) noch nicht der Fall, das 
    Zip-Servlet lässt sich mit jeder MCRID aufrufen.
    </p>
   </section>
  </section>
  
  <section>
   <title>XML Funktionalität</title>
   
   <section>
    <title>URI-Resolver</title>
    <p>
    Die Klasse <code>org.mycore.common.xml.MCRURIResolver</code> implementiert einen Resolver, mit dem an verschiedenen 
    Stellen im MyCoRe-System XML-Daten über URI's gelesen werden können. Der Resolver wird zur Zeit an folgenden Stellen 
    eingesetzt:
    </p>
    <ul>
    <li>Bei der Verarbeitung von Stylesheets im LayoutServlet, wenn XML-Daten über die XSL-Funktion 
    <code>document()</code> in ein Stylesheet nachgeladen werden oder wenn ein untergeordnetes Stylesheet mittels 
    <code>xsl:include</code> nachgeladen wird.
    </li>
    <li>Beim Import von Editor-Definitionsteilen mittels des <code>include</code>-Elementes des Editor-Frameworks.
    </li>
    </ul>
    <p>Der Resolver unterstützt die folgenden Schemata bzw. Protokolle:</p>
    <p class="kasten"><code>file://[Pfad]</code></p>
    <p>liest eine statische XML-Datei vom Dateisystem des Servers</p>    
    <p class="break">Beispiel: 
    <source xml:space="preserve"><![CDATA[
     
    file:///usr/local/tomcat/conf/server.xml
    
    liest die Datei 
    
    /usr/local/tomcat/conf/server.xml
    ]]><![CDATA[
    ]]></source>
    </p>
    <p class="kasten"><code>webapp:[Pfad]</code></p>
    <p>
    liest eine statische XML-Datei vom Dateisystem der Web-Applikation. Im Gegensatz zur file()-Methode kann der Pfad 
    der zu lesenden Datei relativ zum Wurzelverzeichnis der Web-Applikation angegeben werden. Der Zugriff erfolgt 
    direkt, d.h. ohne HTTP Request oder Anwendung eines Stylesheets.
    </p>
    <p class="break">Beispiel: <br/>
    <code>webapp:config/labels.xml</code></p>
    <p class="kasten"><code>http://[URL]</code> <br/>
    <code>https://[URL]</code></p>
    <p>liest eine XML-Datei von einem lokalen oder entfernten Webserver</p>
    <p class="kasten"><code>request:[Path]</code></p>
    <p>
    liest eine XML-Datei durch einen HTTP Request an ein Servlet oder Stylesheet innerhalb der aktuellen 
    MyCoRe-Anwendung. Im Gegensatz zur http/https Methode ist der Pfad relativ zur Basis-URL der Web-Applikation 
    anzugeben, die MCRSessionID wird automatisch als HTTP GET Parameter ergänzt.
    </p>
    <p class="break">Beispiel:<br/>
    <code>request:servlets/MCRLinkServlet?</code><br/>
    <code>XSL.Style=xml&amp;form=&amp;to=DocPortal_document_00000001&amp;type=derivate</code>
    </p>
    <p class="kasten"><code>resource:[Path]</code></p>
    <p>
    liest eine XML-Datei aus dem CLASSPATH der Web-Applikation, d.h. die Datei wird zunächst im Verzeichnis 
    <code>WEB-INF/classes/</code> und als nächstes in einer der jar-Dateien im Verzeichnis <code>WEB-INF/lib/</code> der 
    Web-Applikation gesucht. Diese Methode bietet sich an, um statische XML-Dateien zu lesen, die in einer jar-Datei 
    abgelegt sind.
    </p>
    <p class="break">Beispiel:<br/>
    <code>resource:ContentStoreSelectionRules.xml</code>
    </p>
    <p class="kasten"><code>session:[Key]</code></p>
    <p>
    liest ein XML-Element, das als JDOM-Element in der aktuellen MCRSession abgelegt ist. Mittels der <code>put()</code> 
    Methode der Klasse MCRSession kann analog zu einer Java-Hashtable unter einem Schlüssel ein Objekt abgelegt werden. 
    Ein Servlet kann so z.B. ein JDOM-Element in der <code>MCRSession</code> ablegen, den Schlüssel einem Stylesheet 
    über einen XSL-Parameter mitteilen. Der MyCoRe Editor kann dieses JDOM-Element dann mittels der <code>get()</code> 
    Methode aus der Session lesen. 
    </p>
    <p class="break">Beispiel: <br/>
    <code>session:mylist</code><br/>
    liest das JDOM XML-Element, das als Ergebnis von <br/>
    <code>MCRSessionMgr.getCurrentSession().get("mylist");</code><br/>
    zurückgegeben wird.</p>
    <p class="kasten"><code>mcrobject:[MCRObjectID]</code></p>
    <p>liest die XML-Darstellung der Metadaten eines MCRObject aus.</p>
    <p class="break">Beispiel:<br/>
    <code>mcrobject:DocPortal_document_07910401</code></p>
    <p class="kasten"><code>classification:[Classification Query]</code></p>
    <p>gibt eine Klassifikation in unterschiedlichen Formaten aus, wobei „Classification Query“ folgendes Format hat:</p>
    <p class="break"><code>{editor['['formatAlias']']|metadata}:{Levels}[:noEmptyLeaves]:{parents|children}:{ClassID}[:CategID]</code></p>
    <p>Die einzelnen Parameter sind durch Doppelpunkte getrennt.</p>
    <ol>
    <li>Rückgabetyp ist wahlweise im MyCoRe <code>metadata</code> Format oder für eine Editor-Selectbox 
    (<code>editor</code>). Letztere kann für den Label-Text noch unterschiedliche Formatanweisungen enthalten, die mit 
    <code>formatAlias</code> referenziert werden.<br/>
    Das Property <code>MCR.UriResolver.classification.format.{formatAlias}</code> enthält dann die Formatieranweisung. 
    Diese besteht aus beliebigem Text kombiniert mit Platzhaltern:
    <ol><li><code>{id}</code> steht für die Kategorie-ID,</li>
        <li><code>{count}</code> steht für die Zahl der zugeordneten MyCoRe-Objekte,</li>
        <li><code>{text}</code> steht für das Attribut text im label-Tag der Klassifikationsdefinition,</li>
        <li><code>{description}</code> steht für das Attribut description im label-Tag der Klassifikationsdefinition. </li>
    </ol>
    </li>
    <li><code>Levels</code> gibt an, wieviel Hierarchiestufen dargestellt werden. Bei Angabe der CategID ist dies die 
    Anzahl der Kindkaterogiehierarchiestufen. Ist Levels „<code>-1</code>“ angegeben, so bedeutet dies „komplette 
    Hierarchie“.
    </li>
    <li><code>noEmptyLeaves</code> ist ein optionaler Parameter. Wenn angegeben, werden leere Kategorien ohne Objekte
    nicht mit ausgegeben. Diese Funktion ist nur für den Rückgabetyp <code>editor</code>, d.h. sinnvollerweise in Suchmasken,
    implementiert.</li>
    <li><code>parents</code> oder <code>children</code> gibt an, ob bei Angabe einer <code>CategID</code> zusätzlich 
    alle übergeordneten Kategorien mit zurückgegeben werden (<code>parents</code>) oder ob nur die Kinder der Kategorie 
    berücksichtigt werden sollen. Bei Angabe eines positiven Levels und „<code>parents</code>“ werden sowohl die Eltern 
    ausgegeben, wie auch <code>{Levels}</code> Hierarchieebenen der Kinder.
    </li>
    <li><code>ClassID</code> ist die Klassifikations-ID</li>
    <li><code>CategID</code> ist Kategorie-ID</li>
    </ol>
    <p class="break">Beispiele:
    <ul>
    <li><code>classification:editor:-1:children:DocPortal_class_00000001</code></li>
    <li><code>classification:editor[CountDocument]:2:noEmptyLeaves:children:DocPortal_class_00000002</code></li>
    <li><code>classification:metadata:0:parents:DocPortal_class_00000001:Unis.Jena</code></li>
    </ul>
    </p>
    <p class="kasten"><code>mcrws:[WebService Request]</code></p>
    <p>
    fordert über einen WebService-Request XML-Darstellungen entfernter Hosts der Metadaten eines MCRObject, der einer 
    Klassifikation oder eines Links. Für den WebService request sind folgende Formen derzeit möglich:
    </p>
    <p class="break"><code>operation=MCRDoRetrieveObject&amp;ID={MCRObjectID}&amp;host={hostAlias}</code></p>
    <p class="break"><code>operation=MCRDoRetrieveClassification&amp;level={level}&amp;type={type}
    &amp;classid={classid}&amp;categid={categid}&amp;format={format}&amp;host={hostAlias}</code></p>
    <p class="break"><code>operation=MCRDoRetrieveLinks&amp;from=[{MCRObjectID}]&amp;to=[{MCRObjectID}]
    &amp;type=[{type}]&amp;host={hostAlias}</code></p>
    <p>Die Werte from und to sind alternativ zu belegen, je nach dem, ob nach der Quelle oder dem Ziel eines Links 
    gefragt wird. (Siehe auch Kapitel zur Link Table)</p>
    <p class="break">Beispiel:<br/>
    <code>mcrws:operation=MCRDoRetrieveObject&amp;ID=DocPortal_document_07910401&amp;host=remote</code>
    </p>
    <p class="break"><code>mcrws:MCRDoRetrieveClassification&amp;level=0&amp;type=parents&amp;classid=
    DocPortal_class_00000001&amp;categid=Unis.Jena&amp;format=metadata&amp;host=remote</code></p>
    <p class="break"><code>mcrws:MCRDoRetrieveLinks&amp;from=&amp;to=DocPortal_document_00000001&amp;
    type=derivate&amp;host=remote</code></p>
    <p class="kasten"><code>access:[ Access Value ]</code></p>
    <p>liest die XML-Darstellung der ACL-Metadaten aus.</p>
    <p><code>action=[all|{permision}&amp;object={MCRObjectID}</code></p>
    <p class="break">Beispiel:<br/>
    <code>access:action=all&amp;object=DocPortal_document_07910401</code><br/>
    <code>access:action=writedb&amp;object=DocPortal_document_07910401</code>
    </p>
    <p class="kasten"><code>query:[ Query Value ]</code></p>
    <p>startet eine Query und liefert eine Liste der Treffer als mcr:results XML-Darstellung aus.</p>
    <p><code>term={search_term}&amp;sortby={sort_term}&amp;order={order_term}</code></p>
    <p class="break">Beispiel:<br/>
    <code>query:term=objectType=document&amp;sortby=title</code>
    </p>
    <p>
    Sie können mit diesem Resolver z.B. aus einem XSL Stylesheet heraus eine Suche in MyCoRe anstoßen und die 
    Suchergebnisse (Element mcr:results) in eine Variable ablegen:
    </p>
    <p>
    <code>&lt;xsl:variable name="hits"</code><br/>
     <code>xmlns:encoder="xalan://java.net.URLEncoder"</code><br/>
     <code>select="document(concat('query:term=',encoder:encode(</code><br/> 
      <code>'objectType = fodokperson')))/mcr:results" /&gt;</code>
    </p>
    <p>
    Die Verwendung von java.net.URLEncoder ist notwendig, damit Leerzeichen, Sonderzeichen etc. in der eigentliche 
    Query codiert werden. Die einzelnen Suchtreffer werden als mcr:hit Elemente geliefert, die im wesentlichen nur die 
    IDs der gefundenen Objekte enthalten. Über diese IDs und z.B. das URIResolver Schema „mcrobject:ID“ können Sie dann 
    die Metadaten der gefundenen Objekte weiterverarbeiten. So geben Sie z.B. eine gefundene ID aus:
    </p>
    <p><code>&lt;xsl:value-of select="$hits/mcr:hit/@id" /&gt;</code></p><p class="Standard"/>
    <p class="kasten"><code>ifs:[ Derivate ID ]</code></p>
    <p>startet den Abruf eines Derivate-Contents.</p>
    <p><code>{MCRDerivateID}?host={hostAlias}</code></p>
    <p class="break">Beispiel:<br/>
    <code>ifs:DocPortal_derivate_00000001?host=remote</code>
    </p>
    <p class="kasten"><code>notnull:[uri]</code></p>
    <p>
    stellt sicher, dass es bei Aufruf der genannten URI keine NullPointerException gibt. Sollte es bei Verarbeitung der 
    anhängenden URI eine Exception geben, wird diese geloggt. Im Falle einer Exception oder wenn die URI den Wert NULL 
    zurückgibt, liefert dieser Resolver stattdessen eine leere XML-Datei. Dies ist z.B. hilfreich, um in XSL Stylesheets 
    URIs zu verwenden, aber gegen Fehler abzusichern.
    </p>
    <p class="break">Beispiel:notnull:<code>mcrobject:DocPortal_document_07910401</code></p>
    <p>
    Bei der Verarbeitung von <code>include</code>-Anweisungen in Editor-Definitionen dürfen die folgenden URI-Schemata 
    verwendet werden:
    </p>
    <p class="kasten"><code>classification file http https request resource session webapp mcrobject notnull</code></p>
    <p>
    Beim Aufruf der XSL-Funktion <code>document()</code> innerhalb eines Stylesheets können die folgenden URI-Schemata 
    verwendet werden:
    </p>
    <p class="kasten">
    <code>classification file http https resource session query webapp mcrobject query access mcrws notnull</code>
    </p>
    <p class="kasten"><code>xslStyle:[stylesheet]:[URI-Resolver]</code></p>
    <p>
    wendet das Stylesheet [stylesheet] auf die XML-Datei des URI-Resolvers [URI-Resolver] an und gibt das Ergebnis als 
    XML zurück. Das Stylesheet befindet sich im Classpath der Anwendung. Die Extension .xsl entfällt im Parameter 
    [stylesheet].
    </p>
    <p class="break">Beispiel:<br/>
     <code>xslStyle:hosts:resource:hosts.xml</code>
     </p>
     <p>
     Liest zunächst die Datei hosts.xml aus dem Classpath und wendet darauf das Stylesheet hosts.xsl aus dem Classpath 
     an.
     </p>
    </section>
    
    <section>
     <title>Erweiterung des URI-Resolvers</title>
     <p>
     Unter Umständen kann es nötig sein den URIResolver für eigene Anwendungen zu erweitern. Dabei ist es nicht möglich 
     vorhandene URI-Schemas zu überschreiben, jedoch neue den bereits vorhandenen hinzuzufügen. Für jedes Schema z.B. 
     <code>file</code> gibt es einen Resolver, der entsprechende URIs auflösen kann. Dieser Resolver muss die 
     Schnittstelle <code>MCRURIResolver.MCRResolver</code> im Paket <code>org.mycore.common.xml</code> implementieren. 
     Für die Zuweisung eines Schemas zur <code>MCRResolver</code>-Implementierung ist der 
     <code>MCRResolverProvider</code> verantwortlich, der diese Schnittstelle aus <code>MCRURIResolver</code>
     implementiert. Letzterer stellt eine Abbildung von Schema-Strings zu <code>MCRResolver</code>-Instanzen zur 
     Verfügung. Der <code>MCRResolverProvider</code> kann also beliebig viele <code>MCRResolver</code> zu den bereits 
     in MyCoRe integrierten hinzufügen. Eingebunden wird ein zusätzlicher <code>MCRResolverProvider</code> mittels 
     folgendem Property:</p>
     <p class="kasten">MCR.UriResolver.externalResolver.class = &lt;voller Klassenname&gt;</p>
    </section>
   </section>
   
   <section>
    <title>Das MyCoRe Editor Framework</title>
    <section>
     <title>Funktionalität</title>
     <p>
     Das Metadatenmodell einer MyCoRe Anwendung ist frei konfigurierbar. Dementsprechend benötigt ein MyCoRe System 
     auch einen Online-Editor für diese Metadaten, der frei konfigurierbar ist. Aus dieser Anforderung heraus entstand 
     das MyCoRe Editor Framework, das aus einem XSL Stylesheet und einer Menge von Java-Klassen besteht.
     </p>
     <p>
     Verschiedene MyCoRe Anwendungen können über XML-Definitionsdateien nahezu beliebige Online-Eingabemasken für 
     Metadaten gestalten. Das Framework verarbeitet diese Editor-Definitionsdateien und generiert daraus den HTML-Code 
     der Webseite, die das Online-Formular enthält. Nach Abschicken des Formulars generiert das Framework aus den 
     Eingaben ein dem Metadatenmodell entsprechendes XML-Dokument, das an ein beliebiges Servlet zur endgültigen 
     Verarbeitung (z.B. zur Speicherung) weitergereicht wird. Ebenso können existierende XML-Dokumente als Eingabe in 
     die Formularfelder des Editors dienen, so dass sich vorhandene Metadaten bearbeiten lassen. Das Framework regelt 
     dabei die Abbildung zwischen den XML-Elementen und –Attributen und den Eingabefeldern der resultierenden 
     HTML-Formularseite, indem es die in der Editor-Definitionsdatei hinterlegten Abbildungsregeln verarbeitet.
     </p>
     <p>
     Inzwischen ist das Editor Framework auch in der Lage, einzelne Dateien zusammen mit den Formulareingaben in das 
     System hochzuladen und zur Weiterverarbeitung an ein Servlet durchzureichen. Die Validierung der Eingabefelder ist 
     strukturell vorbereitet, aber derzeit noch nicht implementiert. Prinzipiell erlaubt das Editor Framework, 
     beliebige XML-Dokumente in HTML-Formularen zu erzeugen oder zu bearbeiten.
     </p>
    </section>
    
    <section>
     <title>Architektur</title>
     <p>Die folgende Abbildung zeigt die Architektur des MyCoRe Editor Frameworks:</p>
     <p><code>[ToDo]: Bild folgt</code></p>
     <p>
     Ein HTML Formular, das man mit Hilfe des Frameworks realisieren möchte, wird im folgenden <em>Editor</em> genannt. 
     Jeder Editor besitzt eine eindeutige ID (z.B. <code>document</code> (in den MyCoRe-Applikationen meist eine 
     Mischung aus dem MCRObjectID-Typ und der Bezeichnung eines Verarbeitungsschrittes [editor-commit-document.xml]).
     und eine Definitionsdatei im XML-Format (<code>editor-document.xml</code>). In dieser Definitionsdatei ist 
     festgelegt, aus welchen Eingabefeldern in welcher optischen Anordnung der Editor besteht und wie die Abbildung 
     zwischen den Eingabefeldern und der zugrunde liegenden XML-Darstellung der Daten aussieht. 
     </p>
     <p>
     Ein Editor ist üblicherweise in eine umgebende Webseite eingebunden, die das Formular enthält. Die umgebenden 
     Webseiten referenzieren über die Editor ID den Editor, der an einer bestimmten Stelle der sichtbaren Webseite 
     eingebunden werden soll. Der HTML-Code der Webseite selbst wird in einem MyCoRe System aus einem beliebigen 
     XML-Dokument (z.B. anypage.xml [z.B. editor_form_...xml in DocPortal]) mittels eines dazu passenden XSL Stylesheets 
     (anypage.xsl [z.B. MyCoReWebPage.xsl in DocPortal]) generiert. Um in eine solche Webseite einen Editor integrieren 
     zu können, muss <code>anypage.xml</code> ein XML-Element enthalten, das auf den einzubindenden Editor verweist, 
     zusätzlich muss <code>anypage.xsl</code> das Stylesheet <code>editor.xsl</code> einbinden. Das Stylesheet 
     verarbeitet die Referenz auf den Editor und integriert den HTML-Code des Formulars in die umgebende Webseite. So 
     ist es möglich, Editor-Formulare in beliebige Webseiten einzubinden, unabhängig von ihrem Layout oder ihrer 
     Struktur.
     </p>
     
     <img src="images/include_editor.png" alt="Editor einbinden" title="Editor einbinden"/>
     <p class="klein"><strong>Abbildung 2.10:</strong> Einbindung des Editors in eine Webseite</p>
    
    <p>
    Das Stylesheet <code>editor.xsl</code> aus dem Framework verarbeitet die Definition in 
    <code>editor-document.xml</code> und erzeugt daraus eine HTML-Tabelle mit den entsprechenden Beschriftungen und 
    Formularfeldern für die Eingabe der Metadaten. Es lassen sich jedoch nicht nur neue Daten eingeben, auch 
    existierende Metadatenobjekte können bearbeitet werden. Das Stylesheet kann dazu von einer beliebigen URL ein 
    XML-Dokument einlesen, verarbeitet dieses dann entsprechend den Abbildungsregeln aus <code>editor-person.xsl</code> 
    und füllt die Eingabefelder des Formulars mit den Inhalten der XML-Elemente und –Attribute.
    </p>
    <p>
    Wenn der Benutzer im Browser die Eingaben in die Formularfelder getätigt hat und das Formular abschickt, werden die 
    Eingaben durch das Servlet <code>MCREditorServlet</code> aus dem Framework verarbeitet. Das Servlet generiert aus 
    den Eingaben ein XML-Dokument, entsprechend den Regeln aus <code>editor-document.xml</code>. Dieses XML-Dokument 
    wird anschließend an ein beliebiges anderes Servlet weitergereicht, welches in der Formulardefinition angegeben ist 
    und welches dann die Daten endgültig verarbeiten kann und z.B. das XML-Dokument als MyCoRe Metadaten-Objekt 
    speichert. 
    </p>
    <p>
    <code>MCREditorServlet</code> übergibt dabei dem Ziel-Servlet (z.B. <code>AnyTargetServlet</code>) ein Objekt vom 
    Typ <code>MCREditorSubmission</code>, das nicht nur das XML-Dokument, sondern auch eventuell gemeinsam mit den 
    Formulardaten übertragene Dateien als InputStream enthält. Damit ist es möglich, auch einfache Datei-Upload-Formulare 
    über das Editor Framework zu realisieren. 
    </p>
    <p>
    Das Ziel-Servlet erhält zusätzlich auch die ursprünglichen HTTP Request Parameter aus dem abgeschickten Formular, so 
    dass es bei Bedarf auch direkt auf die Werte bestimmter Eingabefelder zugreifen kann und nicht zwingend unbedingt 
    das resultierende XML-Dokument beachten muss. Dadurch ist es möglich, das Editor Framework auch mit bereits 
    existierenden Servlets zu nutzen, die bisher keine XML-Dokumente als Eingabe verarbeiten. Das Framework ist daher 
    auch in der Lage, die Eingaben an eine beliebige URL statt an ein Servlet zu senden, so dass das Ziel der Eingaben 
    an sich auch ein externes CGI-Skript oder ein Servlet in einem entfernten System sein könnte. Das schafft ein hohes 
    Maß an Flexibilität, durch das das Editor Framework auch genutzt werden kann, um z.B. Suchmasken oder 
    Login-Formulare zu erzeugen. Die Nutzung ist nicht allein auf die Realisierung von Metadaten-Editoren beschränkt.
    </p>
   </section>
   
   <section>
    <title>Beschreibung der Editor-Formular-Definition</title>
    <p class="fett">Die Grundstruktur</p>
    <p>
    Im Folgenden soll die Gestaltung eines Editor-Formulars näher beschrieben werden. Als Beispiel ist ein Formular für 
    ein Dokument gedacht. Die Daten werden z.B. in der Datei <code>editor-document.xml</code> gespeichert.
    </p>
    
    <img src="images/xml_rahmen.png" alt="Editor Rahmen" title="Editor Rahmen"/>
    <p class="klein"><strong>Abbildung 2.11:</strong> Rahmen der Formular-Definition</p>
    
    <p>
    Als nächstes definieren wir die Eingabefelder des Editors. Ein Editor besteht aus verschiedenen Komponenten, die 
    innerhalb des Elements <code>components</code> deklariert werden. Dies können einfache Komponenten z.B. für 
    Auswahllisten und Texteingabefelder sein, oder aber zusammengesetzte Panels, mit deren Hilfe man einfache 
    Komponenten in einer Tabellengitterstruktur anordnen kann. Panels können wiederum andere Panels beinhalten, so dass 
    sich komplexere Layouts erzeugen lassen. Jede Komponente besitzt eine innerhalb des Editors eindeutige ID, über die 
    sie referenziert werden kann. Jeder Editor besitzt ein Root-Panel, die äußerste Struktur, mit der die Anordnung der 
    Komponenten begonnen wird. Die ID dieses Root-Panels wird als Attribut im Element <code>components</code> angegeben.
    </p>
    
    <img src="images/root_panel.png" alt="Root-Panel" title="Root-Panel"/>
    <p class="klein"><strong>Abbildung 2.12:</strong> Definition eines einfachen Formulares</p>
    
    <p>
    Innerhalb eines Panels lassen sich andere Komponenten oder Panels anordnen. Solche Komponenten werden im einfachsten 
    Fall einfach in die Gitterzellen eines Panels eingebettet. Jede Zelle entspricht einem <code>cell</code>-Element 
    innerhalb des Panels. Jede Zelle besitzt eine <code>row</code>- und <code>col</code>-Koordinate, mit deren Hilfe 
    die Zelleninhalte von links nach rechts in Spalten (<code>col</code>) und von oben nach unten in Zeilen 
    (<code>row</code>) angeordnet werden. Dabei ist für Textfelder noch die Angabe der Sprache möglich.
    </p>
    <p>
    Innerhalb der Gitterzellen füllen die Komponenten in der Regel nicht den gesamten Platz aus, daher können sie in 
    ihren Zellen mittels des <code>anchor</code>-Attributs anhand der Himmelsrichtungen (<code>NORTH</code>, 
    <code>NORTHEAST</code>, <code>EAST</code>, ... bis <code>CENTER</code>) angeordnet werden. Wir ordnen die 
    Beschriftungen rechtsbündig, die Texteingabefelder linksbündig an. Außerdem wird nun in der untersten rechten Zelle
     rechtsbündig ein "Speichern" Button zum Absenden des Formulars ergänzt.
     </p>
     
     <img src="images/root_panel2.png" alt="Root-Panel-Auslagerung" title="Root-Panel-Auslagerung"/>
     <p class="klein"><strong>Abbildung 2.14:</strong> Auslagern von Definitionen aus dem Root-Panel</p>
     
     <p>
     Im nächsten Schritt soll nun die Definition aus dem Root-Panel ausgegliedert werden. Sie verwenden dazu ein eigenes 
     Panel. Diese Technik wird verwendet, um Panels mehrfach zu nutzen und den Quellcode des Formulars zu strukturieren. 
     Dabei wird gezeigt, wie sich Panels untereinander aufrufen (Abbildung 2.14).
     </p>
     <p>
     Soll das Panel <code>form</code> nun mehrfach genutzt werden,z.B. in mehreren Formularen, so ist es sinnvoll das 
     Panel in eine gemeinsame Definitionsdatei <code>imports-common.xml</code> auszulagern. Im eigentlichen Formular 
     wird dann nur noch auf das <code>form</code>-Panel verwiesen. Die Einbindung der ausgelagerten Panels erfolgt mit 
     der <code>include</code>-Anweisung (Abbildung 2.15). Die einzufügende Datei (Abbildung 2.16) wird nun im System 
     mittels <code>EntityResolver</code> gesucht und eingebunden. Auf diese Weise lassen sich elegante und wartungsarme 
     Formulare gestalten.
     </p>
     
     <img src="images/imports_formular.png" alt="Editor-Auslagerung" title="Editor-Auslagerung"/>
     <p class="klein"><strong>Abbildung 2.15:</strong> Auslagern von Definitionen aus dem Editor-Formular</p>
          
     <img src="images/imports.png" alt="imports" title="imports"/>
     <p class="klein"><strong>Abbildung 2.16:</strong> Die imports-Formular-Definition</p>
     
     <p class="fett">Abbildung zwischen Eingabefeldern und XML-Strukturen</p>
     <p>
     Als nächstes definieren wir, wie die Eingabefelder auf XML-Elemente abgebildet werden. Dies geschieht über das 
     Attribut <code>var</code> verschiedener Elemente der Editor-Definition. Zunächst wird im <code>var</code>-Attribut 
     des <code>components</code>-Elements der Name des Root-Elements der XML-Darstellung (document) festgelegt. Die 
     Abbildung zwischen Eingabefeldern oder Panels und ihrer Zuordnung zu XML-Elementen geschieht über das 
     <code>var</code>&gt;-Attribut in den <code>cell</code>-Elementen, welche die Eingabekomponente enthalten (Abbildung 217).
     </p>
     
     <img src="images/xml_main_tag.png" alt="XML-Main-Tag-Namen" title="XML-Main-Tag-Namen"/>
     <p class="klein"><strong>Abbildung 2.17:</strong> Einfügen des XML-Main-Tag-Namen</p>
     
     <p>
     Es gibt für Tags und Attribute innerhalb der Root-Komponente verschiedene Möglichkeiten der Gestaltung des 
     Ausgabe-XML-Baumes. Die einfachste Art ist die direkte Zuordnung. Hier werden die Werte des Eingangs-XML-Files dem 
     Feld in der Editormaske zugeordnet. Weiterhin kann dem Feld noch ein Standardwert durch das Attribut <code>default</code> 
     mitgegeben werden. Zudem können Felder, welche von der Dateneingabe ausgenommen werden sollen, deren Inhalte aber 
     an die Ausgabeseite durchgereicht werden sollen, als <code>hidden</code>-Felder mitgeführt werden. Auch hier können 
     Standardwerte angegeben werden, welche eingesetzt werden, wenn keine Daten für das Tag/Attribut vorhanden sind.
     </p>
     
      <img src="images/xml_integration.png" alt="XML-Tag Integration" title="XML-Tag Integration"/>
      <p class="klein"><strong>Abbildung 2.18:</strong> Integration von einfachen XML-Tags</p>
     
     <p>
     Sollten Sie mehrere gleiche XML-Strukturen im Editor zur Bearbeitung anbieten wollen, so wird dies über eine 
     Integer-Zahl in Klammer organisiert. Achtung, es werden immer nur soviel XML-Elemente übernommen und an die Ausgabe 
     weitergereicht, wie angegeben sind. Um eine beliebige Anzahl zu präsentieren und zu bearbeiten nutzen sie die 
     weiter unten angegebene Möglichkeit des Repeaters. Für <code>hidden</code>-Felder gibt es noch die Variante, 
     mittels des <code>descendants="true"</code> - Attributs alle Kindelemente, Attribute und Wiederholungen des 
     Elementes an die Ausgabe durchzureichen.
     </p>
     
     <img src="images/xml_integration_mehrfach.png" alt="XML-Tag Integration" title="XML-Tag Integration"/>
     <p class="klein"><strong>Abbildung 2.19:</strong> Integration von mehrfachen XML-Tags</p>

     <p>
     Wenn das zu bearbeitende Quell-XML-Dokument oder das Zieldokument Namespaces verwendet, 
     können die Werte der var-Attribute auch Namespace-Prefixes enthalten. 
     Dazu müssen sämtliche Namespaces in der Editor-Definition im Element <code>components</code> 
     als zusätzliche Namespaces mit ihrem Prefix registriert werden. Wird in einem var-Attribut ein
     Namespace-Prefix verwendet, das hier nicht deklariert ist, oder erfolgt die Deklaration an
     einer anderen Stelle, führt dies zu einem Verarbeitungsfehler! Ein Beispiel: 
     </p>
     
     <source xml:space="preserve"><![CDATA[
     
       <components root="/mycoreobject" xmlns:xlink="http://www.w3.org/1999/xlink">
         ...
         <cell row="1" col="1" var="@xlink:href">
           ...
         </cell>
         ...
       </components>
     ]]><![CDATA[
     ]]></source>
     
     <p class="fett">Integration und Aufruf des Editor Framework</p>
     <p>
     Bereits am Anfang des Kapitels wurde eine einfache Syntax zum Aufruf des Editor Framework vorgestellt. Dieser 
     Abschnittinformiert umfassend zu diesem Thema. 
     </p>
     
     <img src="images/editor_einbinden.png" alt="Editor einbinden" title="Editor einbinden"/>
     <p class="klein"><strong>Abbildung 2.20:</strong> Einbindung des Editors in eine Webseite</p>
          
     <p>
     Das Editor Framework ist so konzipiert, dass es als XML-Sequenz in einer durch das <code>MCRLayoutServlet</code> 
     darzustellenden Webseite integriert werden kann. D.h. Sie erstellen eine XML Seite, welche durch das Servlet und 
     die zugehörigen XSLT-Stylesheets nach HTML konvertiert wird. Durch den Import (<code>include</code>) der 
     Editor-Framework-XSL-Dateien in das Layout zum Erzeugen der HTML-Seiten ermöglichen Sie die Einbindung ihrer 
     Editor-Formulare. In der oben gezeigten XML-Sequenz wird jedoch nur die Definitionsdatei des Formulars 
     beschrieben: „nimm aus der Web-Applikation die Datei editor-document.xml aus dem Verzeichnis editor“. Dabei ist 
     noch nichts über die Datenquelle bekannt. Hierfür existieren noch einige Parameter, welche durch das Framework 
     ausgewertet werden. Diese können sowohl direkt im Browser in der Aufrufsequenz oder über Parametereinstellungen 
     in einem Servlet mitgegeben werden.
     </p>
     
     <p class="kasten"><code>http://.../document.xml?XSL.editor.source.new=true&amp;type=...</code></p>
     <p>Oder in einem Servlet als Codestück, wie Abbildung 2.21 zeigt.</p>
     
     <img src="images/codesequenz.png" alt="Codesequenz" title="Codesequenz"/>
     <p class="klein"><strong>Abbildung 2.21:</strong> Codesequenz zum Aufruf des Editor Framework</p>
      
     <table><tr><th colspan="1" rowspan="1">Start-Parameter für das Lesen der zu bearbeitenden XML-Quelle:</th></tr></table>
     <p>
     Über XSL-Parameter kann beim Aufruf des Editors gesteuert werden, ob bzw. aus welcher Quelle die zu bearbeitenden 
     XML-Daten gelesen werden. Die zu bearbeitenden XML-Daten werden von einer URL gelesen. Falls die URL mit 
     <code>http://</code> oder <code>https://</code> beginnt, wird sie als absolute URL direkt verwendet, andernfalls 
     wird die URL als relativ zur <code>WebApplicationBaseURL</code> (context root), dem Startpunkt der 
     WebApplication,interpretiert. Es gibt die folgenden vier Optionen:
     </p>
     <ol>
     <li><code>XSL.editor.source.new=true</code><br/>
     Es wird das Formular mit leeren Datenfeldern gestartet.</li>
     <li>Statische URL eines XML-Dokumentes (z.B. eines Metadaten-Templates), die in der Editor-Definition als 
     Top-Level-Element angegeben ist (d.h. auf gleicher Ebene wie die target-Deklaration), z.B.<br/>
     <code>&lt;source url="templates/document.xml" /&gt;</code></li>
     <li>URL, die durch ein Servlet oder Stylesheet zur Laufzeit gebildet wird, und die beim Aufruf des Editors über 
     einen XSL Parameter übergeben wird:<br/><code>XSL.editor.source.url=templates/document.xml</code></li>
     <li>URL, die aus einer Kombination einer statischen URL und eines ID-Tokens gebildet wird, das beim Aufruf des 
     Editors über einen XSL Parameter übergeben wird. Im folgenden Beispiel wird zur Laufzeit das Token XXX durch den 
     Parameterwert 4711 ersetzt:<br/>
     <code>XSL.editor.source.id=4711</code><br/>
     <code>&lt;source url="servlets/SomeServlet?id=XXX" token="XXX" /&gt;</code></li>
     </ol>
     
     <table><tr><th colspan="1" rowspan="1">Start-Parameter für die Definition des Abbrechen-Buttons:</th></tr></table>
     <p>
     <code>XSL.editor.cancel.url/XSL.editor.cancel.id</code><br/>
     Diese Parameter werden im Abschnitt zur Verwendung eines Cancel-Buttons (Abbrechen-Knopf) erläutert, sie steuern 
     die URL, zu der bei Klick auf einen „Abbrechen“ Button zurückgekehrt wird.
     </p>
     <table><tr><th colspan="1" rowspan="1">Start-Parameter für die Weitergabe an das Zielservlet:</th></tr></table>
     <p>
     In der Regel werden die Eingaben nach der Bearbeitung mit dem Editor an ein Zielservlet gesendet 
     (<code>target type="servlet"</code>). Man kann diesem Zielservlet auch HTTP Parameter mitschicken, die der Editor 
     bei Abschicken des Formulars mitsendet. So können Informationen an das Zielservlet weitergegeben werden, die nicht 
     Teil des zu bearbeitenden XML-Dokumentes sind, z.B. die Information, ob es sich um einen Update- oder Create-Vorgang 
     handelt, die Objekt-ID etc. Der Editor reicht automatisch alle HTTP Request Parameter an das Zielservlet durch, 
     deren Name nicht mit XSL beginnt. 
     </p>
     <p class="break">
     Beispiel:<code>http://.../editor-document.xml?XSL.editor.source.id=4711&amp;</code> <br/>
     <code>action=update&amp;mode=bingoBongo</code>
     </p>
     <table><tr><th colspan="1" rowspan="1">Ausgabeziele</th></tr></table>
     <p>
     Das Editor-Framework ist auch hinsichtlich der Verarbeitung der entstandenen Daten flexibel konfigurierbar. 
     Wie bereits erwähnt, wird nach dem Betätigen des Submit-Buttons das <code>MCREditorServlet</code> für eine erste 
     Verarbeitung angestoßen. Diese reicht die Daten dann an ein weiteres konfigurierbares Ziel weiter. Welches das ist, 
     wird mit der target-Zeile in der Formulardefinition festgelegt. Das Attribut <code>method</code> definiert, ob dazu 
     <code>HTTP</code> <code>GET</code> oder <code>POST</code> verwendet wird. Zu empfehlen ist in der Regel immer 
     <code>POST</code>, was auch der Default-Wert ist und zwingend bei File Uploads gesetzt wird. Möglich ist:
     </p>
     <ul>
     <li>die Ausgabe als HTML-Seite zum Debugging des Ergebnisses:<br/>
     <code>&lt;target type="debug" method="post" format="xml" /&gt;</code>,</li>
     <li>die Weiterleitung der Daten in ein nachgeschaltetes Servlet im XML-Format:<br/>
     <code>&lt;target type="servlet" method="post" name="MCRCheckDataServlet" format="xml" /&gt;</code>,</li>
     <li>die Weiterleitung der Daten an ein nachgeschaltetes Servlet in der Form <code>name=value</code>, d. h. ohne 
     Generierung eines XML-Dokumentes:<br/>
     <code>&lt;target type="servlet" method="post" name="MCRCheckDataServlet" format="name=value" /&gt;</code>,</li>
     <li>die Weiterleitung an das LayoutServlet zur Anzeige des generierten XML-Dokumentes als Test:<br/>
     <code>&lt;target type="display" method="post" format="xml" /&gt;</code>.<br/>
     <br/>
     
     <img src="images/target_type.png" alt="Target" title="Target"/>
     <p class="klein"><strong>Abbildung 2.22:</strong> Rahmen der Formular-Definition</p><br/>
     
     </li>
     <li>die Weiterleitung an eine beliebige URL als HTTP GET oder POST Request:<br/>
     <code>&lt;target type="url" method="post" format="name=value" url="cgi-bin/ProcessMe.cgi" /&gt;</code> oder</li>
     <li>die Weiterleitung an einen anderen Editor, für den dieser Editor als „Subdialog“ fungiert. Dies wird in einem 
     separaten Abschnitt erläutert.<br/>
     <code>&lt;target type="subselect" method="post" format="xml" /&gt;</code>
     </li>
     </ul>
     <p>
     Mit der nachfolgenden Java-Code-Sequenz kann nun auf die vom MCREditorServlet durchgereichten XML- und -File-Daten 
     zugegriffen werden.
     </p>
     
     <img src="images/java_code.png" alt="Java" title="Java"/>
     <p class="klein"><strong>Abbildung 2.23:</strong> Java-Code-Sequenz für den Zugriff</p><br/>
          
     <p>
     Neben der Übernahme der Ausgabewerte des <code>MCREditorServlets</code> als XML-Baum können diese auch in der 
     Form '<code>name=value</code>' durchgereicht werden. Hierzu müssen u. a. die <code>var</code>-Attribute 
     entsprechend in eine einfache Form gebracht werden. Der Ausschnitt der Editor-Definition soll das verdeutlichen.
     </p>
     
     <img src="images/editor_rahmen.png" alt="Rahmen Editor" title="Rahmen Editor"/>
     <p class="klein"><strong>Abbildung 2.24:</strong> Rahmen der Formular-Definition mit name=value</p>
               
    </section>
    
    <section>
     <title>Syntax der Formularelemente</title>
     <p class="fett">Aufbau einer Zelle</p>
     <p>
     Das <code>cell</code>-Element stellt ein elementares Gebilde innerhalb eines Formulargitters dar. Seine Position 
     wird durch die Attribute <code>col</code>, <code>row</code> und <code>anchor</code> beschrieben. <code>col</code> 
     gibt dabei die relative Spaltenzahl, <code>row</code> die relative Zeilenzahl an. Mit <code>anchor</code> kann die 
     Ausrichtung gesteuert werden. Mögliche Werte sind hier <code>NORTHWEST</code>, <code>NORTH</code>, 
     <code>NORTHEAST</code>, <code>WEST</code>, <code>CENTER</code>, <code>EAST</code>, <code>SOUTHWEST</code>, 
     <code>SOUTH</code> und <code>SOUTHEAST</code>. Mit dem Attribut <code>ref</code> kann auf ein mehrfach verwendbares 
     Element via ID referenziert werden. Über das Attribut <code>sortnr</code> kann die Reihenfolge der zu generierenden 
     XML-Daten für die Ausgabe geregelt werden. Dieses Attribut bezieht sich dabei auf das gesamte Formular.
     </p>
     
     <img src="images/cell_syntax.png" alt="Syntax" title="Syntax"/>
     <p class="klein"><strong>Abbildung 2.25:</strong> Syntax des cell-Elements</p>
     
     <p class="fett">Texteingabefelder</p>
     <p>
     Ein einzeiliges Texteingabefeld wird mittels eines Elementes <code>textfield</code> erzeugt, ein mehrzeiliges 
     mittels eines Elementes <code>textarea</code>. Das Attribut <code>width</code> gibt die Breite des 
     Texteingabefeldes in Anzahl Zeichen an. Das Attribute <code>height</code> gibt für mehrzeilige Texteingabefelder 
     die Anzahl Zeilen an. Das Attribut <code>maxlenght</code> gibt bei textfield-Elementen die maximale Länge der 
     Eingabe an.
     </p>
     <p>
     Texteingabefelder können einen Vorgabewert enthalten, der wahlweise über ein Attribut oder ein Kindelement mit dem 
     Namen <code>default</code> angegeben wird. Die Verwendung eines default-Elementes statt eines default-Attributes 
     ist sinnvoll, wenn mehrzeilige default-Werte angegeben werden sollen.
     </p>
     
     <img src="images/textfield_syntax.png" alt="Syntax" title="Syntax"/>
     <p class="klein"><strong>Abbildung 2.26:</strong> Syntax von textfield und textarea</p>
     
     <p>
     Alternativ kann auch ein AutoFill-Wert über das Attribut bzw. Element <code>autofill</code> angegeben werden. 
     Während <code>default</code>-Werte immer Teil der Eingabe werden, werden AutoFill-Werte nur dann als Eingabe 
     betrachtet, wenn der Nutzer sie ergänzt oder ändert. Unveränderte AutoFill-Werte werden also ignoriert. Für alle 
     Mitarbeiter der Universität sind z.B. Teile der Email-Adresse oder der Anschrift in den meisten Fällen identisch. 
     Falls der Nutzer diese Angaben im Eingabefeld ändert oder ergänzt, wird dies als Eingabe betrachtet. Ansonsten 
     wird der AutoFill-Wert ignoriert. Default-Werte dagegen werden immer als Eingabe betrachtet. Wichtig ist, dass 
     textfield- und textarea-Elemente ein innerhalb des Editors eindeutiges ID-Attribut besitzen.
     </p>
     
     <img src="images/autofill.png" alt="Autofill-Werte" title="Autofill-Werte"/>
     <p class="klein"><strong>Abbildung 2.27:</strong> AutoFill-Werte in textfield und textarea</p>
     
     <p class="fett">Passwort-Eingabefelder</p>
     <p>
     Passwort-Eingabefelder werden über das Element <code>password</code> erzeugt. Sie können keine default- oder 
     autofill-Werte besitzen. Bei der Eingabe werden Sternchen statt der eingegebenen Zeichen angezeigt. Das Attribut 
     <code>width</code> gibt die Breite des Eingabefeldes in Anzahl Zeichen an. Leider ist es bei allen Browsern so, 
     dass dieses Feld keine vorhandenen Inhalte bearbeiten kann, d. h. Passworte sind aus Sicherheitsgründen immer neu 
     einzugeben.
     </p>
     
     <img src="images/password.png" alt="Syntax password" title="Syntax password"/>
     <p class="klein"><strong>Abbildung 2.28:</strong> Syntax des password-Elements</p>     
     
     <p class="fett">Einfache Checkboxen</p>
     <p>
     Das Element <code>checkbox</code> generiert eine alleinstehende Checkbox, bei der über einen „Haken“ ein Wert 
     ein- oder ausgeschaltet werden kann. Das Attribut <code>value</code> gibt den Wert an, der gesetzt werden soll, 
     wenn die Checkbox markiert ist. Das Attribut <code>checked</code> gibt mit den möglichen Werten <code>true</code> 
     und <code>false</code> an, ob als default die Checkbox markiert sein soll oder nicht. Die Beschriftung der 
     Checkbox erfolgt über ein Attribut <code>label</code> bzw. über untergeordnete mehrsprachige label-Elemente, vgl. 
     dazu den Abschnitt zu Beschriftungen.
     </p>
     
     <img src="images/checkbox.png" alt="Syntax checkbox" title="Syntax checkbox"/>
     <p class="klein"><strong>Abbildung 2.29:</strong> Syntax für Checkboxen</p>     
     
     <p class="fett">Auswahllisten</p>
     <p>
     Auswahllisten werden über das Element <code>list</code> erzeugt. Die in der Liste darzustellenden Werte werden über 
     geschachtelte <code>item</code>-Elemente angegeben. Das Attribut <code>type</code> gibt an, in welchem Format die 
     Listenwerte dargestellt werden. Der Typ <code>dropdown</code> stellt die Listenwerte als einzeilige 
     Dropdown-Auswahlliste dar. Das Attribut <code>width</code> gibt dabei die Breite des Auswahlfeldes in CSS-Syntax an, 
     d.h. es sind Angaben in Anzahl Zeichen oder Pixeln etc. möglich. Der Typ <code>multirow</code> stellt die 
     Listenwerte als mehrzeiliges Auswahlfeld dar. Das Attribut <code>rows</code> gibt dabei die Anzahl Zeilen an, die 
     maximal zu sehen sind. Enthält die Liste mehr Werte als Zeilen, werden Scrollbalken dargestellt. Das Attribut 
     <code>multiple</code> mit den möglichen Werten <code>true</code> und <code>false</code> gibt an, ob eine 
     Mehrfachauswahl möglich ist. Das Attribut <code>default</code> gibt ggf. eine Vorauswahl vor.
     </p>
     
     <img src="images/auswahlliste.png" alt="Syntax Auswahlliste" title="Syntax Auswahlliste"/>
     <p class="klein"><strong>Abbildung 2.30:</strong> Syntax einer Auswahlliste</p>     
     
     <p>
     Die in einer Liste dargestellten Werte werden über <code>item</code>-Elemente angegeben. Diese können auch 
     mehrstufig geschachtelt sein, um eine hierarchische Struktur darzustellen (d.h. item-Elemente können wiederum 
     item-Elemente enthalten). Eine Schachtelung ist nur für die Listentypen <code>dropdown</code> und 
     <code>multirow</code> erlaubt und sinnvoll. Die Hierarchie wird dabei automatisch durch Einrückungen dargestellt. 
     Die Beschriftung der item-Elemente wird über geschachtelte label-Attribute oder Elemente definiert und kann 
     mehrsprachig angegeben werden, vgl. dazu den folgenden Abschnitt zu Beschriftungen. Die Verwendung von 
     <code>&lt;list type="multirow" multiple="true"&gt;</code>, d.h. mehrzeiligen Auswahllisten mit Mehrfachauswahl ist 
     nur sinnvoll, wenn das aktuelle var-Attribut der Zelle auf ein Element verweist, denn Attribute sind ja 
     grundsätzlich in XML nicht wiederholbar.
     </p>
     
     <img src="images/mehrfachauswahl.png" alt="Mehrfachauswahl" title="Mehrfachauswahl"/>
     <p class="klein"><strong>Abbildung 2.31:</strong> Beispiel für Mehrfachauswahl</p>
     
     <p>
     Das Beispiel erzeugt eine dreizeilige Mehrfachauswahlliste, die ggf. in mehrfach generierte XML-Elemente 
     „Programmiersprache“ resultiert.
     </p>
     
     <p class="fett">Radio-Buttons und Checkbox-Listen</p>
     <p>
     Der Typ <code>radio</code> stellt die Listenwerte als eine Menge von Radiobuttons dar, es kann also nur ein Wert 
     ausgewählt werden. Der Typ <code>checkbox</code> stellt die Listenwerte als eine Menge von Checkboxes dar, in 
     diesem Fall können mehrere Werte ausgewählt sein. Bei diesen beiden Typen werden alle Werte der Liste nacheinander 
     in einer Tabellenstruktur mit einer gewissen Anzahl an Zeilen und Spalten ausgegeben. Es kann entweder die Anzahl 
     an Zeilen (Attribut <code>rows</code>) oder die Anzahl an Spalten (Attribut <code>cols</code>) dieser Tabelle 
     angegeben werden. Der jeweils nicht angegebene Wert folgt automatisch aus der Anzahl der Werte in der Liste. 
     Der Spezialfall <code>rows="1"</code> entspricht also einer Anordnung aller Listenwerte von links nach rechts in 
     einer Zeile, der Fall <code>cols="1"</code> entspricht einer Anordnung von oben nach unten in nur einer Spalte.
     </p>
     
     <img src="images/radio_button.png" alt="Radio-Button" title="Radio-Button"/>
     <p class="klein"><strong>Abbildung 2.32:</strong> Syntax von Radio-Button und Checkbox-Listen</p>
     
     <p>
     Analog zu multirow/multiple Listen ist die Verwendung von Checkbox-Listen nur sinnvoll für die Abbildung auf 
     XML-Elemente, da XML-Attribute nicht wiederholbar sind (vgl. vorangehenden Abschnitt).
     </p>
     <p class="fett">Beschriftungen</p>
     <p class="P50">Beschriftungen von Eingabefeldern lassen sich mit den Elementen <code>text</code> und 
     <code>label</code> definieren. Das Element <code>text</code> erzeugt eine frei platzierbare Beschriftung etwa für 
     eine Texteingabefeld. Beschriftungen dürfen auch XHTML Fragmente enthalten, etwa um eine fette, kursive oder 
     mehrzeilige Darstellung zu erreichen. Mehrsprachige Beschriftungen von Elementen können über mehrere 
     <code>label</code>-Elemente realisierte werden, wobei das Attribut <code>xml:lang</code> die Sprache angibt.
     </p>
     <p>
     Die aktive Sprache wird wie bei anderen MyCoRe-Stylesheets über den <code>XSL.Lang</code> Parameter definiert. 
     Wenn ein <code>label</code> existiert, bei dem <code>xml:lang</code> der aktiven Sprache entspricht, wird dieses 
     ausgegeben. Ist dies nicht der Fall, wird als erster Rückfallschritt das <code>label</code> der Default-Sprache 
     (Parameter <code>XSL.DefaultLang</code>) ausgegeben. Existiert auch dies nicht, wird das Label ausgegeben, das 
     im <code>label</code>-Attribut oder im ersten <code>label</code>-Element enthalten ist, das kein 
     <code>xml:lang</code>-Attribut enthält. In alles anderen Fällen wird das erste <code>label</code>-Element 
     verwendet, das überhaupt existiert.
     </p>
     
     <img src="images/textfeld.png" alt="Syntax Textfeld" title="Syntax Textfeld"/>
     <p class="klein"><strong>Abbildung 2.33:</strong> Syntax eines Textfeldes</p>
     
     <p class="fett">Internationalisierung</p>
     <p>
     Das Editor-Framework verfügt über mehrere Möglichkeiten der Mehrsprachigkeit einzelner Auswahl- oder Textfelder. 
     Bis MyCoRe-Version 1.2 war hier nur der Einsatz von <code>&lt;label xml:lang="..."&gt;</code>-Tags 
     (wie oben beschrieben) möglich. Mit Version 1.3 ist die direkte Nutzung von I18N 
     (<a title="" target="_blank" href="http://www.debian.org/doc/manuals/intro-i18n/">http://www.debian.org/doc/manuals/intro-i18n/</a>) 
     möglich. Um eine Abwärts-Kompatibilität zu erreichen sind die <code>&lt;label&gt;</code>-Tags auch weiterhin im 
     Framework gültig. Es ist aber zu empfehlen, langfristig ältere MyCoRe-Anwendungen entsprechend umzustellen. damit 
     wird eine strikte Trennung von Layout und sprachabhängigem Text erreicht.
     </p>
     <p>
     Mit MyCoRe v1.3 wurde das <code>i18n</code>-Attribut in alle Editor-Framework-Stellen eingebaut, in den bisher 
     <code>&lt;label&gt;</code>-Tags vorgesehen waren. Entsprechend der I18N- Spezifikation sind alle Texte nun über 
     eine Property-Variable bekannt zu machen und in sprachabhängigen Dateien anzulegen. Diese tragen die Namen 
     <code>messages_{lang}.properties</code> und sind bei MyCoRe im <code>config</code>-Verzeichnis untergebracht. 
     Sollte das System für die angegebene Sprache keine solche Datei finden, so wird als Fallback die Datei 
     <code>messages.properties</code>&gt; gesucht. Sind beide Angaben vorhanden, hat das <code>i18n</code>-Attribut Vorrang. 
     Die nachfolgende Abbildung verdeutlicht die neue Funktion.
     </p>
     
     <img src="images/beschriftung_i18n.png" alt="I18N" title="I18N"/>
     <p class="klein"><strong>Abbildung 2.34:</strong> Beschriftung mit I18N</p>
     
     <p class="fett">Abstandshalter</p>
     <p>
     Ein Abstandshalter erzeugt leeren Raum als Platzhalter zwischen Elementen. Die Attribute <code>width</code> 
     und <code>height</code> geben Breite und Höhe des Abstandes in CSS-Syntax, etwa in Anzahl Pixeln, an.
     </p>
     
     <img src="images/space.png" alt="Abstand" title="Abstand"/>
     <p class="klein"><strong>Abbildung 2.35:</strong> Syntax eines Abstandhalters</p>
     
     <p class="fett">Externes Popup-Fenster</p>
     <p>
     Ein externes Popup-Fenster kann z.B. ein Hilfetext zu einem Eingabefeld im HTML-Format enthalten. Es können aber 
     auch beliebige andere Informationen und Funktionalitäten wie Eingabehilfen dargestellt werden. Der Startpunkt ist 
     ein Button im Formular, der mit einer frei wählbaren Beschriftung versehen werden kann. Standardmäßig wird er als 
     [?] Button im Formular dargestellt. Bei Anklicken des Buttons erscheint das codierte HTML in einem Popup-Fenster. 
     Die Attribute <code>width</code> und <code>height</code> steuern die Breite und Höhe dieses Fensters. Das Attribut 
     <code>css</code> gestattet die Verwendung eines externen CSS-Files. Wichtig ist, dass jedes <code>helpPopup</code> 
     Element eine eindeutige ID besitzt. Optional kann das Popup-Fenster auch von einer externen URL geladen werden. 
     Falls die URL mit „<code>http://</code>“ oder „<code>https://</code>“ beginnt, wird sie als absolute URL direkt 
     verwendet, andernfalls wird die URL als relativ zur <code>WebApplicationBaseURL</code> (<code>context root</code>), 
     dem Startpunkt der WebApplication, interpretiert.</p>
     <p>
     Innerhalb des helpPopup-Tags gibt es mehrere Tags, welche das Aussehen und den Inhalt des Aufruf-Buttons und des 
     Popup-Fensters bestimmen. Jedes Tag verfügt über das xml:lang-Attribut. Somit kann jedes Tag für die im Projekt 
     benötigten Sprachen implementiert werden. Zusätzlich gibt es das Konstrukt <code>xml:lang="all"</code>, das 
     anzeigt, dass das entsprechende Tag immer unabhängig von der Spracheinstellung des Systems präsentiert werden soll.
     </p>
     <p>Im Einzelnen sind die Tags wie folgend definiert:</p>
     <ul>
     <li><code>button</code> gibt die Zeichenkette an, welche der Start-Button haben soll,</li>
     <li><code>title</code> gibt den Titel des Popup-Fensters an,</li><li><code>close</code> gibt den Text zum 
     Schließen des Popup-Fensters an,</li>
     <li><code>label</code> beinhaltet den eigentlichen darzustellenden HTML-Code oder Text.</li>
     </ul>
     
     <img src="images/popup.png" alt="Popup-Fenster" title="Popup-Fenster"/>
     <p class="klein"><strong>Abbildung 2.36:</strong> Syntax eines Popup-Fensters</p>
     
     <p class="fett">Buttons</p>
     <p>
     Über das Element <code>button</code> wird ein Knopf erzeugt, der bei Anklicken zu einer externen URL wechselt. 
     Das Attibut <code>width</code> legt die Breite des Knopfes fest, das Attribut <code>label</code> oder ggf. 
     mehrsprachige enthaltene label-Elemente legen die Beschriftung des Knopfes fest. Falls die URL mit 
     „<code>http://</code>“ oder „<code>https://</code>“ beginnt, wird sie als absolute URL direkt verwendet, 
     andernfalls wird die URL als relativ zur <code>WebApplicationBaseURL</code> (<code>context root</code>), dem 
     Startpunkt der WebApplication, interpretiert.
     </p>
     
     <img src="images/button.png" alt="Syntax Button" title="Syntax Button"/>
     <p class="klein"><strong>Abbildung 2.37:</strong> Syntax eines einfachen Buttons</p>
     
     <p class="fett">SubmitButton</p>
     <p>
     Über das Element <code>submitButton</code> wird ein Knopf erzeugt, der beim Anklicken die Eingaben an das in der 
     Konfiguration angegebene Ziel sendet. Das Attribut <code>width</code> legt die Breite des Knopfes fest, das 
     Attribut <code>label</code> oder ggf. mehrsprachige enthaltene label-Elemente legen die Beschriftung des Knopfes 
     fest.
     </p>
     
     <img src="images/submit.png" alt="Syntax Submit-Button" title="Syntax Submit-Button"/>
     <p class="klein"><strong>Abbildung 2.38:</strong> Syntax des Submit-Buttons</p>
     
     <p class="fett">CancelButton</p>
     <p>
     Über das Element <code>cancelButton</code> wird ein Knopf erzeugt, der bei Anklicken die Bearbeitung des Formulars 
     abbricht. Das Attibut <code>width</code> legt die Breite des Knopfes fest, das Attribut <code>label</code> oder 
     ggf. mehrsprachige enthaltene label-Elemente legen die Beschriftung des Knopfes fest.
     </p>
     
     <img src="images/cancel.png" alt="Syntax Cancel-Button" title="Syntax Cancel-Button"/>
     <p class="klein"><strong>Abbildung 2.39:</strong> Syntax des Cancel-Buttons</p>
     
     <p>
     Die Ziel-URL des Buttons kann auf drei verschiedene Weisen gebildet werden. Falls die URL mit 
     „<code>http://</code>“ oder „<code>https://</code>“ beginnt, wird sie als absolute URL direkt verwendet, 
     andernfalls wird die URL als relativ zur <code>WebApplicationBaseURL</code> (<code>context root</code>), dem 
     Startpunkt der WebApplication, interpretiert.
     </p>
     <p>
     Statische URL, die in der Editor-Definition als Top-Level-Element angegeben ist (d.h. auf gleicher Ebene wie die 
     target-Deklaration), z.B.<br/>
     <code>&lt;cancel url="pages/goodbye.html" /&gt;</code>
     </p>
     <ol>
     <li>URL, die durch ein Servlet oder Stylesheet zur Laufzeit gebildet wird, und die beim Aufruf des Editors über 
     einen XSL-Parameter übergeben wird:<br/>
     <code>XSL.editor.cancel.url=pages/goodbye.html</code></li>
     <li>URL, die aus einer Kombination einer statischen URL und eines ID=Tokens gebildet wird, das beim Aufruf des 
     Editors über einen XSL Parameter übergeben wird. Im folgenden Beispiel wird zur Laufzeit das Token XXX durch den 
     Parameterwert 4711 ersetzt:<br/>
     <code>XSL.editor.cancel.id=4711</code><br/>
     <code>&lt;cancel url="servlets/SomeServlet?id=XXX" token="XXX" /&gt;</code></li>
     </ol>
     <p class="fett">Ausgabe von Werten aus dem Quelldokument</p>
     <p>
     Das Element <code>output</code> kann bei der Bearbeitung einer existierenden XML-Quelle verwendet werden, um den 
     Inhalt von Attributen oder Elementen im Formular als nicht bearbeitbaren Text auszugeben. Dabei ist zu beachten, 
     dass der ausgegebene Wert bei Abschicken des Formulars nicht weitergegeben wird. Hierfür muss ggf. ein 
     <code>hidden</code>-Element verwendet werden. Das Attribut <code>default</code> gibt den Wert an, der ggf. 
     ausgegeben wird, wenn das Dokument keinen Wert enthält.</p><p class="P50">Beispiel:
     </p>
     <p>
     <code>&lt;text&gt;&lt;label&gt;Dokument-ID:&lt;/label&gt;&lt;/text&gt;</code><br/>
     <code>&lt;output var="@id" default="(neu) /&gt;</code>
     </p>
     <p>
     gibt den Wert des Attributes <code>id</code> aus, sofern dieses im XML-Quelldokument existiert, ansonsten wird 
     „(neu)“ ausgegeben.
     </p>
     <p class="fett">Wiederholbare Elemente mit Repeatern erstellen</p>
     <p>
     Häufig sind einzelne Eingabefelder oder ganz Panels wiederholbar. Das Element <code>repeater</code> schachtelt auf 
     einfache Weise ein Eingabeelement oder ein ganzes Panel und macht dieses wiederholbar. Das var-Attribut der 
     umgebenden Zelle muss auf ein Element verweisen, da Attribute nicht wiederholbar sind. Das Attribut 
     <code>min</code> gibt an, wie oft minimal das wiederholte Element im Formular dargestellt wird, das Attribut 
     <code>max</code> gibt die Maximalzahl an Wiederholungen an. In jedem Fall wird das Element minimal so oft 
     dargestellt, wie es in der Eingabe auftritt.
     </p>
     <p>
     Das Beispiel wiederholt die Komponente mit der ID <code>pcreator</code>. Wiederholbare Elemente werden mit 
     +/- Buttons dargestellt, mit denen neue Eingabefelder hinzugefügt bzw. dargestellte gelöscht werden  können. Bei 
     mehr als einer aktuell dargestellten Wiederholung werden Pfeile angezeigt, mit deren Hilfe die Reihenfolge der 
     Elemente vertauscht werden kann.
     </p>
     
     <img src="images/repeater.png" alt="Repeater" title="Repeater"/>
     <p class="klein"><strong>Abbildung 2.40:</strong> Beispiel Repeator</p>
     
     <p class="fett">Der Framework-interne FileUpload</p>
     <p>
     Das Element <code>file</code> erlaubt es, eine einzelne Datei zusammen mit den Formulareingaben hochzuladen oder 
     eine auf dem Server vorhandene Datei zu löschen oder zu aktualisieren. Voraussetzung ist hierfür die vollständige 
     Integration des Upload-Services in den jeweiligen Java-Klassen. Das Attribut <code>maxlenght</code> gibt optional 
     die maximale Grösse der hochzuladenen Datei an. Der FileUpload über ein HTML-Formular ist nur für relativ kleine 
     Dateien mit wenigen MB zu empfehlen, andernfalls ist der in MyCoRe implementierte externe FileUpload zu nutzen. 
     Das Attribut <code>accept</code> gibt optional den akzeptierten MIME Typ an. Ob diese Angaben beachtet werden, ist 
     jedoch vom Browser abhängig und daher nicht verlässlich. Die Darstellung eines Datei-Upload Feldes hängt ebenfalls 
     sehr stark vom Browser ab und kann nicht über CSS gestaltet werden. In der Regel bestellt ein solches Feld aus einem 
     Texteingabefeld (dessen Breite in Anzahl Zeichen das <code>width</code>-Attribut angibt) und einem Button 
     „Durchsuchen“. Beschriftung und Layout dieser Elemente sind nicht steuerbar und fest vom Browser vorgegeben, CSS 
     Angaben funktionieren nicht zuverlässig. Über den Durchsuchen-Button kann eine Datei von der lokalen Festplatte 
     gewählt werden, alternativ kann der Dateipfad im Texteingabefeld eingegeben werden. Mit Abschicken des Formulars 
     wird der Dateiinhalt und der Dateiname an den Server übertragen, was unter Umständen lange dauern kann. 
     </p>
     
     <img src="images/fileupload.png" alt="FileUpload" title="FileUpload"/>
     <p class="klein"><strong>Abbildung 2.41:</strong> Syntax des FileUpload</p>
      
     <p>Zu beachten ist noch, dass für den FileUpload einige Property-Werte des Systems von Bedeutung sind.</p>
     <ul>
     <li>Dateien bis zu dieser Größe werden im Hauptspeicher des Servers gehalten:<br/> 
     <code>MCR.Editor.FileUpload.MemoryThreshold=1000000</code></li>
     <li>Dateien bis zu dieser Größe werden für HTTP Uploads akzeptiert:<br/>
     <code>MCR.Editor.FileUpload.MaxSize=5000000</code> </li>
     <li>Temporärer Speicherort für hochgeladene Dateien:<br/>
     <code>MCR.Editor.FileUpload.TempStoragePath=/tmp/upload</code>
     </li>
     </ul>
     <p>Das Auslesen der Dateien zur weiteren Verarbeitung kann z.B. wie folgt durchgeführt werden.</p>
     
     <img src="images/java_fileupload.png" alt="FileUpload" title="FileUpload"/>
     <p class="klein"><strong>Abbildung 2.42:</strong> Abbildung 42: Java-Code zum Lesen des FileUpload</p>
     
     <p>
     Weitere Hinweise zum Auslesen der hochgeladenen Dateien finden Sie in der JavaDoc-Dokumentation der Klassen 
     <code>org.mycore.frontend.editor2.MCREditorSubmission</code> und <code>MCREditorVariable</code> sowie in der 
     Online-Dokumentation des Apache File Upload Paketes (http://jakarta.apache.org/commons/fileupload/).
     </p>
     <p>
     Die Methode <code>MCREditorSubmission.listFiles()</code> liefert eine <code>java.util.List</code> von hochgeladenen 
     FileItem-Objekten. Die Apache-Klasse <code>FileItem</code> besitzt Methoden <code>getName()</code> und 
     <code>getInputStream()</code>, die den Dateinamen und den hochgeladenen Dateiinhalt liefern. Die Methode 
     <code>getFieldName()</code> liefert den Pfad im XML-Dokument, zu dem die hochgeladene Datei gehört.
     </p>
     <p>
     Alternativ kann auch über diesen Pfad auf eine bestimmte hochgeladene Datei direkt zugegriffen werden: Die 
     Eingaben aus dem Editor werden als JDOM-Dokument an das Zielservlet übergeben und stehen über 
     <code>MCREditorSubmission.getXML()</code> zur Verfügung. Mit JDOM-Operationen kann man nun zu dem JDOM-Element 
     oder -Attribut navigieren, für das ggf. eine Datei im Formular hochgeladen wurde. Die Methode 
     <code>MCREditorSubmission.getFile()</code>erwartet als Argument dieses JDOM-Objekt und liefert das dazu gehörende 
     FileItem.
     </p>
     <p class="P50">FileItem-Objekte sollten unmittelbar verarbeitet werden, da die Dateiinhalte nur temporär 
     gespeichert werden. Der hochgeladene Inhalt kann mittels <code>FileItem.write()</code> in ein persistentes 
     <code>java.io.File</code> kopiert werden oder in einem <code>MCRFile</code> gespeichert werden.
     </p>
     <p>
     Zu beachten ist, dass FileUploads nicht in Editoren verwendet werden sollten, die Repeater enthalten. Will man mehr 
     als eine Datei hochladen, sollte das file-Element „manuell“ mehrfach im Editor definiert werden, es darf jedoch 
     kein Repeater verwendet werden.
     </p>
     <p class="fett">Integration externer Datenquellen</p>
     <p>
     Das Editor-Framework gestattet die Einbindung externer Datenquellen in das Formular. Dies ermöglicht eine flexible 
     Gestaltung von Eingabewerten zur Laufzeit. Dabei werden Teile der Formulardefinition „on the fly“ erzeugt und im 
     Moment der Darstellung erst integriert.
     </p>
     <table><tr><th colspan="1" rowspan="1">Einfügen eines Request aus einem Servlet</th></tr></table>
     <p>Dieses Beispiel zeigt den Zugriff auf ein Servlet zur Laufzeit. Dabei werden die Ausgabedaten der 
     Servlet-Antwort vor der Integration in das Framework mittels XSLT in eine passende Form gebracht. Im Beispiel 
     wird eine MyCoRe-Klassifikation in eine Auswahlliste eingefügt.
     </p>
     
     <img src="images/servlet_request.png" alt="Servlet-Request" title="Servlet-Request"/>
     <p class="klein"><strong>Abbildung 2.43:</strong> Include Servlet-Request</p>
     
     <table><tr><th colspan="1" rowspan="1">Einfügen eines Definitionsabschnittes aus der Session</th></tr></table>
     <p>
     Es besteht auch die Möglichkeit, Daten dynamisch in der <code>MCRSession</code> zu hinterlegen und von dort in 
     die Gestaltung des Formulars zu integrieren. Im ersten Schritt wird in einer Java-Klasse ein JDOM-Element erzeugt, 
     welches dann im zweiten Schritt in das Formular eingebaut wird. Das Attribut <code>cacheable</code> spezifiziert 
     dabei, ob die Daten permanent vorgehalten werden sollen. Für ständig wechselnde Daten ist hier <code>false</code> 
     anzugeben.
     </p>
     
     <img src="images/java_code_session.png" alt="Java-Code" title="Java-Code"/>
     <p class="klein"><strong>Abbildung 2.44:</strong> Java-Code</p>
     
    </section>
    
    <section>
     <title>Eingabevalidierung</title>
     <p class="fett">Einführung</p>
     <p>
     Die Eingabefelder von Editor-Formularen können durch Integration von Validierungsregeln direkt durch das 
     Editor-Servlet geprüft werden, noch bevor die Eingaben an das weiterverarbeitende Zielservlet weitergegeben werden. 
     Wenn eine Eingabe fehlerhaft ist, wird das Formular noch einmal angezeigt. Es erscheint eine Fehlermeldung. 
     Eingabefelder mit fehlerhaften Eingaben werden im Formular optisch markiert. Zunächst ein einfaches Beispiel:
     </p>
     
     <img src="images/eingabevalidierung.png" alt="Eingabevalidierung" title="Eingabevalidierung"/>
     <p class="klein"><strong>Abbildung 2.45:</strong> Einfaches Beispiel für Eingabevalidierung</p>
     
     <p>
     Das Element <code>validationMessage</code> enthält die Meldung, die am Kopf des Formulars erscheint, wenn ein oder 
     mehrere Eingabefelder fehlerhaft ausgefüllt wurden. Dieses Element ist optional, es kann ein sprachunabhängiges 
     label-Attribut oder ein oder mehrere sprachabhängige label-Elemente enthalten.
     </p>

     <p>
     Jedes zu validierende Eingabefeld muss eine eindeutige ID besitzen. Neben Texteingabefeldern können auch alle 
     anderen Feldtypen wie z.B. Auswahllisten validiert werden. Nur hidden-Felder können momentan nicht validiert 
     werden.
     </p>
     <p>
     Das zu validierende Feld muss ein oder mehrere <code>condition-</code>Elemente enthalten, die wiederum eine 
     eindeutige ID besitzen müssen. Die Attribute dieser <code>condition</code>-Elemente enthalten die zu prüfenden 
     Validierungsregeln. Ein <code>condition</code>-Element kann ein sprachunabhängiges <code>label</code>-Attribut 
     oder ein oder mehrere sprachabhängige label-Elemente enthalten, die eine Meldung für den Benutzer enthalten. Bei 
     einer fehlerhaften Eingabe wird diese Meldung angezeigt, wenn der Benutzer mit der Maus über das Fehlersymbol 
     fährt, das neben dem Eingabefeld angezeigt wird.
     </p>
     
     <img src="images/validierung.png" alt="Fehlgeschlagene Eingabevalidierung" title="Fehlgeschlagene Eingabevalidierung"/>
     <p class="klein"><strong>Abbildung 2.46:</strong> Fehlgeschlagene Eingabevalidierung</p>
     
     <p>
     Ein Eingabefeld kann mehr als ein condition-Element enthalten. Dadurch können komplexe Validierungsregeln 
     schrittweise geprüft werden, und der Nutzer bekommt eine exaktere Rückmeldung, welche dieser Regeln verletzt wurde. 
     Wenn die Validierungsregeln auf mehrere condition-Elemente aufgeteilt wird, sollte die „required“ Regel ggf. die 
     erste sein.
     </p>
     
     <img src="images/conditions.png" alt="Regeln" title="Regeln"/>
     <p class="klein"><strong>Abbildung 2.47:</strong> Beispiel für eine Reihenfolge von Regeln</p>
     
     <p>Oder</p>
     
     <img src="images/condition.png" alt="Regeln in einer condition" title="Regeln in einer condition"/>
     <p class="klein"><strong>Abbildung 2.48:</strong> Beispiel für Regeln in einer <code>condition</code></p>
     
     <p class="fett">Validierungsregeln für einzelne Felder</p>
     <p>
     Die Validierungsregeln für Eingabefelder werden über Attribute oder Attributkombinationen des condition-Elements 
     definiert. Die folgenden Regeln können geprüft werden:
     </p>
     <table>
     <tr><th colspan="1" rowspan="1">required="true"</th></tr>
     <tr>
     <td colspan="1" rowspan="1">Es ist eine Eingabe erforderlich. Auch Eingaben, die nur aus Leerzeichen bestehen, werden abgewiesen. Ist diese 
     Regel verletzt, werden ggf. weitere vorhandene Regeln nicht mehr geprüft.</td>
     </tr>
     </table>
     <table>
     <tr><th colspan="1" rowspan="1">minLength="10"</th></tr>
     <tr><td colspan="1" rowspan="1">Die Eingabe muss aus minimal 10 Zeichen bestehen.</td></tr>
     </table>
     <table>
     <tr><th colspan="1" rowspan="1">maxLength="250"</th></tr>
     <tr><td colspan="1" rowspan="1">Die Eingabe darf aus maximal 250 Zeichen bestehen.</td></tr>
     </table>
     <table>
     <tr><th colspan="1" rowspan="1">type="integer" min="0" max="100"</th></tr>
     <tr><td colspan="1" rowspan="1">Die Eingabe muss eine ganze Zahl sein. Optional kann über die Attribute min und/oder max der Wertebereich 
     eingeschränkt werden.</td></tr>
     </table>
     <table>
     <tr><th colspan="1" rowspan="1">type="decimal" format="de" min="0" max="3,5"</th></tr>
     <tr><td colspan="1" rowspan="1">Die Eingabe muss eine Zahl (ggf. mit Nachkommastellen) sein. Optional kann über die Attribute min und/oder 
     max der Wertebereich eingeschränkt werden. Das Attribut format muss einen ISO 639 Sprachcode enthalten (z.B. „de“ 
     oder „en“), der bestimmt, wie Kommazahlen formatiert werden. Die min- und max-Werte müssen diesem Format 
     entsprechend angegeben werden.</td></tr>
     </table>
     <table>
     <tr><th colspan="1" rowspan="1">type="datetime" format="dd.MM.yyyy" min="01.01.1970" max="31.12.2030"</th></tr>
     <tr><th colspan="1" rowspan="1">type="datetime" format="dd.MM.yyyy;yyyy-MM-dd" min="21.08.2009"</th></tr>
     <tr><td colspan="1" rowspan="1">Die Eingabe muss ein Datums- oder Zeitwert sein. Optional kann über die Attribute min und/oder max der 
     Wertebereich eingeschränkt werden. Das Attribut format muss ein java.text.SimpleDateFormat Pattern enthalten 
     (z.B. „dd.MM.yyyy“), das bestimmt, wie der Wert formatiert sein muss. Erlaubt sind auch mehrere durch Semikolon
     getrennte Formate. Die min- und max-Werte müssen im ersten angegebenen Format spezifiziert werden.</td></tr>
     </table>
     <table>
     <tr><th colspan="1" rowspan="1">type="string" min="a" max="zzz"</th>
     </tr><tr><td colspan="1" rowspan="1">Eine Eingabe kann ein beliebiger Text sein. Optional kann über die Attribute min und/oder max der 
     Wertebereich eingeschränkt werden.</td></tr>
     </table>
     <table>
     <tr><th colspan="1" rowspan="1">regexp=".+@.+\..+"</th></tr>
     <tr><td colspan="1" rowspan="1">Die Eingabe muss den angegebenen regulären Ausdruck erfüllen. Die Syntax des regulären Ausdrucks ist durch 
     die Klasse java.util.regex.Pattern definiert.</td></tr>
     </table>
     <table>
     <tr><th colspan="1" rowspan="1">xsl="contains(.,'@')"</th></tr>     
     <tr><td colspan="1" rowspan="1">Die Eingabe wird gegen eine XSL Bedingung geprüft, wie sie in XSL if oder when Elementen verwendet werden 
     kann. Der Eingabewert wird in der Bedingung durch einen Punkt referenziert.</td></tr>
     </table>
     <table>
     <tr><th colspan="1" rowspan="1">class="foo.bar.Validator" method="validateFooBar"</th></tr>
     <tr><td colspan="1" rowspan="1">Die Eingabe wird durch Aufruf einer beliebigen Java-Methode validiert, die true oder false zurückgibt. Im 
     oben gezeigten Beispiel würde die Methode public static boolean validateFooBar( String value ) aus der Klasse 
     foo.bar.Validator aufgerufen. Es sind so sehr spezielle Validierungsregeln wie z.B. das Prüfen einer ISBN 
     implementierbar.</td></tr>
     </table>
     <p class="fett">Validierungsregeln für Feldkombinationen</p>
     <p>
     Es ist ebenfalls möglich, die Eingaben zweier Felder gegeneinander zu prüfen. Dazu wird ein 
     <code>condition</code>-Element in das die beiden Felder enthaltende Panel eingefügt. Die Werte der beiden Felder 
     können dann über Vergleichsoperatoren gegeneinander geprüft werden. Beispiele:</p>
     <ul>
     <li>Ein Eingabeformular zum Ändern eines Passwortes enthält zwei Passwortfelder, so dass das Passwort 
     wiederholt eingegeben werden muss. Die Eingaben in diesen beiden Feldern müssen identisch sein.</li>
     <li>Ein Eingabeformular enthält zwei Eingabefelder für einen Datumsbereich. Das Datum im Feld 
     <code>validFrom</code> muss kleiner oder gleich dem Datum im Feld <code>validTo</code> sein.</li>
     </ul>
     
     <img src="images/codebeispiel.png" alt="Codebeispiel" title="Codebeispiel"/>
     <p class="klein"><strong>Abbildung 2.49:</strong> Codebeispiel</p>
     
     
     <p>
     Zunächst werden die Werte beider Eingabefelder <code>validFrom</code> und <code>validTo</code> nach den gleichen 
     Regeln auf die Eingabe eines korrekten Datums geprüft. Wenn mindestens eines der Felder eine Eingabe enthält 
     (was ggf. über ein <code>required-</code>&gt;Attribut erzwungen werden könnte), werden die Werte der Felder 
     miteinander verglichen.
     </p>
     
     <p><code>field1="validFrom"</code></p>
     <p>
     Erstes zu vergleichende Feld. Syntax und Funktionsweise entsprechen dem Verhalten des Attributes <code>var</code> 
     für Zellen.
     </p>
     <p><code>field2="validTo" </code>&gt;</p>
     <p>
     Zweites zu vergleichende Feld. Syntax und Funktionsweise entsprechen dem Verhalten des Attributes <code>var</code> 
     für Zellen.
     </p>
     <p><code>operator="&amp;lt;="</code></p>
     <p>
     Vergleichsoperator (hier <code>&gt;=</code>). Es können die Operatoren <code>=, &gt;, &lt;, &gt;=, &lt;=, !=</code> 
     (für ungleich) verwendet werden.
     </p>
     <p><code>type="datetime"</code><br/>
     <code>format="dd.MM.yyyy"</code></p>
     <p>
     Datentyp und Format der Eingabe, analog zu den gleichnamigen Attributen, die im vorangehenden Abschnitt bereits 
     erläutert wurden.
     </p>
     <p>
     Alternativ kann auch hier über eine <strong>externe Java-Methode validiert</strong> werden. Das folgende Beispiel 
     würde für zwei Zahlen prüfen, ob die eine das Quadrat der anderen ist:
     </p>
     <p><code>&lt;condition id="cond.quadrat" field1="zahl1" field2="zahl2"</code> <br/> 
     <code>class="math.Validator" method="validateSquare"&gt;</code><br/>
     <code> &lt;label&gt;Zahl 1 muss gleich dem Quadrat der Zahl 2 sein!&lt;/label&gt;</code><br/>
     <code>&lt;/condition&gt;</code></p>
     <p>In der Klasse math.Validator könnte die Methode zur Validierung wie folgt aussehen:</p>
     <p><code>public static boolean validateSquare( String value1, String value2 )</code><br/>
     <code>{</code><br/> 
     <code>int zahl1 = Integer.parseInt( value1 );</code><br/> 
     <code>int zahl2 = Integer.parseInt( value2 );</code><br/> 
     <code>return ( zahl1 == (zahl2 * zahl2) );</code><br/>
     <code>}</code></p>
     <p>
     Bitte beachten Sie, dass bei externer Validierung die Werte immer als String übergeben werden. Durch Vorschalten 
     einer weiteren Validierungsregel kann aber z.B. leicht erreicht werden, dass nur Zahlen oder bestimmte Datentypen 
     eingegeben werden können.
     </p>
     <p class="fett">Validierung ganzer Panels oder XML-Bereiche</p>
     <p>
     Mehrere Eingabefelder können gemeinsam über eine XSL-Bedingung oder eine externe Java-Methode validiert werden. So 
     kann im Extremfall das gesamte aus der Eingabe resultierende XML-Dokument validiert werden. Die Eingabevalidierung 
     bezieht sich in diesem Fall auf ein Panel der Editor-Definition und dem daraus resultierendem XML-Element. Dies 
     kann auch das Wurzelpanel sein. Das condition-Element für die Validierungsregel muss dabei ein Kindelement dieses 
     Panels sein.
     </p>
     <p>
     Über die Attribute <strong>class</strong> und <strong>method</strong> kann eine externe Java-Methode angegeben 
     werden, die ein XML-Element validiert:
     </p>
     <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
     <components var="/input" root="root"
     ...
       <panel lines="off" id="root">
         <condition id="validateExt" 
                 class="foo.bar.Validator" method="validateInput">
                     <label xml:lang=</code><code>"de"> Eingabefehler! </label>
         </condition>
         ...
     
     ruft dann zur Validierung in der Klasse <code>foo.bar.Validator</code> die folgende Methode auf:
     
     public static boolean validateInput( Element input )
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     Über das Attribut <strong>xsl</strong> kann eine XSL-Bedingung angegeben werden. Im folgenden Beispiel wird in 
     einer Suchmaske sichergestellt, dass mindestens ein Eingabefeld mit einem Wert ausgefüllt ist. Dies entspricht der 
     XSL-Bedingung: „Die Anzahl der Elemente, bei denen das value-Attribut nicht leer ist, ist größer null“.
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     <components var="/query" root="root">
     ...
       <panel lines="off" id="root">
         <condition id="someInputNeeded"
              xsl="count(conditions/boolean/*[string-length(@value) &gt; 0])
                &gt; 0">
           <label xml:lang="de">Bitte einen Suchausdruck eingeben!>/label>
         </condition>
         ...
     ]]>
     </p><![CDATA[
     ]]></source>
    </section>
   </section>
   
   <section>
    <title>Klassifikationsbrowser</title>
    <p>Mit dem Klassifikationsbrowser bietet MyCoRe die Möglichkeit über Klassifikationen zu navigieren und so zu den 
    zugehörigen Dokumenten zu gelangen.
    </p>
    <p>Für jede Klassifikation die über einen Link im Navigationsmenü erreicht werden soll, muss ein Beschreibungsblock 
    für das Browsen angelegt werden. 
    </p>
    <p>Beispiel für Browsen in Dissertationen:<br/>
    Der Klassifikationsbrowser für die Klassifikation der Dissertationen wird (z.B. bei einer lokalen 
    Beispiel-Installation) durch folgenden Request aufgerufen:
    </p>
    <p class="kasten"><code>http://localhost:8080/docportal/browse/dissertationen</code>
    </p>
    <p>
    Dabei werden alle Requests von http://localhost:8080/docportal/browse/* vom Servlet 
    <code>MCRClassificationBrowser</code> entgegengenommen. Hier wird der Browserpfad, der nach <code>…browse/</code> 
    stehen muss, ausgewertet und die dem Browserpfad entsprechende Klassifikation der Navigation zugrunde gelegt.
    </p>
    <p>
    In der Properties-Datei muss zum zugehörigen Browserpfad <code>dissertationen</code> ein Konfigurationsblock 
    angelegt sein. Ist ein Parameter im Konfigurationsblock nicht enthalten, wird versucht in einem 
    Default-Konfigurationsblock den entsprechenden Default-Parameter zu lesen. Ist dieser nicht vorhanden erhält man 
    einen <code>MCRConfigurationException</code> für die Pflichtfelder.
    </p>
    
    <img src="images/klassifikationsbrowser.png" alt="Klassifikationsbrowser" title="Klassifikationsbrowser"/>
     <p class="klein"><strong>Abbildung 2.50:</strong> Klassifikationsbrowser in einer MyCoRe-Anwendung</p>
     
    <section>
     <title>Der Konfigurationsblock</title>
     <p class="fett">MCR.ClassificationBrowser.dissertationen.Classification </p>
     <p>
     Dieser Parameter ordnet dem Browserpfad eine Klassifikation (MyCoRe ID der Klassifikation) zu. 
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     Beispiel:
     
     MCR.ClassificationBrowser.dissertationen.Classification
     = Docportal_class_00000009
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     Hinter der Klassifikation mit der ID Docportal_class_00000009 verbirgt sich in diesem Fall die DDC-Klassifikation, 
     nach der typischerweise Dissertationen klassifiziert werden.
     </p>
     <p class="fett">MCR.ClassificationBrowser.dissertationen.EmbeddingPage</p>
     <p>
     Legt fest, in welche Datei die Klassifikation eingebettet werden soll. Diese Datei muss das Tag 
     <code>&lt;classificationbrowser/&gt;</code> enthalten. An der Position dieses Tags wird der Inhalt (der generierte 
     XML-Klassifikationsbaum) zur Laufzeit eingefügt. Durch die Variabilität ist es möglich, Klassifikationen nach 
     Belieben in beliebige XML-Dokumente einzubetten.
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
      Beispiel:
      
      MCR.ClassificationBrowser.dissertationen.EmbeddingPage
      = mcr_doc_browse.xml</code>
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>Die Datei <code>mcr_doc_browse.xml</code> ist im DocPortal enthalten.</p>
     <p class="fett">MCR.ClassificationBrowser.dissertationen.Style</p>
     <p>
     Legt das Stylesheet fest, mit dem das erzeugte XML-Document transformiert wird. Dabei setzt sich der Name des 
     auszuwählenden Stylesheets aus der EmbeddingPage und dem Style zusammen. 
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     Beispiel:
     
     MCR.ClassificationBrowser.dissertationen.Style = search
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>Es wird die Datei <code>mcr_doc_browse-search.xsl</code> zur Transformation verwendet.</p>
     <p class="fett">MCR.ClassificationBrowser.dissertationen.EmptyLeafs</p>
     <p>
     Klassifikationen besitzen im Allgemeinen eine baumartige Struktur. Zu jeder im Baum dargestellten Kategorie wird 
     die Anzahl der damit klassifizierten Objekte ermittelt und (je nach Stylesheet) dargestellt. Kategorien die keine 
     Objekte referenzieren (Anzahl der Dokumente=0) können durch diese Option ausgeblendet werden. Mögliche Werte sind 
     <code>yes|no.</code>
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     Beispiel:

     MCR.ClassificationBrowser.dissertationen.EmptyLeafs = yes
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>Zeigt auch die leeren Kategorien der Klassifikation an.</p>
     <p class="fett">MCR.ClassificationBrowser.dissertationen.View</p>
     <p>
     Bei der Darstellung einer Klassifikation kann gewählt werden, ob der gesamte Baum oder nur die jeweils aktuelle 
     Ebene angezeigt werden soll.
     </p>
     <p>
     Durch Zu- und Aufklappen wird die nächste Ebene dann ein- bzw. ausgeblendet. Mit <code>View=flat</code> wird dann 
     in die aktuelle Ebene gewechselt und die vorherige ist nicht mehr sichtbar. Mit <code>View=tree</code> wird immer 
     der gesamte Baum dargestellt und die gewählten Ebenen werden auf- und zugeklappt, sodass es möglich ist, 
     gleichzeitig mehrere Kategorien verschiedener Ebenen darzustellen.<br/>
     Mögliche Werte sind <code>flat|tree</code>
     </p>     
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     Beispiel:
     
     MCR.ClassificationBrowser.dissertationen.View = flat
     ]]>
     </p><![CDATA[
     ]]></source>
     <p class="fett">MCR.ClassificationBrowser.dissertationen.Doctype</p>
     <p>
     Über den Parameter Doctype wird die Auswahl der Dokumenttypen gesteuert, die bei der Abrage der Dokumente 
     berücksichtigt werden sollen.
     </p>
     <p>
     Der angegebene Typ muss in der Datei <code>mycore.properties</code> über den Parameter 
     <code>MCR.type_[Doctype]=[Dokumententypliste]</code> definiert sein. Als möglicher Wert, kann jede Angabe aus 
     MCR.type_* verwendet werden. 
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     Beispiel:
     
     MCR.ClassificationBrowser.dissertationen.Doctype = mydisshabs
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>Es wird <code>MCR.type_mydisshabs</code> in der Datei <code>mycore.properties</code> herausgesucht, der z.B. 
     mit <code>MCR.type_mydisshabs=disshab</code> belegt ist. Somit werden bei dieser Klassifikation alle Dokumente vom 
     Typ <code>disshab</code> berücksichtigt.
     </p>
     <p>
     Für <code>Doctype=alldocs</code> wird z.B. der Wert <code>MCR.type_alldocs=document, article, codice, disshab, 
     professorum, portrait </code>gefunden und alle Dokumente, die einem Typ aus der Typliste entsprechen, bei der Suche 
     berücksichtigt.
     </p>
     <p class="fett">MCR.ClassificationBrowser.dissertationen.Restriction</p>
     <p>
     Es ist möglich für die referenzierten Objekte eine Restriktion zu setzen um die Auswahl durch eine weitere 
     Kategorie einer beliebigen Klassifikation weiter einzuschränken. Es werden dann nur die Objekte berücksichtigt, die 
     beiden Kriterien genügen.
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     Beispiel:

     MCR.ClassificationBrowser.dissertationen.Restriction
      = Docportal_class_00000005##TYPE0007
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     Mit dieser Restriktion werden nur die Dissertationen berücksichtigt, die auch der Klassifikation 
     <code>Docportal_class_00000005</code> mit der Kategorie <code>TYPE0007</code> genügen. Das sind im Beispiel als 
     Ergebnis alle Dissertationen im PDF-Format.
     </p>
     <p class="fett">MCR.ClassificationBrowser.dissertationen.searchField</p>
     <p>
     Hier wird das bei der Ausführung der Query zu durchsuchende Feld festgelegt.
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     Beispiel:
     
     MCR.ClassificationBrowser.dissertationen.searchField = ddc1
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     Es wird das DDC-Tag in den Metadaten der Dokumente als Suchparameter genutzt.
     </p>
     <p class="fett">MCR.ClassificationBrowser.dissertationen.Comments</p>
     <p>
     Kommentare, die optional beim Erstellen der Klassifikation für Kategorien angegeben sein können, werden im Baum mit 
     dargestellt. Mögliche Werte sind <code>true|false</code>
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     Beispiel:

     MCR.ClassificationBrowser.dissertationen.Comments = true
     ]]>
     </p><![CDATA[
     ]]></source>
     <p class="fett">Der Default-Konfigurationsblock</p>
     <p>
     Die Defaultbelegung für die notwendigen Parameter enthält folgende Werte:
     </p>
     <source xml:space="preserve"><![CDATA[
     ]]><p class="kastensource">  
     <![CDATA[ 
     MCR.ClassificationBrowser.default.EmbeddingPage = mcr_doc_browse.xml
     MCR.ClassificationBrowser.default.Style = search
     MCR.ClassificationBrowser.default.EmptyLeafs = yes
     MCR.ClassificationBrowser.default.View = tree
     MCR.ClassificationBrowser.default.Comments = true
     MCR.ClassificationBrowser.default.Doctype = alldocs
     MCR.ClassificationBrowser.default.searchField = cltype
     ]]>
     </p><![CDATA[
     ]]></source>
     <p>
     Insbesondere die Belegung des <code>searchField</code>-Parameters kann natürlich zu falschen Ergebnissen bei der 
     Dokumentreferenzierung und der damit verbundenen Anzeige der Anzahl der Dokumente führen.
     </p>
    </section>
   </section>
   
   <section>
    <title>Klassifikationseditor </title>
    <p>
    Mit dem Klassifikationseditors als Webinterface, gibt es neben der Kommandozeilen-Schnittstelle eine weitere 
    Möglichkeit, Klassifikationen im System zu erzeugen, zu bearbeiten und zu löschen.
    </p>
    <p>
    Um Klassifikationen editieren zu können, muss der angemeldete Nutzer je nach Bedarf über folgende Rechte verfügen:
    </p>
    <p class="kasten">
    <code>create-classification</code> zum Erzeugen von Klassifikationen<br/>
    <code>modify-classification</code> zum Modifizieren von Kategorieeinträgen in einer Klassifikation<br/>
    <code>delete-classification</code> zum Löschen einer Klassifikation </p>
    <p>(siehe Kapitel 5.3.4 Administrative Privilegien im UserGuide).</p>
    <p class="fett">Konfiguration</p>
    <p>
    Die Konfiguration des Klassifikationseditors erfolgt über die Angaben in der Datei 
    <code>mycore.properties.classification</code>. Wie man Seiten, die im Fehlerfall angezeigt werden, definieren kann, 
    zeigt nachstehender Auszug aus der Datei:</p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    MCR.classeditor_page_error_user = editor_error_user.xml
    MCR.classeditor_page_cancel = classeditor_cancel.xml
    MCR.classeditor_page_error_id = classeditor_error_clid.xml
    MCR.classeditor_page_error_move = classeditor_error_move.xml
    MCR.classeditor_page_error_delete = classeditor_error_delete.xml
    ]]>
    </p><![CDATA[
    ]]></source>
    <p>Analoge Properties zum Klassifikationsbrowser:</p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    MCR.classeditor.EmbeddingPage = mcr_doc_browse.xml
    MCR.classeditor.Style = edit
    ]]>
    </p><![CDATA[
    ]]></source>
    <p>
    Für die Klassifikationen, die über die ID definiert sind, wird analog zum Browsen der Browserpfad definiert. Dies 
    dient dazu, um auch hier die richtige Zuordnung zu den, durch die Klassifikation referenzierten Dokumente zu 
    besitzen:
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    MCR.classeditor.atlibri_class_00000012 = codices
    MCR.classeditor.atlibri_class_00000013 = archiv
    MCR.classeditor.atlibri_class_00000009 = ddc
    MCR.classeditor.atlibri_class_00000008 = eval
    MCR.classeditor.atlibri_class_00000007 = dnb
    MCR.classeditor.atlibri_class_00000006 = medien
    MCR.classeditor.atlibri_class_00000005 = type
    MCR.classeditor.atlibri_class_00000003 = origin
    ]]>
    </p><![CDATA[
    ]]></source>
    
    <section>
     <title>Start des Klassifikationseditors</title>
     <p>
     Der Editor wird über den Klassifikationsbrowser mit dem Parameter <code>mode=edit</code> gestartet.
     </p>
     <p>
     Beispiel:<br/>
     <code>http://localhost:8080/docportal/browse?mode=edit </code></p>
     <p>Die Handhabung des Klassifikationseditors ist im UserGuide beschrieben.</p>
    </section>
   </section>
   <section>
    <title>Nützliche Klassen </title>
    <section>
      <title>MCRTextResolver</title>
      <p>
      Ab MyCoRe 2.1 gibt es die neue Klasse MCRTextResolver. Diese ermöglicht es frei definierbare Variablen
      und MyCoRe-Properties (im folgenden unter dem Begriff Variablen zusammengefasst) in Texten aufzulösen.
      Hierzu ein kleines Beispiel:
      </p>
      <source xml:space="preserve"><![CDATA[
        ]]><p class="kastensource">  
          <![CDATA[ 
          „Ich programmiere in {MCR.NameOfProject}.“
          ]]>
        </p><![CDATA[
      ]]></source>
      <p>
      Würde man diesen Text innerhalb des DocPortal Projekts mit dem MCRTextResolver auflösen, entsteht
      folgender Text: „Ich programmiere in DocPortal“. Inhalte in geschweiften Klammern werden vom
      MCRTextResolver als Variablen erkannt und entsprechend aufgelöst.
      </p>
      <p class="fett">Bedingungen – eckige Klammern []</p>
      <p>
      Eckige Klammern ermöglichen es Variablenbedingung zu definieren. Der gesamte Inhalt in eckigen Klammern
      wird nur dann verwendet, wenn alle enthaltenen Variablen nicht null und nicht leer sind. Als Beispiel soll
      „[Mein Nachname ist {lastname}].“ dienen. Der gesamte Inhalt wird nur aufgelöst, wenn die Variable lastname
      existiert. Andernfalls wird der Inhalt ignoriert.
      </p>
      <p>
      Eine valide Datums Angabe könnte damit zum Beispiel folgendermaßen realisiert werden: „{year}[-{month}[-{day}]]“.
      </p>
      <p class="fett">Escaping - \</p>
      <p>
      Der MCRTextResolver unterstützt Escaping um vordefinierte Symbole wie {}[] zu maskieren.
      </p>
      <p class="fett">API</p>
      <p>
      Der Zugriff über die API ist denkbar einfach:
      </p>
      <source xml:space="preserve"><![CDATA[
        ]]><p class="kastensource">  
          <![CDATA[ 
          MCRTextResolver resolver=new MCRTextResolver();
          String result=resolver.resolve("Ich programmiere in {MCR.NameOfProject}.");
          ]]>
        </p><![CDATA[
      ]]></source>
      <p>
      Variablen können entweder mit Hilfe einer Map an den Konstruktor übergeben, oder per
      addVariable(name, value) gesetzt werden.
      </p>
      <source xml:space="preserve"><![CDATA[
        ]]><p class="kastensource">  
          <![CDATA[ 
          Map<String, String> vars=new Hashtable<String, String>();
          vars.put("firstname", "Max");
          vars.put("lastname", "Mustermann");
          MCRTextResolver resolver=new MCRTextResolver(vars);
          resolver.addVariable("birthdate", "1977-04-04");
          String result=resolver.resolve("Name: {firstname} {lastname}; Geburtstag: {birthdate}");
          ]]>
        </p><![CDATA[
      ]]></source>
    </section>
   </section>
  </section>
  <section>
  <title>Komponenten</title>
  <p>
  Eine allgemeine Beschreibung, was Komponenten in MyCoRe ausmachen, wie sie definiert sind und welche Struktur 
  sie haben, wurde bereits im Kapitel 1 ausführlich erläutert. Dieses Kapitel soll nun die Funktionalitäten der 
  einzelnen Komponenten und ihre Einbindung in die Gesamtapplikation näher beschreiben.  
  </p>
  
  <section>
   <title>Das Session Listing (session-listing)</title>
   
   <section>
    <title>Allgemeines</title>
    
    <p>
	Die Komponente Session Listing ist relativ klein und einfach. Sie stellt lediglich die 
	Möglichkeit bereit, in der interaktiven Sitzung angezeigt zu bekommen, welche Sitzungen
	für die MyCoRe-Anwendung aktiv sind. Die Anfrage an das Servlet liefert eine XML-Datei 
	zurück, welche über das mitgelieferte Stylesheet angezeigt wird. Ggf. kann dieses Stylesheet 
	durch eine eigene Variante überschrieben werden.
	</p>
   </section>
   
   <section>
    <title>Installation</title>
    
    <p>
	Der MyCoRe-Kern enthält schon alle Dateien für die Integration der Komponente. Sie muss
	lediglich noch aufgerufen werden, z. B. in der navigation.xml mit <code>href="/servlets/MCRSessionListingServlet"</code>.
	</p>
   </section>
   
  </section>
	  
  <section>
   <title>Die SimpleWorkflow-Komponente (swf)</title>
   
   <section>
    <title>Allgemeines</title>  
    
    <img src="images/progguide_simpleworkflow_1.png" alt="SimpleWorkflow allgemein" title="SimpleWorkflow allgemein"/>
    <p class="klein"><strong>Abbildung 3.1:</strong> Grundübersicht des SimpleWorkflow</p>  
    
    <p>
    Für die Erstellung einfacher Anwendungen, welche nur einen relativ primitiven Arbeitsablauf bedingen, war es 
    notwendig ein Werkzeug zur Gestaltung dieser Abläufe anzubieten. So entstand die Idee des 
    <code>SimpleWorkflow</code>. Eigentlich handelt es sich dabei gar nicht um einen Workflow, sondern eher um eine 
    Menge von kleinen Werkzeugen, die über HTTP-Requests zu einem interaktiven Arbeitsablauf zusammengefügt werden 
    können. Der Begriff <em>Workflow</em> soll dabei die Bearbeitungsebene zwischen dem ersten Erstellen eines 
	Objektes, seiner Bearbeitung und der Ablage im Server sowie die dabei vor sich gehenden Arbeitsschritte beschreiben. Physisch handelt es 
    sich um ein Verzeichnis <code>workflow</code>, unter welchem für jeden Objekttyp Unterverzeichnisse angelegt sind, 
    in welchen die Daten zwischengespeichert werden. Konsultieren Sie zum besseren Verständnis auch die Beschreibung im 
    MyCoRe-User Guide.
    </p>
    <p>
    Der SimpleWorkflow besteht im wesentlichen aus einer Sammlung von Servlets, die über HTTP-Requests angesprochen, 
    verschiedene Bearbeitungsprozesse initiieren. Dabei wird gleichzeitig eine Berechtigungsprüfung für den Zugriff auf 
    einzelne Aktionen durchgeführt. Für das Neuanlegen von Objekten ist die Permission 'create-'ObjectTyp bzw. für 
	mandantenfähige Systeme 'create-'ObjectBase erforderlich. 
    Ist das Objekt schon vorhanden, so entscheiden die ACL's des jeweiligen Objektes selbst über die Möglichkeit der Bearbeitung.
    </p>
    <table>
    <tr>
    <th colspan="1" rowspan="1">ACL-Permission</th>
    <th colspan="1" rowspan="1">Bedeutung</th>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>writewf</code></td>
    <td colspan="1" rowspan="1">Gestattet das Bearbeiten der Objekte im Workflow (d. h. auf dem Plattenbereich).</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>deletewf</code></td>
    <td colspan="1" rowspan="1">Gestattet das Löschen von Objekten im Workflow (d. h. auf dem Plattenbereich).</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>writedb</code></td>
    <td colspan="1" rowspan="1">Gestattet das Bearbeiten von Objekten im Server.</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>deletedb</code></td>
    <td colspan="1" rowspan="1">Gestattet das Löschen der Objekte aus dem Server.</td>
    </tr>
    </table>
    <p class="klein"><strong>Tabelle 3.1:</strong> Permissionliste für den SimpleWorkflow</p>
   </section>
   
   <section>
    <title>Bestandteile und Funktionen</title>
    <p>
    Der SimpleWorkflow besteht aus einer Reihe von Servlets. Die folgende Tabelle listet die Servlets auf.
    </p>
    <table>
    <tr>
    <th colspan="1" rowspan="1">Servlet</th>
    <th colspan="1" rowspan="1">Funktion</th>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>MCRStartEditorServlet</code></td>
    <td colspan="1" rowspan="1">Das Servlet dient als Startpunkt für alle Arbeiten mit dem SimpleWorkflow.</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>MCRCheckCommitDataServlet</code></td>
    <td colspan="1" rowspan="1">Wird vom Editor über ein &lt;target&gt;-Tag aufgerufen und schreibt die Metadaten nach Bearbeitung in den Server.</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>MCRCheckEditDataServlet</code></td>
    <td colspan="1" rowspan="1">Wird vom Editor über ein &lt;target&gt;-Tag aufgerufen und schreibt die Metadaten nach deren Bearbeitung auf 
    die Platte.</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>MCRCheckNewDataServlet</code></td>
    <td colspan="1" rowspan="1">Wird vom Editor über ein &lt;target&gt;-Tag aufgerufen und schreibt die neuen Metadaten auf die Platte.</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>MCRCheckCommitFileServlet</code></td>
    <td colspan="1" rowspan="1">Wird vom Editor über ein &lt;target&gt;-Tag aufgerufen und schreibt die Derivate-Daten nach Bearbeitung in den 
    Server.</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>MCRCheckNewFileServlet</code></td>
    <td colspan="1" rowspan="1">Wird vom Editor über ein &lt;target&gt;-Tag aufgerufen und schreibt die neuen Derivate-Daten auf die Platte.</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>MCRFileListWorkflowServlet</code></td>
    <td colspan="1" rowspan="1">Listet die auf der Platte befindlichen Dateien in den Derivaten auf.</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>MCRFileViewWorkflowServlet</code></td>
    <td colspan="1" rowspan="1">Gestattet den Zugriff auf eine Derivate-Datei auf der Platte.</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>MCRListDerivateServlet</code></td>
    <td colspan="1" rowspan="1">Listet alle auf der Platte befindlichen Derivate auf.</td>
    </tr>
    <tr>
    <td colspan="1" rowspan="1"><code>MCRListWorkflowServlet</code></td>
    <td colspan="1" rowspan="1">Erzeugt einen XML-Baum, welcher zur Darstellung des Workflow (Platteninhaltes) benötigt wird.</td>
    </tr>
    </table>
    <p class="klein"><strong>Tabelle 3.2:</strong> Übersicht der SimpleWorkflow-Servlets</p>
    <p>Die folgende Abbildung soll noch einmal die Beziehungen der einzelnen Teile verdeutlichen. Hier gibt es 
    zwei Komplexe. Der erste arbeitet mit dem Plattenzwischenspeicher und stellt einen simplen <em>Workbasket</em> dar. 
    In diesen Korb können Objekte neu eingestellt, bearbeitet, ergänzt, geprüft oder wieder gelöscht werden. Ist dieser 
    Arbeitsschritt fertig, so kann das Objekt in den Server hoch geladen werden. Hier gibt es wieder die Möglichkeit, so 
    der Nutzer die Berechtigung dazu hat, Objekte zu bearbeiten, zu verändern oder zu löschen. Diese Schritte arbeiten 
    direkt gegen den Server. Ausgangspunkt aller Aktivitäten ist dabei das <code>MCRStartEditorServlet</code>. Hier wird 
    beim Aufruf eine Aktion mitgegeben, welche den weiteren Ablauf bestimmt. Entweder werden jetzt die ToDo's direkt 
    ausgeführt (Löschen) oder es wird z.B. eine Web-Seite mit einer Editor-Maske aufgerufen. Diese wiederum beinhaltet im 
    &lt;target&gt;-Tag das zu nutzende Verarbeitungs-Servlet, welches dann je nach Aufgabe wieder zu einer Web-Seite oder 
    der Workflow-Ansicht verzweigt. Um weitere Aktionen in eigene Anwendungen zu integrieren, muss nur eine Servlet erstellt 
	werden, welches eine Ableitung vom <code>MCRStartEditorServlet</code> ist und die neuen Aktionen implementiert. Mit 
	MyCoRe 2.0 besteht die Möglichkeit, statt der Angabe des Types nun den Base-Bestandteil der MCRObjectID, also 
	<code>projectid_type</code> anzugeben. Damit können Permissions für gleiche Datenmodelltypen bei unterschiedlicher Projekt-ID
	einzeln abgesichert werden. 
    </p>
    
    <img src="images/progguide_simpleworkflow_2.png" alt="SimpleWorkflow" title="SimpleWorkflow"/>
    <p class="klein"><strong>Abbildung 3.2:</strong> Ablaufschema im SimpleWorkflow</p>  
    
   </section>
   
   <section>
    <title>Installation</title>
    <p>
    In DocPortal sind die Funktionen bereits standardmäßig integriert. Bei der Verwendung in anderen Applikationen 
	sind die nacholgenden Schritte auszuführen:
    </p>
    <ol>
    <li>die folgende Zeile ist in das XSL-Stylesheet zu kopieren, welches die Auswertung Ihrer XML-Webseiten 
		realisiert (z.B. <code>MyCoReWebPage.xsl</code>).<br/>
		<code>&lt;xsl:include href="workflow.xsl" /&gt;</code>
	</li>
    <li>Weiterhin finden Sie im Kern unter <code>components/swf/xsl</code> das Stylesheet <code>mycoreobject-to-workflow.xsl</code>. 
		Dieses ist eine Transformationsvorlage für die Transformation von den XML-Objekt-Metadaten in eine 
		SimpleWorkflow-interne XML Struktur. Für jeden Ihrer Metadaten-Typen muss eine solche Konverter-Datei mit 
		Namen <code>mycoreobject-&lt;type&gt;-to-workflow.xsl</code> in Ihrer Anwendung vorhanden sein.
	</li>
    <li>Als letztes muss der Workflow in eine XML-Webseite integriert und diese entsprechend über Menüpunkte aufgerufen werden. Aufgerufen 
		wird ein Workbasket mit der eingebetteten Zeile<br/>
		<code>&lt;workflow base="MCRObjectID.Base" step="editor" /&gt;</code> oder <br/>
		<code>&lt;workflow type="MCRObjectID.Type" step="editor" /&gt;</code>
	</li>
    </ol>
    
    <p>
    Die Integration des SimpleWorkflow in die Präsentationsseiten erfolgt unter Einbeziehung der bereitgestellten Icons 
    und eines dahinter liegenden Links. Dieses kann an beliebiger Stelle in der Präsentation platziert werden. Da die
	einzelnen Aktionsaufrufe sich in ihren Parametern doch erheblich unterscheiden sollten bei Bedarf die relevanten
	die entsprechenden Aufrufe im DocPortal-Beispiel zu Rate gezogen werden.
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    <a href="{$ServletsBaseURL}MCRStartEditorServlet{$HttpSession}?
       tf_mcrid={$mcrid}&amp;       - MCRObjectID
       se_mcrid={$mcrid}&amp;       - MCRObjectID
       re_mcrid={$mcrid}&amp;       - Return MCRObjectID, nur für Derivate-ToDo, optional
       type={$type}&amp;            - MCRObjectID Typ, alte Variante, ggf. optional
       project={$project}&amp;      - MCRObjectID Base, neu, überschreibt type
       step=commit&amp;             - Arbeitsschritt
       todo=seditobj&amp;           - ToDo
       layout={$layout}"            - optional
    >
	<img
       src="{$WebApplicationBaseURL}images/static/workflow_objedit.gif" 
       title="{$OMD.EditorEdit}"/>
    </a>
    ]]>
    </p><![CDATA[
    ]]></source>
    <p>
    Die Einbindung in den Editor erfolgt mit den folgenden Zeilen.
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[
    <target type="servlet" name="MCRCheckNewDataServlet" method="post" format="xml" />
    oder
    <target type="servlet" name="MCRCheckEditDataServlet" method="post" format="xml" />
    oder
    <target type="servlet" name="MCRCheckCommitDataServlet" method="post" format="xml" />
    ]]>
    </p><![CDATA[
    ]]></source>
   </section>
   
   <section>
    <title>Konfiguration</title>
    <p>
    Die Konfiguration des SimpleWorkflow beschränkt sich auf einige wenige Dinge. Für MyCoRe 2.0
	kann alternativ entweder auf den MCRObjectID.Type (alt) oder MCRObjectID.Base (neu) 
	referenziert werden. Für jede Installation können einige Werte different sein, so dass 
	es sich empfiehlt, diese in der <code>mycore.private.properties</code> abzulegen. 
	Ein großer Teil der vom <code>MCRStartEditorServlet</code> veranlassten Aktionen ist so 
    implementiert, dass Sie auf Wunsch eine E-Mail an eine oder mehrere E-Mail-Adressen schicken können. Wenn Sie für 
    den Konfigurationswert, welcher durch das Paar <code>[MCRObjectID.Base|MCRObjectID.Type].[todo]</code> 
	beschrieben wird, nichts angeben, so wird die E-Mail unterdrückt. Alle Angaben in diesem
	Konfigurationsabschnitt sind selbsterklärend. Anzugeben sind:
    </p>
    <ul>
	<li>allgemeine Angaben zur Mailverteilung</li>
    <li>die Verzeichnisnamen des Plattenspeichers,</li>
    <li>die Mail-Verteilung</li>
    </ul>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    ##################################################################
    #  SimpleWorkflow                                                #
    ##################################################################
		
    # Generic mail configuration for MCRMailer
    # The server for outgoing mails
    MCR.Mail.Server=mail.mycore.de
    # The mail protocol
    MCR.Mail.Protocol=smtp
    # The debug option
    MCR.Mail.Debug=false
    # Encoding for the mail
    MCR.Mail.Encoding=UTF-8
    # Number of send tries to send the mail : 0 – off or n tries
    MCR.Mail.NumTries=1
    # Editor Mail adresses for Messages add1@serv1,add2,@serv2,...
    MCR.Mail.Address=mycore@mail.mycore.de

    # Editor path for directories
    MCR.SWF.Directory.base=%MCR.basedir%/data/workflow
    MCR.SWF.Directory.[MCRObjectID.Base|MCRObjectID.Type]=%MCR.basedir%
        /data/workflow/[MCRObjectID.Base|MCRObjectID.Type]]]><![CDATA[
    ...

    # Editor flags for base/type and todo
    MCR.SWF.Mail.[MCRObjectID.Base|MCRObjectID.Type].
        [todo]=%MCR.Mail.Address%
	...

    ]]>
    </p><![CDATA[
    ]]></source>
   </section>
   
   <section>
    <title>Ergänzung eigener ToDo's</title>
    <p>
    Das MCRStartEditorServlet gestattet eine Erweiterung mit eigenen Funktionen durch einfache Vererbung. Erstellen Sie 
    eine Klasse MCRStartEditorServletMyToDo als Ableitung des MCRStartEditorServlet. Hierin können Sie nun Methoden 
    definieren, welche als ToDo direkt aufgerufen werden können. Entsprechend der Konfiguration können dann auch Mails
	versendet werden.	 
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
package org.mycore.frontend.servlets;

import java.io.IOException;

/**
 * The class extends the MCRStartEditorServlet with a new method
 * 
 * @author Jens Kupferschmidt
 */
public class MCRStartEditorServletMyToDo extends MCRStartEditorServlet {

    private static final long serialVersionUID = 1L;

    /**
     * A new method. The access right is writedb.
     * 
     * @param job
     *            the MCRServletJob instance
     * @param cd
     *            the common data part
     */
    public void mytodo(MCRServletJob job, CommonData cd) throws IOException {
        // access right
        if (!MCRAccessManager.checkPermission(cd.mysemcrid, "writedb")) {
            job.getResponse().sendRedirect(job.getResponse().encodeRedirectURL(getBaseURL() + usererrorpage));
            return;
        }
		
		/** ToDo code */
		
        // back to the metadata view
        StringBuffer sb = new StringBuffer();
        sb.append(getBaseURL()).append("receive/").append(cd.mysemcrid);
        job.getResponse().sendRedirect(job.getResponse().encodeRedirectURL(sb.toString()));
    }

}
    ]]>
    </p><![CDATA[
    ]]></source>
   </section>
   
   <section>
    <title>Ergänzung eigener Datenmodell-Datentypen</title>
    <p>
    Werden dem bereits vorhandenen allgemeinen Datenmodell neue bzw. ergänzende Typen 
	hinzugefügt, so muss die Prüfung und Vervollständigung des Output Validators für den Editor
	erweitert werden. Dazu muss in der Klasse <code>MCREditorOutValidator</code> eine
	Methode für die Klasse eingefügt werden. Die Klasse prüft den Output des Editor Framework
	und ergänzt fehlende Namespaces (z. B. für xml:lang).
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    /**
     * @param datasubtag
     */
    boolean checkMCRMetaXYZ(Element datasubtag) {
        return checkMetaObject...(datasubtag, MCRMetaXYZ.class);
    }
    ]]>
    </p><![CDATA[
    ]]></source>
   </section>
  </section>
  
  <section>
   <title>Das Webservice-Modul</title>
   
   <section>
    <title>Allgemeines</title>
    <p>
    Für das Webservice-Module wird das Axis-Framework verwendet (http://ws.apache.org/axis/). Über den Webservice können 
    MyCoRe-Objekte geholt und Queries in der neuen Abfragesprache ausgeführt werden. In dem Modul ist auch ein Beispiel 
    eines Clients enthalten, der den installierten Webservice von MyCoRe nutzt.
    </p>
   </section>
   
   <section>
    <title>Installation des Webservices</title>
    <p>
    Hierzu müssen in der mycore.private.properties die Properties für den Axis-Administrator gesetzt werden:
    </p>
    <p class="break"><code>MCR.ws_admin</code> =Kennung des Axis-Administrators</p>
    <p class="break"><code>MCR.ws_adminpasswd</code> =und zugehöriges Passwort</p>
    <p>
    Von <code>ant webapps</code> werden Kennung und Passwort in die Datei webapps/WEB-INF/users.lst eingetragen. 
    Docportal wird wie gewohnt gestartet und durch Eingabe der Url 
    </p>
    <p class="break"><code>http://localhost:8080/servlets/AxisServlet</code></p>
    <p>
    wird geprüft, ob Axis richtig konfiguriert ist. Danach wird das Deployment des Webservice mit 
    <code>ant webservice.deploy</code> (docportal/modules/module-webservices/build.xml) durchgeführt. Ein erneuter 
    Aufruf des AxisServlets zeigt den MyCoRe-Webservice mit dem Namen <code>MCRWebService</code> und den Methoden 
    <code>MCRDoRetrieveObject</code> und <code>MCRDoQuery</code> an. Ein Klick auf die <code>WSDL</code> 
    (Web Service Description Language) von <code>MCRWebService</code> zeigt die Parameter und Datentypen der 
    Rückgabewerte an.
    </p>
    <p>
    Mit <code>ant webservice.undeploy</code> wird das Undeployment des Webservice <code>MCRWebService</code> 
    durchgeführt. 
    </p>
    <p>Mit </p>
    <p class="breaksource">  
    <source xml:space="preserve"><![CDATA[      
     
    http://localhost:8080/services/MCRWebService?
    method=MCRDoRetrieveObject&id=<mcrid>
    ]]><![CDATA[
    ]]></source>
    </p>
    <p>kann überprüft werden, ob der <code>MCRWebService</code> Ergebnisse liefert.</p>
    <p>
    Sollten Sie beim Deploy/Undeploy die Meldung „Exception in axis-admin“ oder „axis-admin failed with 
    {http://xml.apache.org/axis/}HTTP (401)Unauthorized“ erhalten, setzen Sie wie am Anfang dieses Abschnittes 
    beschrieben, Kennung und Passwort des Axis-Administrators. Nach einem erneuten <code>ant webapps</code> führen 
    Sie <code>ant webservice.deploy</code> aus. Die Konfigurationsdatei für Axis ist 
    docportal/config/server-config.wsdd.
    </p>
   </section>
   
   <section>
    <title>Client für den Webservice erzeugen </title>
    <p>
    Mit '<code>ant client.cmd</code>' wird ein Webservice-Client erstellt, der den Webservice <code>MCRWebService</code> 
    nutzt. Hierzu werden WSDL-Informationen vom Server geholt und mittels Axis die Stubs generiert und im Verzeichnis 
    <code>module-webservices/build/src</code> gespeichert. Anschließend werden alle Daten kompiliert und 
    <code>module-webservices/build/bin/wsclient.cmd </code>(Windows) gebaut.
    </p>
    <p><code>[ToDo]: sh für Linux bauen]</code></p>
   </section>
  </section>
  
  <section>
   <title>Bildbetrachter</title>
   
   <section>
    <title>Allgemeines</title>
    <p>
    DocPortal bietet einen sogenannten „Image-Viewer“ für das komfortable Betrachten von Bilddaten an. Dieser eignet 
    sich sehr gut für Bildarchive oder jegliche Content-Repositories in denen Bilddaten verwaltet und angezeigt werden 
    müssen.
    </p>
    <p>
    Der Bildbetrachter basiert, wie MyCoRe, auf Java und XML/XSL. Grundsätzlich wird die Funktionalität in zwei 
    getrennten Modulen, „Module-Imaging“ im MyCoRe-Kern und „Module-IView“ in DocPortal realisiert. Die folgende 
    Abbildung zeigt die allgemeine Systemarchitektur.
    </p>
    <p><code>[ToDo: Graphik erstellen]</code></p>
   </section>
   
   <section>
    <title>Module-Imaging – API zur Bildbearbeitung</title>
    <p>
    Das „Module-Imaging“ befindet sich im MyCoRe-Kern und bietet eine API um Bilddaten, in MyCoRe abzuspeichern, 
    performant zu laden und gegebenenfalls zu verändern (Skalierung, Bereichsextraktion).
    </p>
    <p>
    Das Modul benutzt die Bildbearbeitungsbibliothek „JAI“ von Sun als Grundlage für Bildberechnungen.
    </p>
    <p>
    Die folgende Abbildung gibt einen Überblick über die verschiedenen Klassen und deren Zusammenarbeit.
    </p>
    
    <img src="images/module_imaging.png" alt="Module-Imaging" title="Module-Imaging"/>
    
    <p class="fett">Bilder lesen</p>
    <p>
    Bilder können über den Image-Service geladen werden. Das Modul organisiert dabei automatisch den für das Bild 
    optimalen Ladevorgang. Entsprechend der Ausgabegröße wird entschieden, ob der Cache benutzt werden kann oder eine 
    Live-Skalierung durchgeführt werden muss.
    </p>
    <note label="Hinweis">
    Beachten Sie, dass performante Leseoperationen nur garantiert werden können, wenn der Cache eingeschaltet ist. Lesen 
    sie dazu den entsprechenden Abschnitt „Cache“.</note>
    <p class="fett">Bilder schreiben</p>
    <p>
    Bei eingeschaltetem Cache, werden die Bilder redundant abgelegt. Die gecachten Bilder werden im selben Content-Store 
    gespeichert, wie der restliche Content. Es ist nicht nötig, dafür weitere Konfigurationen vorzunehmen.
    </p>
    <p class="fett">Cache</p>
    <p>Der Cache speichert grundsätzlich Bilder redundant im Repository. Dabei werden die am häufigsten angeforderten 
    Bildgrößen bereits fertig berechnet vorgehalten. Dadurch müssen bei Leseoperationen keinerlei Berechnungen mehr 
    durchgeführt werden und die Ladezeit wird sehr gering.</p><p>Es können grundsätzlich drei verschiedene Caches 
    angelegt werden:
    </p>
    <ol>
    <li>Thumbnail-Cache<br/>
    <br/>
    Dieser Cachteil speichert eine Thumbnailversion des Bildes ab. Die Größe des Thumbnails wird in der Properties-Datei 
    $DocPortal/modules/module-iview/mycore.properties.iview im Bildbetrachter („MCR-IView“) als Pixel angegeben.
    <p class="breaksource">  
    <source xml:space="preserve"><![CDATA[      
     
    MCR.Module-iview.thumbnail.size.width=100
    MCR.Module-iview.thumbnail.size.height=75
    ]]><![CDATA[
    ]]></source>
    </p>
    </li>
    <li>Übersichtsbilder<br/>
    <br/>
    Dieser Cacheteil speichert Bilder in einer gebräuchlichen Bildschirmauflösung um Übersichten („Bildgröße an Seite-, 
    Breite angepasst“) vorzuhalten.<br/>
    <br/>
    Weiterhin wird er dazu benutzt, Ausgabegrößen, die kleiner sind als diese Cachegröße, beschleunigt zu berechnen.<br/>
    <br/>
    Zur Konfiguration sollte die am meisten benutzte maximale Monitorauflösung der Nutzer angegeben werden. In der 
    Properties-Datei $DocPortal/modules/module-iview/mycore.properties.iview im Bildbetrachter („MCR-IView“) sind die 
    beiden Werte als Pixel anzugeben:
    <p class="breaksource">  
    <source xml:space="preserve"><![CDATA[      
     
    MCR.Module-iview.cache.size.width=1280
    MCR.Module-iview.cache.size.height=1024
    ]]><![CDATA[
    ]]></source>
    </p>
    </li>
    <li>Originalgröße<br/>
    <br/>
    Dieser Cacheintrag speichert vom Originalbild ein gekacheltes TIFF in der Originalauflösung ab. Das ist nötig, wenn 
    Nutzer innerhalb von Bildern , wie zum Beispiel bei Landkarten, navigieren müssen.<br/>
    <br/>
    Durch diesen Cacheeintrag müssen beim Lesen von Ausschnitten aus Bildern, nur die Informationen der Ausschnitte 
    geladen werden und nicht mehr das gesamte Bild.<br/>
    <br/>
    Für Bilder die bereits im TIFF-Format vorliegen, wird kein eigener Cache erzeugt, sondern das Originalbild gekachelt 
    und überschrieben. Für alle Formate außer TIFF werden separate Cache-Einträge angelegt. <br/>
    <br/>
    In der Properties-Datei $DocPortal/modules/module-iview/mycore.properties.iview im Bildbetrachter („MCR-IView“) wird 
    dieser Wert angegeben.
    <p class="break"><code>MCR.Module-iview.cacheOrig=false|true</code></p>
    <note label="Hinweis">
    Beachten sie, dass dieser Cache-Eintrag das Repository stark vergrößern kann, wenn Sie Bilder nicht als TIFF 
    abspeichern. Nur wenn Sie wirklich innerhalb der Bilder navigieren möchten, sollte dieser Cache eingeschaltet 
    werden.</note>
    </li>
    </ol>
   </section>
   
   <section>
    <title>Module-IView - Bildbetrachter</title>
    <p class="fett">Allgemeines</p>
    <p>
    Das Modul-IView ist ein Anwendungsmodul von DocPortal und realisiert einen Bildbetrachter. Es basiert auf dem Modul 
    „Module-Imaging“ aus dem MyCoRe-Kern, nutzt dessen API.
    </p>
    <p>Es besteht im Wesentlichen aus einem Servlet, zwei XSL-Stylesheets und einer JavaScript-Bibliothek. Um den 
    Bildbetrachter in der Anwendung zu nutzen, muss der Web-Browser JavaScript interpretieren können.
    </p>
    <p class="fett">Funktionsweise</p>
    <p>Der Bildbetrachter wird über folgenden Mechanismus erzeugt.</p>
    <p><code>[ToDo: Graphik erstellen]</code></p>
    <p>
    Der Bildbetrachter wird über eine HTTP-Anfrage an das IView-Servlet initialisiert. Das IView-Servlet erstellt die 
    aktuelle Konfiguration für die Session und leitet diese als XML-Document an das Layout-Servlet weiter. Das 
    Layout-Servlet seinerseits generiert mithilfe XSL („mcr-module-iview.xsl“) HTML. Dieses HTML wird dann als Response 
    an den Web-Browser zurückgesendet und als Bildbetrachter dargestellt.</p><p class="fett">Integration
    </p>
    <p>
    Der Bildbetrachter-IView kann in XSL oder von einer MyCoRe-WebPage aufgerufen werden .
    </p>
    <p class="fett">XSL</p>
    <p>
    Iview kann in jedes XSL-Stylesheet eingebunden werden. Dazu muss lediglich im Kopf des entsprechenden Stylesheets 
    mcr-module-startIview.xsl eingebunden werden.
    </p>
    <p class="kasten">
    <code>&lt;include href="mcr-module-startIview.xsl" /&gt;</code>
    </p>
    <p>    Anschließend stehen die folgenden Templates zur Verfügung</p>
    <ol>
    <li>Test auf unterstützte Hauptdatei<br/>
    <br/>
    Das folgende Template überprüft, ob die Hauptdatei eines Derivates ein Bild ist, das mit Iview dargestellt werden 
    kann.
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    <xsl:call-template name="iview.getSupport"> 
      <xsl:with-param name="derivID" />
    </xsl:call-template>
    ]]>
    </p><![CDATA[
    ]]></source>
    Antwort:
    <ul>
    <li>leerer String =&gt; Hauptdatei wird nicht unterstützt</li>
    <li>String mit Wert =&gt; Hauptdatei wird unterstützt, Wert ist der absolute Pfad der Hauptdatei 
    (wird zum Aufruf des Viewers benötigt)</li>
    </ul>
    </li>
    <li>Aufruf des Bildbetrachters im eingebetteten Modus (wird als IFrame in eine HTML-Seite integriert)
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    <xsl:call-template name="iview">
         <xsl:with-param name="derivID" />
         <xsl:with-param name="pathOfImage" />
         <xsl:with-param name="height" />
         <xsl:with-param name="width" />
         <xsl:with-param name="scaleFactor" />
    
         <xsl:with-param name="display" />
         <xsl:with-param name="style" />
    </xsl:call-tenmplate>
    ]]>
    </p><![CDATA[
    ]]></source>
    Folgende Parameter sind zu übergeben:
    <ul><li>derivID = Derivate-ID</li>
        <li>pathOfImage = absoluter Pfad des Bildes oder Ordners</li>
        <li>height = Höhe des eingebetteten Fensters</li>
        <li>width = Breite des eingebetteten Fensters</li>
        <li>scaleFactor = Zoom
        <ul><li>0.1 ... 1.0</li>
            <li>„fitToWidth“ - an Breite angepasst</li>
            <li>„fitToScreen“ - an Seite angepasst</li>
        </ul>
        </li>
        <li>display = Ansicht des Viewers 
        <ul><li>„minimal“ = nur die Navigationsleiste (vor, zurück) wird eingeblendet</li>
            <li>„normal“ = die obere Menüleiste wird angezeigt</li>
            <li>„extended“ = obere und erweiterte Menüleiste werden eingeblendet</li>
        </ul>
        </li>
        <li>style = Modus, in der Bild angezeigt wird
        <ul><li>„thumbnail“ = Thumbnailübersicht </li>
            <li>„image“ = das eigentliche Bild </li>
            <li>„text“ = technische Metadatenansicht</li>
        </ul>
        </li>
    </ul>
    </li>
    <li>Ermitteln der Bildbetrachter-Adresse für den Vollbildmodus<br/>
    <br/>
    Der Bildbetrachter kann auch im Vollbildmodus aufgerufen werden. Das folgende Template ermittelt die Adresse dafür.
    <source xml:space="preserve"><![CDATA[
     
    <xsl:call-template name="iview.getAddress">
         <xsl:width-param name="derivID"/>
         <xsl:width-param name="pathOfImage"/>
         <xsl:width-param name="width"/>
         <xsl:width-param name="height"/>
         <xsl:width-param name="scaleFactor"/>
         <xsl:width-param name="display"/>
         <xsl:width-param name="style"/>
    </xsl:call-template>
    ]]><![CDATA[
    ]]></source>
    Die zu übergebenden Parameter sind identisch mit Punkt 2 – Aufruf im eingebetteten Modus.<br/>
    <br/>
    Antwort: Adresse des Bildbetrachters 
    </li>
    <li>Erzeugen eines Thumbnail<br/>
    <br/>
    Der Image-Viewer kann auch einfach dazu benutzt werden, Thumbnails von Bildern anzuzeigen. Durch den Aufruf des 
    folgenden Templates wird ein HTML-Image (&lt;img...&gt;) erzeugt, ohne den Viewer an sich.
    <source xml:space="preserve"><![CDATA[
     
    <xsl:call-template name="iview.getEmbedded.thumbnail" >
         <xsl:with-param name="derivID"/>
         <xsl:with-param name="pathOfImage"/>
    </xsl:call-template>
    ]]><![CDATA[
    ]]></source>
    Zu übergebende Parameter:
    <ul><li>derivID – Derivate-ID</li>
        <li>pathOfImage – absoluter Pfad des Bildes</li>
    </ul>
    Antwort:<br/>
    <br/>
    <code>&lt;img src="Adresse des Thumbnails" /&gt;</code>
    </li>
    </ol>
    <p class="fett">XML – MyCoRe-WebPage</p>
    <p>
    Statische Webseiten für DocPortal werden über XML-Dateien, sogenannte MyCoRe-WebPages generiert. Jede Webseite hat 
    eine XML-Seite, aus der sie generiert wird. Diese Webseiten können auch im WYSIWYG-Modus über das Module-WCMS 
    gepflegt werden. 
    </p>
    <p>
    In diese Webseiten, kann auch der Bildbetrachter Iview eingebunden werden. Folgender Aufruf ruft den Bildbetrachter 
    auf:
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    <iview
        @derivid 
        @pathofimage
        @height 
        @width 
        @scalefactor 
        @display 
        @style
    </iview>
    ]]>
    </p><![CDATA[
    ]]></source>
    <p>
    Die zu übergebenden Parameter sind identisch zum vorigen Punkt XSL, 2 – Aufruf im eingebetteten Modus.
    </p>
    <p class="fett">Konfiguration</p>
    <p>
    Die Konfiguration des Bildbetrachters wird über die Datei 
    $DOCPORTAL_HOME/modules/module-iview/config/mycore.properties.iview vorgenommen.
    </p>
    <p class="fett">Was soll angezeigt werden?</p>
    <p>
    Der Bildbetrachter kann grundsätzlich Dateien mit folgenden MIME-Types anzeigen: 
    </p>
    <p class="break"><code>jpeg,gif,tiff,tif,bmp,png,FlashPix,flashpix</code></p>
    <p>Über das Property </p>
    <p class="break"><code>MCR.Module-iview.SupportedContentTypes</code> </p>
    <p>
    kann gesteuert werden, welche Dateien Iview anzeigen soll. Es sind hier die MIME-Types, kommasepariert, anzugeben.
    </p>
    <p class="fett">Sortierung von Bildsammlungen</p>
    <p class="P26">Existieren mehrere Bilder in einem Derivat, kann die Sortierung voreingestellt werden. 
    Beim ersten Aufruf wird automatisch in der eingestellten Reihenfolge sortiert.
    </p>
    <p>Das dafür zuständige Property ist</p>
    <p class="break"><code>MCR.Module-iview.defaultSort</code> </p>
    <p>Mögliche Werte: </p>
    <ul>
    <li><code>name</code> – nach Dateiname</li>
    <li><code>size</code> – nach Dateigröße</li>
    <li><code>lastModified</code> – nach Datum der letzten Änderung</li>
    </ul>
    <p>Die Reihenfolge wird über das zweite Property eingestellt:</p>
    <p class="break"><code>MCR.Module-iview.defaultSort.order</code></p>
    <p>Werte: <code>ascending, descending</code></p>
    <p class="fett">Zoomstärke</p>
    <p>
    Die Veränderung des Zoomwertes beim Vergrößern und Verkleinern kann angepasst werden. Standardmäßig ist +-20% 
    eingestellt (das bedeutet am Beispiel: aktuell Zoomstufe=40% -&gt; Vergrößerung -&gt; Zoomstufe=60%).
    </p>
    <p>Das folgende Property steuert die Zoomstärke</p>
    <p class="break"><code>MCR.Module-iview.zoomDistance</code></p>
    <p>Werte: <code>0.1F</code> bis <code>1.0F</code></p>
    <p class="fett">Qualität des Bildes </p>
    <p>Bilder werden von IView immer als JPEG-Datei ausgegeben. Die Qualität der Bilder kann über den Kompressionsfaktor 
    geändert werden.</p>
    <p class="break"><code>MCR.Module-iview.jpegQuality</code></p>
    <p>Werte: <code>0.1</code> bis <code>1.0</code></p>
    <p class="fett">Cache</p>
    <p>
    Für die Nutzung des Bildbetrachters kann ein Cache zu Hilfe genommen werden. Leseoperationen auf Bildern werden 
    dadurch stark beschleunigt. 
    </p>
    <p>
    Die Nutzung des Cache kann ein- oder ausgeschaltet werden. Wenn der Cache ausgeschaltet ist, werden Lese- und 
    Schreiboperationen ohne Cache durchgeführt. 
    </p>
    <p>Das Property dafür ist </p>
    <p class="break"><code>MCR.Module-iview.useCache=true|false</code></p>
    <p>Weitere Informationen zur Konfiguration des Cache sind im Abschnitt Module-Imaging -&gt; Cache nachzulesen.</p>
   </section>
   
   <section>
     <title>Der Zoomify-Bildbetrachter</title>
     
     <p class="fett">Allgemein</p>
     <p>Die Firma Zoomify Inc. bietet einen Web-basierten Bildbetrachter an, der auf der Grundlage von gekachelten Bilder basiert
     und diese "on-demand" nachlädt. Innerhalb des Bildausschnitt kann stufenlos gezoomt werden.
     </p>
     
     <p class="fett">Grundlagen</p>
     <p>Um ein Bild über den Zoomify-Viewer anzeigen zu können, muss dieses zunächst aufbereitet werden. In Windows existiert dafür
     ein Midlet, in Linux kann ein Phyton-Skript genutzt werden. Bei der Datenaufbereitung werden Ausschnittbilder in verschiedenen
     Auflösungen erzeugt und in Ordnern abgelegt. Für das Zoomify-Servlet in MyCoRe kann der so entstandene Datenbestand in Zip-Archive
     verpackt werden (jedoch ohne Archiv-Kompression!). Somit wird das Handling extrem vereinfacht. Die Zip-Dateien werden dann als Derivat hochgeladen.
     </p>
         
     <p class="fett">Bilder anzeigen</p>
     <p>Für die Bildanzeige wird das Zoomify-Express-Plugin erwartet. Über das MCRStartZoomifyServlet wird die Anzeige der Bilder gesteuert.
       Zur Zeit findet sich eine adäquate Navigation wie beim IView zur Bildsteuerung im Servlet-Menü. Die Bilder werden über das  MCRZipFileNodeServlet
       automatisch an das Plugin übergeben. Die Anzeigereihenfolge wird über die Mets/Mods-Datei definiert und ist zwingend erforderlich (siehe dazu
       den Abschnitt über das Mets/Mods-Modul).
     </p>
     
     <p class="fett">Konfiguration</p>
     <p>In der mycore.properties-Datei kann über die folgende Variable der Titel des Bildes in Abhängigkeit des zugrunde gelegten Objektes
       angezeigt werden:    
     <p class="breaksource">  
     <source xml:space="preserve"><![CDATA[      
      
        MCR.Component.Zoomify.[type].identifier=[field of datamodel]]]><![CDATA[
     ]]><![CDATA[
     ]]></source>
     </p>
       Hierbei steht [type] für den Objekttyp und [field of datamodel] für ein verknüpftes Feld aus dem Datenmodell.
     </p>
   </section>   
    
  </section>
  
  <section>
    <title>Das Mets/Mods-Module</title>
    <section>
      <p class="fett">Allgemein</p>
      <p>
        Das Mets/Mods-Format ist ein Austauschformat in XML für mediale Inhalte. Besonders für die Darstellung von Bildern im DFG-Viewer
        wird das Format benötigt. Daneben nutzt der Zoomify-Bildbetrachter das Format als Reihenfolgenvorgabe bei Bilderserien.
      </p>
      <p class="fett">Mets/Mods-Dateien erzeugen</p>
      <p>
        Die Mets/Mods-Datei kann vom Derivat-Menü aus erzeugt werden und lässt sich via Java-Applet konfigurieren.
      </p>  
      <p class="fett">Modulkonfiguration</p>
      <p>
        Das Modul kann über folgende Properties konfiguriert werden:
        <table>
          <tr><td colspan="1" rowspan="1">
          MCR.Component.MetsMods.owner</td><td colspan="1" rowspan="1">Beschreibt den Eigentümer des Derivates</td>
          </tr>
          <tr><td colspan="1" rowspan="1">
          MCR.Component.MetsMods.ownerLogo</td><td colspan="1" rowspan="1">Beschreibt das Logo des Eigentümers</td>
          </tr>
          <tr><td colspan="1" rowspan="1">
          MCR.Component.MetsMods.ownerSiteURL</td><td colspan="1" rowspan="1">Beschreibt die URL des Eigentümers</td>
          </tr>
          <tr><td colspan="1" rowspan="1">
          MCR.Component.MetsMods.referenceURL</td><td colspan="1" rowspan="1">Beschreibt die Referenz-URL</td>
          </tr>
          <tr><td colspan="1" rowspan="1">
          MCR.Component.MetsMods.[type].title</td><td colspan="1" rowspan="1">Titel des Derivates in der Anzeige</td>
          </tr>
          <tr><td colspan="1" rowspan="1">
          MCR.Component.MetsMods.[type].display</td><td colspan="1" rowspan="1">Anzeige des Derivates</td>
          </tr>
          <tr><td colspan="1" rowspan="1">
          MCR.Component.MetsMods.[type].place</td><td colspan="1" rowspan="1">Ort des Derivates</td>
          </tr>
          <tr><td colspan="1" rowspan="1">
          MCR.Component.MetsMods.[type].date</td><td colspan="1" rowspan="1">Datierung des Derivates</td>
          </tr>
          <tr><td colspan="1" rowspan="1">
          MCR.Component.MetsMods.disallowed</td><td colspan="1" rowspan="1">Beschreibt die Endungen von Teilen in Derivaten, in denen keine Mets-Dateien gebaut werden dürfen.</td>
          </tr>
          <tr><td colspan="1" rowspan="1">
          MCR.Component.MetsMods.activated</td><td colspan="1" rowspan="1">Beschreibt die Attribute, die in der Mets-Datei hinzugefügt werden sollen. Voreinstellung: CONTENTIDS</td>
          </tr>
        </table>
      </p>
      
      <p class="fett">CommandLine-Befehle:</p>
      <table>
        <tr>
          <td colspan="1" rowspan="1">build mets files</td><td colspan="1" rowspan="1">Erstellt zu jedem im System befindlichen Derivat eine Mets-Datei.</td>
          </tr><tr>
          <td colspan="1" rowspan="1">build mets files for type {0}</td><td colspan="1" rowspan="1">Erstellt zu jedem Derivat, welches sich an einem Objekt vom Typ 'type' befindet, eine Mets-Datei.</td>
          </tr><tr>
          <td colspan="1" rowspan="1">build mets files for derivate {0}</td><td colspan="1" rowspan="1">Erstellt zu einem Derivat eine Mets-Datei.</td>
          </tr><tr>
          <td colspan="1" rowspan="1">build mets files for object {0}</td><td colspan="1" rowspan="1">Erstellt zu allen Derivaten eines Objekts eine Mets-Datei.</td>
          </tr><tr>
          <td colspan="1" rowspan="1">remove mets files</td><td colspan="1" rowspan="1">Löscht von jedem Derivat die Mets-Datei.</td>
          </tr><tr>
          <td colspan="1" rowspan="1">remove mets files for type {0}</td><td colspan="1" rowspan="1">Löscht von jedem Derivat, welches sich an einem Object vom Typ 'type' befindet, die Mets-Datei.</td>
          </tr><tr>
          <td colspan="1" rowspan="1">check mets files</td><td colspan="1" rowspan="1">Überprüft das Vorhandensein einer Mets-Datei in jedem Derivat.</td>
          </tr><tr>
          <td colspan="1" rowspan="1">check mets files for type {0} with exclude label {1}</td><td colspan="1" rowspan="1">Überprüft das Vorhandensein einer Mets-Datei an Derivaten, die an Objekte vom
           Typ 'type' gebunden sind, und die im Label einen Bezeichner besitzen, der <u>nicht</u> in {1} aufgeführt wurde.</td> 
          </tr><tr>
          <td colspan="1" rowspan="1">check mets files for type {0}</td><td colspan="1" rowspan="1">Überprüft das Vorhandensein einer Mets-Datei an Derivaten, die an Objekte vom
           Typ 'type' gebunden sind.</td>
          </tr><tr>
          <td colspan="1" rowspan="1">check mets files for Object {0} with exclude label {1}</td><td colspan="1" rowspan="1">Überprüft das Vorhandensein einer Mets-Datei an Derivaten, die an ein Objekt
           gebunden sind, und die im Label einen Bezeichner besitzen, der <u>nicht</u> in {1} aufgeführt wurde.</td>
          </tr><tr>
           <td colspan="1" rowspan="1">check mets files for Object {0}</td><td colspan="1" rowspan="1">Überprüft das Vorhandensein einer Mets-Datei an Derivaten, die an ein Objekt
           gebunden sind.</td>
          </tr><tr>
           <td colspan="1" rowspan="1">check mets files for Derivat {0}</td><td colspan="1" rowspan="1">Überprüft das Vorhandensein einer Mets-Datei an einem Derivat.</td>
         </tr>
        </table>
         
    </section>  
  </section>  
    
    
  <section>
   <title>Das Broadcasting-Module</title>
   
   <section>
    <title>Allgemeines</title>
    <p>
    Dieses Modul ergänzt die Anwendung um die Funktionalität einer Runtime-Anwenderinformation. Als berechtigter Nutzer 
    oder Administrator können Sie Nachrichten online generieren und versenden.
    </p>
   </section>
   
   <section>
    <title>Konfiguration</title>
    <p>
    In der konkreten Anwendung muss im Verzeichnis <em>modules</em> ein Unterverzeichnis <em>module-broadcasting</em> 
    angelegt werden. Hier muss sich eine <em>build.xml</em>-Datei mit folgenden Targets befinden:</p>
    <ul>
    <li>create.default-rules – Es werden die erforderlichen Rechteeinträge erzeugt.</li>
    <li>webapps – Der Modul wird in die Web-Applikation integriert.</li>
    </ul>
    <p>
    Die Nutzung des Modules in mehreren Anwendungen macht weiterhin die Existenz eines config-Verzeichnisses 
    erforderlich. Darin sind die Dateien <em>grant-broadcastinggroup.xml</em> und <em>mcr-module-broadcasting.xml</em> 
    abzulegen. Die Datei <em>grant-broadcastinggroup.xml</em> beschreibt die Gruppen und Nutzer, welche Nachrichten an 
    die Anwendung versenden dürfen. Im Beispiel sind das alle Mitglieder der Gruppe <strong>admingroup</strong>.
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
     <![CDATA[ 
    <?xml version="1.0" encoding="utf-8"?>
    <!-- this rule allways returns true -->
    <condition format="xml"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
       xsi:noNamespaceSchemaLocation="MCRCondition.xsd">
       <boolean operator="or">
         <condition value="admingroup" operator="=" field="group" />
       </boolean>
    </condition>
    ]]>
    </p><![CDATA[
    ]]></source>
    <p>
    Mit den folgenden MyCoRe-Kommandos werden die Rechte für die Nutzung des Modules eingetragen. Bei Nutzung des 
    ANT-Tagets <strong>create.default-rules</strong> erfolgt dies automatisch.
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    update permission manage for id module-broadcasting with rulefile grant-broadcastinggroup.xml
    
    update permission read for id webpage:/servlets/MCRBroadcastingServlet?mode=getReceiverList with rulefile grant-broadcastinggroup.xml 
    ]]>
    </p><![CDATA[
    ]]></source>
    <p>
    Die Grundkonfiguration zum Versenden der Nachrichten ist in der Datei <em>mcr-module-broadcasting.xml</em> 
    gespeichert. Sie stellt eine Voreinstellung dar, welche zum Ausführungszeitpunkt interaktiv verändert werden kann.
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <mcr-module-broadcasting>
       <!-- on | off -->
       <!-- on = client will autmatically listen for new messages by AJAX -->
       <!-- off client won't listen for new messages -->
       <power>on</power>
   
       <!-- Seconds, in which intervall the client will ask for new messages -->
       <refreshRate>60</refreshRate>
    
       <!-- true | false -->
       <!-- true = User will get the same message again, if a new session is opened, even though the user already received 
            the message. This should be used, if a user login will be used by more than one person -->
       <!-- false = Each user will get a message only on times, indepently on the session. -->
       <sessionSensitive>false</sessionSensitive>
    
       <message.header>Sehr geehrte Mitarbeiter</message.header>
       <message.tail>Ihr Administrator</message.tail>
       <!-- <group/> &| <user> -->
    
       <!-- allowGuestGroup ("true|false")  if set to true all "gast" users are listen on the channel, if "false" only 
            user != "gast" are listen -->
       <receivers allowGuestGroup="false"/>
    
       <!-- <from> & <to> (ISO 8601) are NOT supported yet, -> use @send -->
       <!-- @send = ever | never --><!-- ever = send continuasly -->
       <!-- never = do NOT send -->
       <onAirTime send="ever">
          <from>2006-10-20T10:17:42.920Z</from>
          <to>2006-10-20T10:17:42.920Z</to>
       </onAirTime>
    
    </mcr-module-broadcasting>
    ]]>
    </p><![CDATA[
    ]]></source>
    
    <p>    Einbinden in die Anwendung</p>
    <p>
    Der Aufruf des Broadcasting-Modules sollte aus der Navigation der Anwendung heraus erfolgen. Hierfür ist in der 
    navigation.xml folgender Eintrag zu tätigen.
    </p>
    <source xml:space="preserve"><![CDATA[
    ]]><p class="kastensource">  
    <![CDATA[ 
    <item 
       href="/servlets/MCRBroadcastingServlet?mode=getReceiverList"
       type="extern"
       target="_self"
       style="normal"
       replaceMenu="false"
       constrainPopUp="false">
         <label xml:lang="de">Nachrichten</label>
         <label xml:lang="en">Broadcasting</label>
    </item>
    ]]>
    </p><![CDATA[
    ]]></source>
    <p>Der Include der benötigten XSLT-Stylesheets erfolgt in der Datei generatePage.xsl.</p>
    <p class="kasten">&lt;xsl:include href="mcr-module-broadcasting.xsl" /&gt;</p>
    <p>
    Als letztes ist dafür zu sorgen, dass der Listener in alle Webseiten im HEAD-Bereich eingetragen wird. Dazu ist das 
    head-HTML-Tag um diese Zeile zu ergänzen.
    </p>
    <p class="kasten">&lt;xsl:call-template name="module-broadcasting.getHeader"/&gt;</p>
    <p>Informationen zu Benutzung des Modules finden Sie im MyCoRe User Guide.</p>
   </section>
 </section>
</section>
<section>
  <title>Anmerkungen und Hinweise</title>
  
  <section>
   <title>Ergänzung der DocPortal-Beispieldaten</title>
   <p>
   Mit Version 1.1 wurden die Beispieldaten für das DocPortal aus der Distribution des selbigen herausgelöst und in 
   eine separaten CVS-Baum untergebracht. Dies hat den Vorteil, dass
   </p>
   <ul>
   <li>die Installation des DocPortals nicht mehr von Beispieldaten abhängig ist,</li>
   <li>man nach der Installation ein leeres, betriebsbereites System hat,</li>
   <li>die Distribution des Samples schlanker und der Download damit schneller ist,</li>
   <li>mehr Beispiele in einer extra-CVS-Distribution angeboten werden können und</li>
   <li>die Beispiele gezielt geladen und auch wieder entfernt werden können.</li>
   </ul>
   <p>
   Die Beispieldaten stehen auf dem CVS-Server in Essen (server.mycore.de) in einem extra CVS-Baum mit dem Namen 
   <code>content</code> bereit. Dieser Enthält eine Sammlung einzelner Beispieldatengruppen. Nach dem checkout können 
   die Gruppen je nach Wunsch einzeln installiert werden (siehe UserGuide). Dabei spielt das jeweils mitgelieferte 
   <code>build.xml</code>-Skript eine wichtige Rolle, hier sind alle Funktionen zur Arbeit mit dem Beispiel definiert.
   </p>
   <p>
   Um neue Beispieldaten bereitzustellen gibt es zwei Wege: es wird eine Beispielgruppe mit Daten ergänzt oder es wird 
   einen neue Beispielgruppe aufgebaut.
   </p>
   
   <section>
    <title>Ergänzungen in einer Beispielgruppe</title>
    <p>Folgende Arbeiten sind erforderlich:</p>
    <ul>
    <li>Erzeugen der Metadaten für das Dokument (ggf. mit Daten für den Autor und/oder die Institution).</li>
    <li>Erzeugen des/der Derivate.</li>
    <li>Integration des Ladens und Entfernens im <code>build.xml-</code>Skript in den <code>target</code>-Abschnitten 
        <code>load</code> und <code>remove.</code>
    </li>
    </ul>
   </section>
   
   <section>
    <title>Hinzufügen einer neuen Beispielgruppe</title>
    
    <img src="images/content.png" alt="content" title="content"/>
    <p class="klein"><strong>Abbildung 4.1:</strong> Mindeststruktur einer Beispielgruppe</p>  
    
    <p>
    Hier sind mehr Schritte erforderlich. Dabei ist immer darauf zu achten, dass die Beispielgruppe in sich vollständig 
    ist, d. h. alle Autoren- und Institutionsdaten mitgeliefert werden. Da zum Laden der Daten das Update-Kommando 
    verwendet wird, ist sichergestellt, dass es keine Doppelung im System gibt. Verwenden Sie möglichst die schon 
    vorhandenen Autoren und Institutionen erneut.
    </p>
    <ul>
    <li>Checken Sie die content-Distribution aus.</li>
    <li>Erzeugen Sie ein neues Verzeichnis unter <span class="T1">content</span>, welches die Wurzel für Ihre 
    Beispielgruppe sein soll.</li>
    <li>Übernehmen Sie die Verzeichnisstruktur von einem bestehenden Beispiel und füllen Sie diese mit Ihren Daten.</li>
    <li>Kopieren Sie das build.xml-Skript von einem bestehenden Beispiel und adaptieren Sie es. Es muss mindestens die 
    targets <code>info</code>, <code>load</code> und <code>remove</code> beinhalten. Ggf. sind noch weitere targets zum 
    Kopieren von Stylesheets usw. nötig, hier müssen Sie das build.xml-File ergänzen.</li><li>Schreiben Sie ein kurzes 
    ReadMe-File im ASCII-Format mit Installationshinweisen.</li>
    <li>Testen Sie das fertige Beispiel.</li>
    <li>Commiten Sie alles in den CVS-Server.</li>
    </ul>
   </section>
  </section>
 </section>
</body>
</document>
