Zwischenspeichern von Annotationen im jadice web toolkit

Gültig in jadice web toolkit 5.x

Dieser Artikel beschreibt einen Workaround zum Zwischenspeichern von Annotationen. 

Problemstellung/Anwendungsfall

Nach dem Speichern von Änderungen an Annotationen soll mit demselben Dokument weitergearbeitet werden.

Lösung

Grundsätzlich empfehlen wir ein "spätes Speichern" der Annotationen, also als letzte Aktion vor dem Schließen des Dokuments, da das jadice web toolkit bisher keine Synchronisation von inkrementellen Änderungen zwischen Server und Client unterstützt. Im Idealfall sollte also ein erneuter, vollständiger Ladevorgang von Dokument + Annotationen durchgeführt werden, um einen konsistenten Zustand des Dokuments und der zugehörigen Anntationen auf Server und Client sicherzustellen.

In manchen Umgebungen ist jedoch das Laden von Dokumenten eine ressourcen- und zeitaufwendige Angelegenheit, so dass es höchst wünschenswert ist, mit demselben Dokument nach dem Zwischenspeichern der Annotationen weiterzuarbeiten.

In diesem Fall lässt sich der nachfolgend beschriebene Workaround einsetzen. 


Workaround

Die Annotations-API im jadice web toolkit sieht normalerweise nicht vor, dass Annotationen nach dem Speichern direkt weiter bearbeitet werden. Korrekterweise müssten also die Annotationen nach einem Speichervorgang neu geladen werden. Um das Neuladen zu umgehen, kann es simuliert werden, indem im Nachhinein die zwischengespeicherten Annotationen zurückgesetzt und ihnen entsprechende User-Properties gesetzt werden.

Beim Speichern von Annotationen muss hierzu auf Clientseite (z.B. in einem SaveAnnotationCommand) nach dem erfolgreichen Speichervorgang für jede neue oder veränderte Annotation das modified-Flag zurückgesetzt werden.

annotation.clearModified();


Neuen Annotationen müssen folgende Properties gesetzt werden, um ein korrektes Verhalten zu gewährleisten:

annotation.getProperties().put(AnnotationPropertyConstants.ANNOTATION_INITIAL, Boolean.TRUE.toString());
annotation.getProperties().put(AnnotationPropertyConstants.ANNOTATION_DESCRIPTION, "archivspezifische Annotationsbeschreibung");

Die Property AnnotationPropertyConstants.ANNOTATION_DESCRIPTION sollte dem verwendeten Annotationsformat entsprechen. 

Hintergrundinformationen dazu:

  • Annotationen, die aus dem Archiv geladen werden, besitzen die User-Properties AnnotationPropertyConstants.ANNOTATION_INITIAL und AnnotationPropertyConstants.ANNOTATION_DESCRIPTION
  • Neu angebrachte Annotationen - auch wenn sie integrationsseitig bereits gespeichert wurden - besitzen diese Properties nicht.
  • Beim Löschen von Annotationen werden clientseitig der Liste deletedAnnotations nur Annotationen mit der Property ANNOTATION_INITIAL hinzugefügt und in der ServerOperation an den Server übertragen.
Beispiel einer Server Operation zum Speichern von Annotationen
/**
 * Stores the annotations and resets their state.
 */
public class SaveAnnoServerOperationCommand extends AbstractServerOperationCommand {
  
  private Observer<SaveAnnoServerOperationMessage> observer;

  public SaveAnnoServerOperationCommand() {
    this.observer = new ObserverImpl();
  }

  private class ObserverImpl implements Observer<SaveAnnoChangePermissionsServerOperationMessage> {
    @Override
    public void onNext(SaveAnnoServerOperationMessage message) {
      // nothing to do
    }

    @Override
    public void onCompleted() {
      Document doc = getPageView().getDocument();
      for (Page page : doc.getPages()) {
        AnnotationPageSegment aps = (AnnotationPageSegment) page.getPageSegment(DocumentLayer.ANNOTATIONS);
        if (null != aps) {
          List<Annotation> annotations = aps.getAnnotations();
          for (Annotation annotation : annotations) {
            if (annotation.isModified()) {
              if (!isLoadedAnnotaion(annotation)) {
				annotation.getProperties().put(AnnotationPropertyConstants.ANNOTATION_INITIAL, Boolean.TRUE.toString());
                // Set the following property dependent on the annotation format that you save into your archive.
                // Here we assume that the annotations are saved in IBM CM7 format.
                // Supported values are
                // CMAnnotationConstants.ANNOTATION_FORMAT_DESCRIPTION_CM7
                // CMAnnotationConstants.ANNOTATION_FORMAT_DESCRIPTION_CM8
                // FNP8AnnotationConstants.ANNOTATION_FORMAT_DESCRIPTION - further actions required to propagate unique ID and timestamps
                // FNISAnnotationConstants.ANNOTATION_FORMAT_DESCRIPTION
                annotation.getProperties().put(AnnotationPropertyConstants.ANNOTATION_DESCRIPTION, CMAnnotationConstants.ANNOTATION_FORMAT_DESCRIPTION_CM7);
              }
              annotation.clearModified();
            }
          }
        }
      }
    }
 
	/**
	* Returns true if the AnnotationPropertyConstants.ANNOTATION_INITIAL flag is set to true
	**/
	private boolean isLoadedAnnotation(Annotation annotation) {
      try {
        return Boolean.valueOf(
            annotation.getProperties().get(AnnotationPropertyConstants.ANNOTATION_INITIAL).toString()).booleanValue();
   	  } catch (final Exception e) {
        return false;
      }
  	}

    @Override
    public void onError(final Throwable e) {
      NotificationEventBus.Instance.get().fireEvent(
          new InfoNotifcationEvent("Error invoking ServerOperation", "Message: " + e.getMessage()));
    }
  }

  /**
   * Start a new ServerOperation. The answers from the server will be processed by the observer.
   */
  @Override
  protected void execute() {
    SaveAnnoServerOperationParameters params = new SaveAnnoServerOperationParameters();
    invoke(params, observer);
  }
}