blob: 29d9df7c80aad415f36a68c850394b6d77fe2efa [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2008 Oracle Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Oracle Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.ui.internal.component;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IStructuredDocumentContextResolverFactory;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IWorkspaceContextResolver;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContext;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContextFactory;
import org.eclipse.jst.jsf.designtime.DTAppManagerUtil;
import org.eclipse.jst.jsf.designtime.DesignTimeApplicationManager;
import org.eclipse.jst.jsf.designtime.context.DTFacesContext;
import org.eclipse.jst.jsf.designtime.internal.view.DTUIViewRoot;
import org.eclipse.jst.jsf.designtime.internal.view.IDTViewHandler;
import org.eclipse.jst.jsf.designtime.internal.view.IViewRootHandle;
import org.eclipse.jst.jsf.designtime.internal.view.DTUIViewRoot.StalenessEvent;
import org.eclipse.jst.jsf.designtime.internal.view.DTUIViewRoot.StalenessListener;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
/**
* The top-level input model for a design time component tree
*
* @author cbateman
*
*/
/* package */class DTJSFViewModel
{
private final IStructuredDocument _document;
private final IProject _project;
private final IFile _file;
private final IStructuredDocumentContext _context;
private final AtomicBoolean _alreadyUpdating = new AtomicBoolean(
false);
private Runnable _runnable;
private final IViewRootHandle _viewRootHandle;
private StalenessListener _stalenessListener;
/**
* @param document
* @throws IllegalArgumentException
* if document cannot be used to initialize a component tree.
*/
public DTJSFViewModel(final IStructuredDocument document)
{
_document = document;
_context = IStructuredDocumentContextFactory.INSTANCE.getContext(
_document, -1);
final IWorkspaceContextResolver resolver = IStructuredDocumentContextResolverFactory.INSTANCE
.getWorkspaceContextResolver(_context);
if (resolver == null)
{
throw new IllegalArgumentException();
}
_project = resolver.getProject();
_file = (IFile) resolver.getResource();
if (_project == null || _file == null)
{
throw new IllegalArgumentException();
}
final DTFacesContext facesContext = getFacesContext();
_viewRootHandle = facesContext.getViewRootHandle();
}
/**
* Acquire and initialize the component tree root for the document
*
* @param runnable
*/
public void init(final Runnable runnable)
{
_runnable = runnable;
_viewRootHandle.addListener(getOrCreateListener());
}
public void dispose()
{
if (_stalenessListener != null)
{
_viewRootHandle.removeListener(_stalenessListener);
}
synchronized(this)
{
_runnable = null;
}
}
/**
* @return the structured document that this view model was created for.
*/
public final IStructuredDocument getDocument()
{
return _document;
}
public final IProject getProject()
{
return _project;
}
public final IFile getFile()
{
return _file;
}
public final String getViewId()
{
final DTFacesContext facesContext = getFacesContext();
final IDTViewHandler viewHandler = DTAppManagerUtil
.getViewHandler(_project);
if (facesContext != null && viewHandler != null)
{
return viewHandler.getViewId(facesContext, _file);
}
return null;
}
private DTFacesContext getFacesContext()
{
final DesignTimeApplicationManager manager = DesignTimeApplicationManager
.getInstance(_project);
if (manager != null)
{
return manager.getFacesContext(_file);
}
return null;
}
public void update()
{
final DTFacesContext facesContext = getFacesContext();
if (facesContext != null)
{
// latch the alreadyRunning flag; job will unset to false
if (_alreadyUpdating.compareAndSet(false, true))
{
final Job job = new UpdateRootAndRefreshJob(_viewRootHandle);
job.addJobChangeListener(new JobChangeAdapter()
{
@Override
public void done(final IJobChangeEvent event)
{
// always reset the updating flag
_alreadyUpdating.set(false);
if (event.getResult().isOK())
{
synchronized(DTJSFViewModel.this)
{
if (_runnable != null)
{
_runnable.run();
}
}
}
}
});
job.schedule();
}
}
}
/**
* @return the design time view root or null
*/
public DTUIViewRoot getRoot()
{
final DTFacesContext facesContext = getFacesContext();
if (facesContext != null)
{
final DTUIViewRoot viewRoot = _viewRootHandle.getCachedViewRoot();
// if our copy is uninit or null, kick off an update
if (viewRoot == null || viewRoot.isStale())
{
update();
}
return viewRoot;
}
return null;
}
private StalenessListener getOrCreateListener()
{
if (_stalenessListener == null)
{
_stalenessListener = new StalenessListener()
{
@Override
protected void stalenessChanged(StalenessEvent event)
{
switch (event.getChangeType())
{
case VIEW_DEFN_CHANGED:
case PROJECT_CLEANED:
{
update();
}
case VIEW_DEFN_DELETED:
case VIEW_DEFN_PROJECT_CLOSED:
{
DTUIViewRoot root = _viewRootHandle
.getCachedViewRoot();
if (root != null)
{
root.removeListener(_stalenessListener);
}
}
}
}
};
}
return _stalenessListener;
}
private static class UpdateRootAndRefreshJob extends Job
{
private final IViewRootHandle _viewRootHandle;
public UpdateRootAndRefreshJob(final IViewRootHandle viewRootHandle)
{
super(Messages.DTJSFViewModel_JobDesc);
_viewRootHandle = viewRootHandle;
}
@Override
protected IStatus run(final IProgressMonitor monitor)
{
_viewRootHandle.updateViewRoot();
return Status.OK_STATUS;
}
}
}