/*****************************************************************************
* Copyright (c) 2011 Atos Origin Integration.
*
* 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:
* Tristan Faure (Atos Origin Integration) tristan.faure@atosorigin.com - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.infra.onefile.providers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.security.auth.kerberos.KerberosKey;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.papyrus.infra.core.Activator;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.resource.ModelMultiException;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.resource.uml.UmlModel;
import org.eclipse.papyrus.infra.core.resource.uml.UmlUtils;
import org.eclipse.papyrus.infra.core.services.ExtensionServicesRegistry;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.onefile.matcher.OnlyDiFilter;
import org.eclipse.papyrus.infra.onefile.model.IPapyrusFile;
import org.eclipse.papyrus.infra.onefile.model.PapyrusModelHelper;
import org.eclipse.papyrus.infra.onefile.utils.OneFileUtils;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.navigator.CommonViewer;
/**
* Content provider able to retrieve Papyrus children from an {@link IContainer}
*
* @author Tristan FAURE
*
*/
public class PapyrusContentProvider extends WorkbenchContentProvider {
private CommonViewer common;
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
super.inputChanged(viewer, oldInput, newInput);
if(viewer instanceof CommonViewer) {
common = (CommonViewer)viewer;
}
}
/**
* Determine if the current navigator is filtered or not
*
* @return true if the viewer is filtered
*/
public boolean isFiltered() {
return common != null && common.getNavigatorContentService() != null && common.getNavigatorContentService().getFilterService() != null && common.getNavigatorContentService().getFilterService().isActive(OnlyDiFilter.FILTER_ID);
}
@Override
public void dispose() {
super.dispose();
}
public Object[] getElements(Object inputElement) {
if(inputElement instanceof IWorkspaceRoot) {
return null;
}
List<Object> result = new LinkedList<Object>();
try {
if(isFiltered()) {
if(inputElement instanceof IPapyrusFile) {
IPapyrusFile file = (IPapyrusFile)inputElement;
for(IResource r : file.getAssociatedResources()) {
result.add(PapyrusModelHelper.getPapyrusModelFactory().createISubResourceFile(file, (IFile)r));
}
} else {
IResource[] members = null;
if(inputElement instanceof IContainer) {
members = ((IContainer)inputElement).members();
}
if(members != null) {
for(IResource r : members) {
if(r instanceof IContainer && !(r instanceof IProject)) {
IContainer cont = (IContainer)r;
result.add(cont);
} else if(r instanceof IFile) {
if(OneFileUtils.isDi(r)) {
IPapyrusFile createIPapyrusFile = PapyrusModelHelper.getPapyrusModelFactory().createIPapyrusFile((IFile)r);
result.add(createIPapyrusFile);
} else {
if(!OneFileUtils.diExists(r.getName(), r.getParent())) {
result.add(r);
}
}
} else {
result.add(r);
}
}
}
}
}
} catch (CoreException e) {
}
return result.isEmpty() ? null : result.toArray();
}
public Object[] getChildren(Object inputElement) {
return getElements(inputElement);
}
public Object getParent(Object element) {
if(element instanceof IPapyrusFile) {
IPapyrusFile papyFile = (IPapyrusFile)element;
return papyFile.getParent();
}
return null;
}
public boolean hasChildren(Object element) {
return OneFileUtils.hasChildren(element);
}
@Override
protected void processDelta(IResourceDelta delta) {
super.processDelta(delta);
if(!isFiltered()) {
return;
}
Control ctrl = common.getControl();
if(ctrl == null || ctrl.isDisposed()) {
return;
}
final Collection<Runnable> runnables = new ArrayList<Runnable>();
processPapyrusDelta(delta, runnables);
if(runnables.isEmpty()) {
return;
}
//Are we in the UIThread? If so spin it until we are done
ctrl.getDisplay().asyncExec(new Runnable() {
/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public void run() {
//Abort if this happens after disposes
Control ctrl = common.getControl();
if(ctrl == null || ctrl.isDisposed()) {
return;
}
runUpdates(runnables);
}
});
}
private void runUpdates(Collection<?> runnables) {
Iterator<?> runnableIterator = runnables.iterator();
while(runnableIterator.hasNext()) {
((Runnable)runnableIterator.next()).run();
}
}
protected void processPapyrusDelta(IResourceDelta delta, Collection<Runnable> runnables) {
IResourceDelta[] affectedChildren = delta.getAffectedChildren(IResourceDelta.CHANGED);
// Handle changed children .
for(int i = 0; i < affectedChildren.length; i++) {
processPapyrusDelta(affectedChildren[i], runnables);
}
IResourceDelta[] addedChildren = delta.getAffectedChildren(IResourceDelta.ADDED);
final Object[] addedObjects;
// Process additions before removals as to not cause selection
// preservation prior to new objects being added
// Handle added children. Issue one update for all insertions.
if(addedChildren.length > 0) {
addedObjects = new Object[addedChildren.length];
for(int i = 0; i < addedChildren.length; i++) {
addedObjects[i] = addedChildren[i].getResource();
}
} else {
addedObjects = new Object[0];
}
// Handle removed children. Issue one update for all removals.
// heuristic test for items moving within same folder (i.e. renames)
Runnable addAndRemove = new Runnable() {
public void run() {
if(common instanceof AbstractTreeViewer) {
AbstractTreeViewer treeViewer = (AbstractTreeViewer)common;
// Disable redraw until the operation is finished so we don't
// get a flash of both the new and old item (in the case of
// rename)
// Only do this if we're both adding and removing files (the
// rename case)
try {
// need to handle resource addition
if(addedObjects.length > 0) {
ArrayList<IPapyrusFile> elements = new ArrayList<IPapyrusFile>(addedObjects.length);
ArrayList<IPapyrusFile> toAdd = new ArrayList<IPapyrusFile>(addedObjects.length);
for(Object r : addedObjects) {
if(r instanceof IResource) {
IResource current = (IResource)r;
if(OneFileUtils.diExists(current.getName(), current.getParent())) {
elements.add(PapyrusModelHelper.getPapyrusModelFactory().createIPapyrusFile(OneFileUtils.getDi(current.getName(), current.getParent())));
}
if(OneFileUtils.isDi(current)) {
toAdd.add(PapyrusModelHelper.getPapyrusModelFactory().createIPapyrusFile((IFile)current));
}
}
}
for(Object o : elements) {
common.refresh(o);
}
for(IPapyrusFile o : toAdd) {
common.add(o.getParent(), o);
}
}
} finally {
}
}
}
};
runnables.add(addAndRemove);
}
// @Override
// protected ITreeContentProvider getDelegateContentProvider() {
// if(provider == null) {
// provider = new WorkbenchContentProvider();
// }
// return provider;
// }
//
// @Override
// protected String getModelProviderId() {
// return OneFileModelProvider.MODEL_PROVIDER_ID;
// }
//
// @Override
// protected Object getModelRoot() {
// return null;
// }
// @Override
// protected ResourceTraversal[] getTraversals(ISynchronizationContext context, Object object) {
// return null;
// }
}