2019.06 2020.06

Die Korbfunktion (workbasket)

Beschreibung der Komponente zur integration einer Korbfunktion in die Anwendung

Allgemein

Das Paket org.mycore.frontend.basket implementiert eine Korbfunktion für MyCoRe Anwendungen. Ein Korb sammelt Verweise auf Objekte, z. B. Dokumente in einem Dokumentenserver oder Bilder, die zu einem Album zusammengefasst werden sollen. Das Paket enthält Klassen für den API-Zugriff auf die Korbfunktionen und ein Servlet, das die Weboberfläche implementiert.

Ein Eintrag im Korb besteht aus einer eindeutigen ID und einer URI. Die ID repräsentiert ein Objekt, das im Korb enthalten sein soll, z. B. die MCRObjectID. Die URI gibt eine Quelle für XML-Daten an, die das Objekt beschreiben. Ein XSL-Stylesheet kann diese URI auflösen, um die im Korb enthaltenen Objekte in der Weboberfläche darzustellen.

1
MCRBasketEntry entry = new MCRBasketEntry( "DocPortal_document_00774301", "mcrobject:DocPortal_document_00774301" );

Ein Korb wird zunächst in nicht persistenter Form in der Session des Benutzers im Speicher gehalten. Innerhalb einer Anwendung und einer Session könnte es verschiedene Körbe geben, die über ein Typattribut unterschieden werden können, z. B. einen Korb zu Sammeln von Dokumenten, einen anderen Korb für Verweise auf Bilddateien.

Beispiel (API):

1
2
3
4
       MCRBasketEntry entry = new MCRBasketEntry( "DocPortal_document_00774301", "mcrobject:DocPortal_document_00774301" );
       MCRBasket basket = MCRBasketManager.getOrCreateBasketInSession( "objects" );
       basket.add( entry );
     

Die Klasse Basket implementiert die Schnittstellen List<MCRBasketEntry> und Set<MCRBasketEntry>.
Das MCRBasketServlet implementiert die Weboberfläche der Korbfunktion.
Beispiel (Servlet):

  • den Inhalt des Korbs "objects" anzeigen
    1
    
    BasketServlet?type=objects&amp;action=show
  • einen Eintrag dem Korb hinzufügen
    1
    
    BasketServlet?type=objects&amp;action=add&amp;id=DocPortal_document_00774301&amp;uri=mcrobject:DocPortal_document_00774301
  • die Parameter id und uri sind wiederholbar, so dass in einem Durchgang gleich mehrere Objekte zum Korb hinzugefügt oder gelöscht werden können. Damit die korrekte Zuordnung beibehalten wird, sollten die Parameter aber nicht als GET (Query-String) sondern mittels POST (HTML-Formular) übertragen werden.
  • den Korb leeren
    1
    
    BasketServlet?type=objects&amp;action=clear

Die HTML-Ausgabe von BasketServlet wird durch das XSL Stylesheet basket-{TYP}.xsl generiert, im obigen Beispiel also basket-objects.xsl.

Reihenfolge der Einträge

Einträge im Korb werden in einer definierten Reihenfolge abgelegt, zunächst in der Reihenfolge des Einfügens in den Korb. Die Position der Einträge ist veränderbar, Einträge können auf und ab geschoben werden:

1
2
3
4
       basket.up( entry );
       basket.down( entry );
       basket.move( entry, 3 ); // move entry 3 positions down
      

bzw.

1
2
3
        BasketServlet?type=objects&amp;action=up&amp;id=DocPortal_document_00774301
        BasketServlet?type=objects&amp;action=down&amp;id=DocPortal_document_00774301
      

Ein Objekt kann nur einmal in einem Korb vorhanden sein (Set-Eigenschaft). Zum Vergleich von Einträgen wird die ID des Eintrages verwendet.

Entfernen von Objekten

1
2
3
4
       basket.remove( entry );
       basket.removeEntry( "DocPortal_document_00774301" );
       basket.remove( basket.get( "DocPortal_document_00774301" ) );
     

bzw.

1
BasketServlet?type=objects&amp;action=remove&amp;id=DocPortal_document_00774301

Kommentare

Einträge im Korb können kommentiert werden.

1
2
3
       entry.setComment( "Kommentar" );
       String comment = entry.getComment();
     

bzw.

1
BasketServlet?type=objects&amp;action=comment&amp;id=DocPortal_document_0077430

Der obige Aufruf erwartet als weitere Requestparameter die Ausgabe eines Editor-Formulars. In diesem Formular wird der Kommentar bearbeitet. DocPortal enthält hierfür kein Beispiel. Das Formular basket-edit.xml aus miless kann hier als Vorlage dienen.

Körbe speichern und laden

