/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.navigator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.ui.texteditor.MarkerUtilities;
import org.python.pydev.core.IInterpreterInfo;
import org.python.pydev.core.PythonNatureWithoutProjectException;
import org.python.pydev.core.bundle.ImageCache;
import org.python.pydev.core.log.Log;
import org.python.pydev.navigator.elements.ProjectConfigError;
import org.python.pydev.navigator.elements.PythonSourceFolder;
import org.python.pydev.plugin.PydevPlugin;
import org.python.pydev.plugin.nature.PythonNature;
import org.python.pydev.ui.UIConstants;
import com.aptana.shared_core.structure.Tuple;
/**
* This class contains information about the project (info we need to show in the tree).
*/
public class ProjectInfoForPackageExplorer {
/**
* Note that the source folders are added/removed lazily (not when the info is recreated)
*/
public final Set<PythonSourceFolder> sourceFolders = new HashSet<PythonSourceFolder>();
/**
* Whenever the info is recreated this is also recreated.
*/
public final List<ProjectConfigError> configErrors = new ArrayList<ProjectConfigError>();
/**
* The interpreter info available (may be null)
*/
public IInterpreterInfo interpreterInfo;
/**
* Cache for the interpreter info tree root (so, if asked more than once this one will be reused).
*/
private InterpreterInfoTreeNodeRoot<LabelAndImage> interpreterInfoTreeRoot;
/**
* Creates the info for the passed project.
*/
public ProjectInfoForPackageExplorer(IProject project) {
this.recreateInfo(project);
}
/**
* Recreates the information about the project.
*/
public void recreateInfo(IProject project) {
interpreterInfoTreeRoot = null;
configErrors.clear();
Tuple<List<ProjectConfigError>, IInterpreterInfo> configErrorsAndInfo = getConfigErrorsAndInfo(project);
configErrors.addAll(configErrorsAndInfo.o1);
this.interpreterInfo = configErrorsAndInfo.o2;
}
public synchronized InterpreterInfoTreeNodeRoot<LabelAndImage> getProjectInfoTreeStructure(IProject project,
Object parent) {
if (parent == null || this.interpreterInfo == null) {
return null;
}
PythonNature nature = PythonNature.getPythonNature(project);
if (interpreterInfoTreeRoot != null) {
if (interpreterInfoTreeRoot.getParent().equals(parent)
&& interpreterInfoTreeRoot.interpreterInfo.equals(interpreterInfo)) {
return interpreterInfoTreeRoot;
}
}
interpreterInfoTreeRoot = null;
try {
ImageCache imageCache = PydevPlugin.getImageCache();
//The root will create its children automatically.
interpreterInfoTreeRoot = new InterpreterInfoTreeNodeRoot<LabelAndImage>(interpreterInfo, nature, parent,
new LabelAndImage(interpreterInfo.getNameForUI(), imageCache.get(UIConstants.PY_INTERPRETER_ICON)));
} catch (Throwable e) {
Log.log(e);
return null;
}
return interpreterInfoTreeRoot;
}
/**
* Never returns null.
*
* This method should only be called through recreateInfo.
*/
@SuppressWarnings("unchecked")
private Tuple<List<ProjectConfigError>, IInterpreterInfo> getConfigErrorsAndInfo(IProject project) {
if (project == null || !project.isOpen()) {
return new Tuple<List<ProjectConfigError>, IInterpreterInfo>(new ArrayList(), null);
}
PythonNature nature = PythonNature.getPythonNature(project);
if (nature == null) {
return new Tuple<List<ProjectConfigError>, IInterpreterInfo>(new ArrayList(), null);
}
//If the info is not readily available, we try to get some more times... after that, if still not available,
//we just return as if it's all OK.
Tuple<List<ProjectConfigError>, IInterpreterInfo> configErrorsAndInfo = null;
boolean goodToGo = false;
for (int i = 0; i < 10 && !goodToGo; i++) {
try {
configErrorsAndInfo = nature.getConfigErrorsAndInfo(project);
goodToGo = true;
} catch (PythonNatureWithoutProjectException e1) {
goodToGo = false;
synchronized (this) {
try {
wait(100);
} catch (InterruptedException e) {
}
}
}
}
if (configErrorsAndInfo == null) {
return new Tuple<List<ProjectConfigError>, IInterpreterInfo>(new ArrayList(), null);
}
if (nature != null) {
try {
project.deleteMarkers(PythonBaseModelProvider.PYDEV_PACKAGE_EXPORER_PROBLEM_MARKER, true, 0);
} catch (Exception e) {
Log.log(e);
}
List<ProjectConfigError> errors = configErrorsAndInfo.o1;
for (ProjectConfigError error : errors) {
try {
Map attributes = new HashMap();
attributes.put(IMarker.MESSAGE, error.getLabel());
attributes.put(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
MarkerUtilities.createMarker(project, attributes,
PythonBaseModelProvider.PYDEV_PACKAGE_EXPORER_PROBLEM_MARKER);
} catch (Exception e) {
Log.log(e);
}
}
}
return configErrorsAndInfo;
}
}