001/*
002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 */
020
021package org.nuxeo.ecm.webapp.context;
022
023import static org.jboss.seam.annotations.Install.FRAMEWORK;
024
025import java.io.Serializable;
026
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.jboss.seam.Component;
030import org.jboss.seam.ScopeType;
031import org.jboss.seam.annotations.In;
032import org.jboss.seam.annotations.Install;
033import org.jboss.seam.annotations.Name;
034import org.jboss.seam.annotations.Observer;
035import org.jboss.seam.annotations.Scope;
036import org.nuxeo.ecm.core.api.CoreSession;
037import org.nuxeo.ecm.core.api.DocumentModel;
038import org.nuxeo.ecm.core.api.DocumentNotFoundException;
039import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
040import org.nuxeo.ecm.platform.ui.web.api.WebActions;
041
042/**
043 * Seam Bean that is responsible from refetching the CurrentDocument in case it is Dirty (Transient modifications not
044 * pushed inside the DB).
045 * <p>
046 * This can happen if a low level Listener decides to RollBack the transaction.
047 * <p>
048 * In this case the DocumentModel won't be saved to the DB, but since the ApplyModelValue JSF phase has run, the
049 * DocumentModel will have been modified resulting in a Dirty state inside the Context.
050 * <p>
051 * We want to keep this dirty state as long as we stay on the same Tab, but as soon as we navigate somewhere else, we
052 * must reset the state.
053 *
054 * @author <a href="mailto:tdelprat@nuxeo.com">Tiry</a>
055 * @since 5.6
056 */
057@Name("transientStateCleaner")
058@Scope(ScopeType.EVENT)
059@Install(precedence = FRAMEWORK)
060public class TransientStateCleaner implements Serializable {
061
062    private static final long serialVersionUID = 1L;
063
064    @In(create = true, required = false)
065    protected transient NavigationContext navigationContext;
066
067    protected static final Log log = LogFactory.getLog(TransientStateCleaner.class);
068
069    @Observer(value = { WebActions.CURRENT_TAB_CHANGED_EVENT }, create = true)
070    public void flushTransientStateIfNeeded() {
071        DocumentModel currentDocument = navigationContext.getCurrentDocument();
072        if (currentDocument != null && currentDocument.isDirty()) {
073            CoreSession documentManager = (CoreSession) Component.getInstance("documentManager", false);
074            if (documentManager != null) {
075                try {
076                    // refetch
077                    currentDocument = documentManager.getDocument(currentDocument.getRef());
078                    // force refresh
079                    navigationContext.setCurrentDocument(null);
080                    navigationContext.setCurrentDocument(currentDocument);
081                } catch (DocumentNotFoundException e) {
082                    log.error("Error during reset of transient state", e);
083                }
084            }
085        }
086    }
087}