Ein Korb wird zunächst in nicht persistenter Form in der Session der Webanwendung gehalten und dort bearbeitet. Eine Anwendung kann Funktionen zur Speicherung eines Korbes bereitstellen. Beispielsweise könnten in einer Bilddatenbank einzelne Bildobjekte im Korb gesammelt werden und diese Kollektion dann als Album mit weiteren Metadaten persistent gespeichert werden. Die Kollektion kann hierbei beliebige Metadaten enthalten und durch einen MyCoRe Objekttyp implementiert werden. Die Inhalte des Korbs selbst, d.h. die enthaltenen Verweise auf Objekte, werden als XML in einer Derivat-Datei gespeichert.

Korb speichern

1
2
3
       MCRObjectID ownerID = MCRObjectID.getInstance( "ImagePortal_basket_01234567" );
       MCRBasketPersistence.createDerivateWithBasket(basket, ownerID);
     

bzw.

1
BasketServlet?type=objects&amp;action=create&amp;ownerID=ImagePortal_basket_01234567

erzeugt ein neues Derivat für das Metadaten-Objekt ImagePortal_basket_01234567, legt darin eine Datei basket.xml an und speichert die Verweise des Korbs "objects" darin.

Das Metadaten-Objekt, das die Inhalte des Korbs persistent aufnimmt, kann zuvor auf beliebige andere Weise erstellt werden, etwa über ein Formular, das wie bei jedem MyCoRe Objekt Metadaten zur Beschreibung der Kollektion aufnimmt. Ein Korb merkt sich, in welchem Derivat er gespeichert wurde:

1
String derivateID = basket.getDerivateID();

Korb erneut speichern

Ein Korb wird in der Session über das BasketServlet oder über die API bearbeitet. Nach Veränderung kann er erneut persistent gespeichert werden:

1
MCRBasketPersistence.updateBasket(basket);

bzw.

1
BasketServlet?type=objects&amp;action=update

Korb laden

Ein Korb kann aus der gespeicherten Form zur Anzeige und Bearbeitung in die Session geladen werden:

1
2
3
       MCRBasket basket = MCRBasketPersistence.retrieveBasket(derivateID);
       MCRBasketManager.setBasketInSession(basket);
     

bzw.

1
BasketServlet?action=retrieve&amp;derivateID=ImagePortal_derivate_12345678

Aufgelöstes XML oder beliebige weitere Metadaten im Korb

In der Regel wird ein Korb nur Referenzen auf andere Objekte enthalten. Für einige Anwendungsfälle kann es jedoch nützlich sein, direkt das aufgelöste XML der Objekt-Metadaten statt nur die URI-Referenz darauf im Korb zu halten. In miless können so beispielsweise Publikationen in einem Korb gesammelt werden, und deren Metadaten direkt im Korb für alle Einträge auf einmal geändert werden. Erst beim Speichern des Korbes werden diese Änderungen dann von miless persistent gemacht.

Um die URI-Referenz für neue Einträge direkt aufzulösen und das XML der enthaltenen Objekte im Korb abzulegen, sind folgende Aufrufe zu nutzen:

1
2
3
4
5
       MCRBasketEntry entry = new MCRBasketEntry( "DocPortal_document_00774301", "mcrobject:DocPortal_document_00774301" );
       entry.resolveContent();
       basket.add(entry);
       Element resolvedXML = entry.getContent();
     

bzw.

1
BasketServlet?type=objects&amp;action=add&amp;id=DocPortal_document_00774301&amp;uri=mcrobject:DocPortal_document_00774301&amp;resolve=true

Es liegt in der Verantwortung der Anwendung, diese Variante zu unterstützen.

XML-Darstellung

Die Klassen MCRBasketXMLBuilder und MCRBasketXMLExporter transformieren ein Korbobjekt und seine Einträge von/nach XML. Bei der Generierung einer XML-Darstellung der Korbinhalte kann gewählt werden, ob die XML-Metadaten der Objekte selbst auch enthalten sein sollen:

1
2
3
       boolean includeBasketEntryContent = false;
       Document xml = new MCRBasketXMLBuilder( includeBasketEntryContent ).buildXML(basket);
     

bzw.

1
MCRBasket basket = new MCRBasketXMLParser().parse( xml );

Wird der Inhalt eines Korbes in einer Derivat-Datei persistent gespeichert, werden stets nur die enthaltenen Referenzen, nicht aber das aufgelöste XML der Objekt-Metadaten gespeichert.
Beispiel:

1
2
3
4
5
6
7
8
 
       <basket type="objects" id="ImagePortal_derivate_12345678">
         <entry id="DocPortal_document_00774301" uri="mcrobject:DocPortal_document_00774301">
           <!-- Hier evtl. weitere aufgelöste XML-Metadaten des Objektes -->
           <comment>Kommentar</comment>
         </entry>
       </basket>