All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dellroad.stuff.pobj.vaadin.PersistentObjectContainerLoader Maven / Gradle / Ivy


/*
 * Copyright (C) 2012 Archie L. Cobbs. All rights reserved.
 */

package org.dellroad.stuff.pobj.vaadin;

import com.vaadin.server.VaadinSession;

import org.dellroad.stuff.pobj.PersistentObject;
import org.dellroad.stuff.vaadin7.AbstractSimpleContainer;

/**
 * Facilitates populating a {@link AbstractSimpleContainer} with data from {@link PersistentObject}
 * and automatically updating it when that {@link PersistentObject} changes.
 *
 * 

* The constructor requires a {@link Generator} to generate, from the {@link PersistentObject} * root object, the Java objects that populate the {@link AbstractSimpleContainer}. * *

* Note: Instances of this class start out in a non-listening state. You must invoke {@link #connect connect()} * to start listening to the {@link PersistentObject} and (re)load the container contents. * You should invoke {@link #disconnect} whenever the container is no longer used to avoid a memory leak. * Typically, {@link #connect connect()} and {@link #disconnect} are invoked from the * {@link com.vaadin.ui.Component#attach attach()} and {@link com.vaadin.ui.Component#detach detach()} methods (respectively) * of the GUI widget that is using the container. * * @param type of the persistent object * @param the type of the Java objects that back each {@link com.vaadin.data.Item} in the container */ @SuppressWarnings("serial") public class PersistentObjectContainerLoader { private final AbstractSimpleContainer container; private final Generator generator; private VaadinPersistentObjectListener listener; /** * Constructor. * * @param container container to populate * @param generator object that generates the Java objects that back the {@link com.vaadin.data.Item}s in the container * @throws IllegalArgumentException if {@code container} is null * @throws IllegalArgumentException if {@code generator} is null */ public PersistentObjectContainerLoader(AbstractSimpleContainer container, Generator generator) { if (container == null) throw new IllegalArgumentException("null container"); if (generator == null) throw new IllegalArgumentException("null generator"); this.container = container; this.generator = generator; } /** * Register this container as a listener on the persistent object and load the container. * This method may only be invoked while the {@link VaadinSession} is locked by the current thread. * If this method is invoked twice with no intervening {@link #disconnect}, this instance will * automatically disconnect from the old {@link PersistentObject} before connecting to the new one. * * @param persistentObject persistent object database * @throws IllegalArgumentException if {@code persistentObject} is null * @throws IllegalStateException if there is no {@link VaadinSession} associated with the current thread */ public void connect(PersistentObject persistentObject) { // Sanity check this.assertSession(); if (persistentObject == null) throw new IllegalArgumentException("null persistentObject"); // Connect boolean needReload = false; T root = null; synchronized (this) { if (this.listener != null) this.listener.unregister(); this.listener = new VaadinPersistentObjectListener(persistentObject) { @Override protected void handlePersistentObjectChange(T oldRoot, T newRoot, long version) { PersistentObjectContainerLoader.this.reload(newRoot); } }; this.listener.register(); root = persistentObject.getSharedRoot(); needReload = true; } // Load container if there is data if (needReload) this.reload(root); } /** * Shutdown this container. This unregisters the container from the {@link PersistentObject} it was previously * {@linkplain #connect connected} to. This method may be invoked from any thread and is idempotent. * The associated container is not notified about any change. * * @throws IllegalStateException if there is no {@link VaadinSession} associated with the current thread */ public synchronized void disconnect() { this.assertSession(); if (this.listener != null) { this.listener.unregister(); this.listener = null; } } /** * Reload the container associated with this instance using the given {@link PersistentObject} root. * * @param root root object from which to derive container content * @throws IllegalStateException if there is no {@link VaadinSession} associated with the current thread */ protected void reload(T root) { this.assertSession(); this.container.load(this.generator.generateContainerObjects(root)); } /** * Verify there is a {@link VaadinSession} associated with the current thread. * * @throws IllegalStateException if there is no {@link VaadinSession} associated with the current thread */ protected void assertSession() { if (VaadinSession.getCurrent() == null) throw new IllegalStateException("there is no VaadinSession associated with the current thread"); } // Generator /** * Interface used by {@link PersistentObjectContainerLoader} to derive {@link AbstractSimpleContainer} backing * objects from a {@link PersistentObject} root. * * @param type of the persistent object * @param the type of the Java objects that back each {@link com.vaadin.data.Item} in the {@link AbstractSimpleContainer} */ public interface Generator { /** * Generate the Java objects that will back the {@link AbstractSimpleContainer} associated with * a {@link PersistentObjectContainerLoader} from the given {@link PersistentObject} root. * *

* This method should not modify {@code root}. * *

* If the associated {@link PersistentObject} allows empty starts or stops, then {@code root} might be null. * * @param root updated persistent object root, or null in the case of an empty start or stop * @return container backing objects */ Iterable generateContainerObjects(T root); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy