/*******************************************************************************
* Copyright (c) 2007 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.seam.internal.core;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IType;
import org.eclipse.jst.jsf.designtime.DesignTimeApplicationManager;
import org.jboss.tools.common.model.project.ext.event.Change;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.common.util.UniquePaths;
import org.jboss.tools.common.validation.internal.ProjectValidationContext;
import org.jboss.tools.common.xml.XMLUtilities;
import org.jboss.tools.seam.core.BijectedAttributeType;
import org.jboss.tools.seam.core.IBijectedAttribute;
import org.jboss.tools.seam.core.ISeamComponent;
import org.jboss.tools.seam.core.ISeamComponentDeclaration;
import org.jboss.tools.seam.core.ISeamContextShortVariable;
import org.jboss.tools.seam.core.ISeamContextVariable;
import org.jboss.tools.seam.core.ISeamFactory;
import org.jboss.tools.seam.core.ISeamJavaComponentDeclaration;
import org.jboss.tools.seam.core.ISeamNamespace;
import org.jboss.tools.seam.core.ISeamPackage;
import org.jboss.tools.seam.core.ISeamProject;
import org.jboss.tools.seam.core.ISeamScope;
import org.jboss.tools.seam.core.ISeamXmlComponentDeclaration;
import org.jboss.tools.seam.core.ScopeType;
import org.jboss.tools.seam.core.SeamCoreBuilder;
import org.jboss.tools.seam.core.SeamCorePlugin;
import org.jboss.tools.seam.core.event.ISeamProjectChangeListener;
import org.jboss.tools.seam.core.event.SeamProjectChangeEvent;
import org.jboss.tools.seam.core.project.facet.SeamRuntime;
import org.jboss.tools.seam.core.project.facet.SeamRuntimeManager;
import org.jboss.tools.seam.internal.core.el.VariableResolver;
import org.jboss.tools.seam.internal.core.project.facet.ISeamFacetDataModelProperties;
import org.jboss.tools.seam.internal.core.scanner.LoadedDeclarations;
import org.jboss.tools.seam.internal.core.scanner.lib.ClassPath;
import org.osgi.service.prefs.BackingStoreException;
import org.w3c.dom.Element;
/**
* @author Viacheslav Kabanovich
*/
public class SeamProject extends SeamObject implements ISeamProject, IProjectNature {
IProject project;
ClassPath classPath = new ClassPath(this);
// boolean useDefaultRuntime = false;
Set<IPath> sourcePaths = new HashSet<IPath>();
Map<IPath, LoadedDeclarations> sourcePaths2 = new HashMap<IPath, LoadedDeclarations>();
private boolean isStorageResolved = false;
SeamScope[] scopes = new SeamScope[ScopeType.values().length];
Map<ScopeType, SeamScope> scopesMap = new HashMap<ScopeType, SeamScope>();
Set<SeamProject> dependsOn = new HashSet<SeamProject>();
Set<SeamProject> usedBy = new HashSet<SeamProject>();
ImportStorage imports = new ImportStorage();
{
createScopes();
}
NamespaceStorage namespaces = new NamespaceStorage();
ComponentStorage components = new ComponentStorage();
FactoryStorage factories = new FactoryStorage();
VariablesStorage variables = new VariablesStorage();
Map<String, ISeamPackage> packages = new HashMap<String, ISeamPackage>();
List<ISeamProjectChangeListener> listeners = new ArrayList<ISeamProjectChangeListener>();
ProjectValidationContext validationContext;
protected int modifications = 0;
protected boolean isBuilt = false;
private void inc() {
modifications++;
}
/**
*
*/
public SeamProject() {}
/**
*
*/
public void configure() throws CoreException {
addToBuildSpec(SeamCoreBuilder.BUILDER_ID);
DesignTimeApplicationManager dtAppManager = DesignTimeApplicationManager.getInstance(project);
if(dtAppManager!=null)
dtAppManager.setVariableResolverProvider(VariableResolver.ID);
}
/**
*
*/
public void deconfigure() throws CoreException {
removeFromBuildSpec(SeamCoreBuilder.BUILDER_ID);
DesignTimeApplicationManager dtAppManager = DesignTimeApplicationManager.getInstance(project);
if(dtAppManager!=null) {
dtAppManager.setVariableResolverProvider(null);
}
}
/**
*
*/
public IProject getProject() {
return project;
}
/**
*
*/
public String getRuntimeName() {
IEclipsePreferences p = getSeamPreferences();
return p.get(ISeamFacetDataModelProperties.SEAM_RUNTIME_NAME, null);
}
/**
*
*/
public SeamRuntime getRuntime() {
String parent = getParentProjectName();
if(parent != null) {
IProject p = ResourcesPlugin.getWorkspace().getRoot().getProject(parent);
if(p == null || !p.isAccessible()) return null;
ISeamProject sp = SeamCorePlugin.getSeamProject(p, false);
return sp == null ? null : sp.getRuntime();
}
String runtimeName = getRuntimeName();
return runtimeName == null ? null : SeamRuntimeManager.getInstance().findRuntimeByName(runtimeName);
}
public String getParentProjectName() {
IEclipsePreferences p = getSeamPreferences();
return p == null ? null : p.get(ISeamFacetDataModelProperties.SEAM_PARENT_PROJECT, null);
}
public ISeamProject getParentProject() {
String n = getParentProjectName();
if(n == null || n.length() == 0) return null;
IProject parent = ResourcesPlugin.getWorkspace().getRoot().getProject(n);
return n == null ? null : SeamCorePlugin.getSeamProject(parent, true);
}
public void setRuntimeName(String runtimeName) {
IEclipsePreferences prefs = getSeamPreferences();
String storedRuntimeName = getRuntimeName();
boolean changed = (storedRuntimeName == null) ? runtimeName != null : !storedRuntimeName.equals(runtimeName);
if(!changed) return;
if(runtimeName == null) {
prefs.remove(RUNTIME_NAME);
} else {
prefs.put(RUNTIME_NAME, runtimeName);
}
try {
prefs.flush();
} catch (BackingStoreException e) {
SeamCorePlugin.getPluginLog().logError(e);
}
}
/**
* Returns list of scope objects for all scope types.
* @return
*/
public ISeamScope[] getScopes() {
return scopes;
}
/**
* Returns scope object for specified scope type.
* @param scopeType
* @return
*/
public SeamScope getScope(ScopeType scopeType) {
return scopesMap.get(scopeType);
}
/**
*
*/
public Collection<ISeamPackage> getPackages() {
synchronized(packages) {
return packages.values();
}
}
public void removePackage(ISeamPackage p) {
synchronized(packages) {
packages.remove(p.getName());
}
}
/**
*
*/
public Collection<ISeamPackage> getAllPackages() {
List<ISeamPackage> list = new ArrayList<ISeamPackage>();
SeamPackageUtil.collectAllPackages(packages, list);
return list;
}
/**
*
*/
public ISeamPackage getPackage(ISeamComponent c) {
String pkg = SeamPackageUtil.getPackageName(c);
return SeamPackageUtil.findPackage(this, packages, pkg);
}
/**
*
*/
public ISeamProject getSeamProject() {
return this;
}
/**
*
*/
public void setProject(IProject project) {
this.project = project;
setSourcePath(project.getFullPath());
resource = project;
classPath.init();
// load();
}
IEclipsePreferences preferences = null;
/**
*
* @return
*/
public IEclipsePreferences getSeamPreferences() {
if(preferences == null) {
IScopeContext projectScope = new ProjectScope(project);
preferences = projectScope.getNode(SeamCorePlugin.PLUGIN_ID);
}
return preferences;
}
/**
*
* @param p
*/
public void addSeamProject(SeamProject p) {
if(dependsOn.contains(p)) return;
dependsOn.add(p);
inc();;
p.addDependentSeamProject(this);
if(!p.isStorageResolved) {
p.resolve();
} else {
Map<IPath,LoadedDeclarations> map = null;
try {
map = p.getAllDeclarations();
} catch (CloneNotSupportedException e) {
SeamCorePlugin.getPluginLog().logError(e);
}
for (IPath source : map.keySet()) {
LoadedDeclarations ds = map.get(source);
registerComponents(ds, source);
}
}
}
/**
*
* @return
*/
public Set<SeamProject> getSeamProjects() {
return dependsOn;
}
/**
*
* @param p
*/
public void addDependentSeamProject(SeamProject p) {
if(usedBy.add(p)) inc();;
}
public Map<String, Set<ISeamNamespace>> getNamespaces() {
return namespaces.namespacesByURI;
}
/**
*
* @param p
*/
public void removeSeamProject(SeamProject p) {
if(!dependsOn.contains(p)) return;
p.usedBy.remove(this);
dependsOn.remove(p);
inc();;
IPath[] ps = sourcePaths2.keySet().toArray(new IPath[0]);
for (int i = 0; i < ps.length; i++) {
IPath pth = ps[i];
if(p.getSourcePath().isPrefixOf(pth) || (p.isPathLoaded(pth) && !EclipseResourceUtil.isJar(pth.toString()))) {
pathRemoved(pth);
}
}
}
/**
*
* @return
*/
public ClassPath getClassPath() {
return classPath;
}
/**
*
* @param load
*/
public void resolveStorage(boolean load) {
if(isStorageResolved) return;
if(load) {
load();
} else {
isStorageResolved = true;
}
}
public void build() {
resolveStorage(!hasNoStorage());
getClassPath().build();
}
public boolean isStorageResolved() {
return isStorageResolved;
}
/**
*
*/
public void resolve() {
resolveStorage(true);
}
/**
* Loads results of last build, which are considered
* actual until next build.
*/
public void load() {
if(isStorageResolved) return;
isStorageResolved = true;
postponeFiring();
try {
boolean b = getClassPath().update();
if(b) {
getClassPath().validateProjectDependencies();
}
File file = getStorageFile();
Element root = null;
if(file != null && file.isFile()) {
root = XMLUtilities.getElement(file, null);
if(root != null) {
loadProjectDependencies(root);
loadNamespaces(root);
if(XMLUtilities.getUniqueChild(root, "paths") != null) {
loadSourcePaths2(root);
} else {
//old code
loadSourcePaths(root);
}
}
}
if(b) {
getClassPath().process();
}
if(root != null) {
getValidationContext().load(root);
}
} finally {
fireChanges();
modifications = 0;
namespaces.modifications = 0;
components.modifications = 0;
factories.modifications = 0;
}
}
public void clean() {
File file = getStorageFile();
if(file != null && file.isFile()) {
file.delete();
}
isBuilt = false;
classPath.clean();
postponeFiring();
IPath[] ps = sourcePaths2.keySet().toArray(new IPath[0]);
for (int i = 0; i < ps.length; i++) {
pathRemoved(ps[i]);
}
dependsOn.clear();
packages.clear();
createScopes();
fireChanges();
}
public long fullBuildTime;
public List<Long> statistics;
/**
* Method testing how long it takes to load Seam model
* serialized previously.
* This approach makes sure, that all other services
* (JDT, XModel, etc) are already loaded at first start of
* Seam model, so that now it is more or less pure time
* to be computed.
*
* @return
*/
public long reload() {
statistics = new ArrayList<Long>();
classPath = new ClassPath(this);
sourcePaths.clear();
sourcePaths2.clear();
isStorageResolved = false;
dependsOn.clear();
usedBy.clear();
namespaces.clear();
components.clear();
factories.clear();
variables.clear();
imports.clear();
packages.clear();
createScopes();
long begin = System.currentTimeMillis();
classPath.init();
resolve();
long end = System.currentTimeMillis();
return end - begin;
}
private void createScopes() {
ScopeType[] types = ScopeType.values();
for (int i = 0; i < scopes.length; i++) {
scopes[i] = new SeamScope(this, types[i]);
scopesMap.put(types[i], scopes[i]);
}
}
public int getModificationsSinceLastStore() {
return modifications +
namespaces.modifications +
components.modifications +
factories.modifications +
((validationContext != null) ? validationContext.getModificationsSinceLastStore() : 0);
}
public void setBuilt(boolean b) {
isBuilt = b;
}
public boolean isBuilt() {
return isBuilt;
}
public void printModifications() {
System.out.println(project.getName());
System.out.println("" + modifications);
System.out.println("namespaces " + namespaces.modifications);
System.out.println("components " + components.modifications);
System.out.println("factories " + factories.modifications);
if(validationContext != null)
System.out.println("validationContext " + validationContext.getModificationsSinceLastStore());
}
private boolean storeDisabledForTesting; // Should be used for testing only!
/**
* Should be used for testing only!
* @param disable
*/
public void setStoreDisabledForTesting(boolean disable) {
this.storeDisabledForTesting = disable;
}
/**
* Stores results of last build, so that on exit/enter Eclipse
* load them without rebuilding project
* @throws IOException
*/
public void store() throws IOException {
if(!storeDisabledForTesting) {
File file = getStorageFile();
if(file != null) {
file.getParentFile().mkdirs();
Element root = XMLUtilities.createDocumentElement("seam-project"); //$NON-NLS-1$
storeProjectDependencies(root);
storeNamespaces(root);
// storeSourcePaths(root);
storeSourcePaths2(root);
if(validationContext != null) validationContext.store(root);
XMLUtilities.serialize(root, file.getAbsolutePath());
modifications = 0;
namespaces.modifications = 0;
components.modifications = 0;
factories.modifications = 0;
}
}
}
/*
*
*/
// private void storeSourcePaths(Element root) {
// Element sourcePathsElement = XMLUtilities.createElement(root, "source-paths"); //$NON-NLS-1$
// for (IPath path : sourcePaths) {
// Element pathElement = XMLUtilities.createElement(sourcePathsElement, "path"); //$NON-NLS-1$
// pathElement.setAttribute("value", path.toString()); //$NON-NLS-1$
// }
// }
private void storeNamespaces(Element root) {
Element namespacesElement = XMLUtilities.createElement(root, "namespaces"); //$NON-NLS-1$
for (String uri : namespaces.namespacesByURI.keySet()) {
Set<ISeamNamespace> s = namespaces.namespacesByURI.get(uri);
for (ISeamNamespace n: s) {
((SeamNamespace)n).toXML(namespacesElement);
}
}
}
private void storeSourcePaths2(Element root) {
Properties context = new Properties();
Element sourcePathsElement = XMLUtilities.createElement(root, "paths"); //$NON-NLS-1$
for (IPath path : sourcePaths2.keySet()) {
IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
if(f != null && f.exists() && f.getProject() != project) {
continue;
}
context.put(SeamXMLConstants.ATTR_PATH, path);
LoadedDeclarations ds = sourcePaths2.get(path);
Element pathElement = XMLUtilities.createElement(sourcePathsElement, "path"); //$NON-NLS-1$
pathElement.setAttribute("value", path.toString()); //$NON-NLS-1$
List<ISeamComponentDeclaration> cs = ds.getComponents();
if(cs != null && !cs.isEmpty()) {
Element cse = XMLUtilities.createElement(pathElement, "components"); //$NON-NLS-1$
for (ISeamComponentDeclaration d: cs) {
SeamObject o = (SeamObject)d;
o.toXML(cse, context);
}
}
List<ISeamFactory> fs = ds.getFactories();
if(fs != null && !fs.isEmpty()) {
Element cse = XMLUtilities.createElement(pathElement, "factories"); //$NON-NLS-1$
for (ISeamFactory d: fs) {
SeamObject o = (SeamObject)d;
o.toXML(cse, context);
}
}
List<SeamImport> imports = ds.getImports();
if(imports != null && !imports.isEmpty()) {
Element cse = XMLUtilities.createElement(pathElement, "imports"); //$NON-NLS-1$
for (SeamImport d: imports) {
d.toXML(cse);
}
}
}
}
/*
*
*/
private void storeProjectDependencies(Element root) {
Element dependsOnElement = XMLUtilities.createElement(root, "depends-on-projects"); //$NON-NLS-1$
for (ISeamProject p : dependsOn) {
if(!p.getProject().isAccessible()) continue;
Element pathElement = XMLUtilities.createElement(dependsOnElement, "project"); //$NON-NLS-1$
pathElement.setAttribute("name", p.getProject().getName()); //$NON-NLS-1$
}
Element usedElement = XMLUtilities.createElement(root, "used-by-projects"); //$NON-NLS-1$
for (ISeamProject p : usedBy) {
if(!p.getProject().isAccessible()) continue;
Element pathElement = XMLUtilities.createElement(usedElement, "project"); //$NON-NLS-1$
pathElement.setAttribute("name", p.getProject().getName()); //$NON-NLS-1$
}
}
/*
* obsolete, will work only for old projects
*/
private void loadSourcePaths(Element root) {
Element sourcePathsElement = XMLUtilities.getUniqueChild(root, "source-paths"); //$NON-NLS-1$
if(sourcePathsElement == null) return;
Element[] paths = XMLUtilities.getChildren(sourcePathsElement, "path"); //$NON-NLS-1$
if(paths != null) for (int i = 0; i < paths.length; i++) {
String p = paths[i].getAttribute("value"); //$NON-NLS-1$
if(p == null || p.trim().length() == 0) continue;
IPath path = new Path(p.trim());
if(sourcePaths.contains(path)) continue;
IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
if(f == null || !f.exists() || !f.isSynchronized(IResource.DEPTH_ZERO)) continue;
SeamResourceVisitor b = new SeamResourceVisitor(this);
b.visit(f);
}
}
private void loadNamespaces(Element root) {
Element namespacesElement = XMLUtilities.getUniqueChild(root, "namespaces"); //$NON-NLS-1$
if(namespacesElement == null) return;
Element[] ns = XMLUtilities.getChildren(namespacesElement, "namespace"); //$NON-NLS-1$
for (int i = 0; i < ns.length; i++) {
SeamNamespace sn = new SeamNamespace();
sn.loadXML(ns[i]);
namespaces.addNamespace(sn);
}
}
private void loadSourcePaths2(Element root) {
Properties context = new Properties();
context.put("seamProject", this);
Element sourcePathsElement = XMLUtilities.getUniqueChild(root, "paths"); //$NON-NLS-1$
if(sourcePathsElement == null) return;
Element[] paths = XMLUtilities.getChildren(sourcePathsElement, "path"); //$NON-NLS-1$
if(paths != null) for (int i = 0; i < paths.length; i++) {
String p = paths[i].getAttribute("value"); //$NON-NLS-1$
if(p == null || p.trim().length() == 0) continue;
IPath path = new Path(p.trim());
if(sourcePaths2.containsKey(path)) continue;
if(!getClassPath().hasPath(path)) {
IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
if(f == null || !f.exists() || !f.isSynchronized(IResource.DEPTH_ZERO)) continue;
}
context.put(SeamXMLConstants.ATTR_PATH, path);
long t1 = System.currentTimeMillis();
LoadedDeclarations ds = new LoadedDeclarations();
Element components = XMLUtilities.getUniqueChild(paths[i], "components");
if(components != null) {
Element[] cs = XMLUtilities.getChildren(components, SeamXMLConstants.TAG_COMPONENT);
for (int j = 0; j < cs.length; j++) {
String cls = cs[j].getAttribute(SeamXMLConstants.ATTR_CLASS);
SeamComponentDeclaration d = null;
if(SeamXMLConstants.CLS_JAVA.equals(cls)) {
d = new SeamJavaComponentDeclaration();
} else if(SeamXMLConstants.CLS_XML.equals(cls)) {
d = new SeamXmlComponentDeclaration();
} else if(SeamXMLConstants.CLS_PROPERTIES.equals(cls)) {
d = new SeamPropertiesDeclaration();
}
if(d == null) continue;
d.loadXML(cs[j], context);
ds.getComponents().add(d);
}
}
Element factories = XMLUtilities.getUniqueChild(paths[i], "factories");
if(factories != null) {
Element[] cs = XMLUtilities.getChildren(factories, SeamXMLConstants.TAG_FACTORY);
for (int j = 0; j < cs.length; j++) {
String cls = cs[j].getAttribute(SeamXMLConstants.ATTR_CLASS);
AbstractContextVariable d = null;
if(SeamXMLConstants.CLS_XML.equals(cls)) {
d = new SeamXmlFactory();
} else if(SeamXMLConstants.CLS_JAVA.equals(cls)) {
d = new SeamAnnotatedFactory();
} else if(SeamXMLConstants.CLS_MESSAGES.equals(cls)) {
d = new SeamMessages();
}
if(d == null) continue;
d.loadXML(cs[j], context);
ds.getFactories().add((ISeamFactory)d);
}
}
Element imports = XMLUtilities.getUniqueChild(paths[i], "imports");
if(imports != null) {
Element[] cs = XMLUtilities.getChildren(imports, SeamXMLConstants.TAG_IMPORT);
for (int j = 0; j < cs.length; j++) {
SeamImport s = new SeamImport();
s.loadXML(cs[j]);
if(s.getSeamPackage() != null && s.getSeamPackage().length() > 0) {
ds.getImports().add(s);
}
}
}
getClassPath().pathLoaded(path);
Set<ISeamNamespace> ns = namespaces.getNamespacesBySource(path);
if(ns != null) {
//we need that, or registering will remove them
ds.getNamespaces().addAll(ns);
}
Iterator<ISeamComponentDeclaration> it = ds.getComponents().iterator();
while(it.hasNext()) {
ISeamComponentDeclaration d = it.next();
if(d instanceof ISeamJavaComponentDeclaration) {
ISeamJavaComponentDeclaration sd = (ISeamJavaComponentDeclaration)d;
if(sd.getClassName() == null) {
it.remove();
}
}
}
registerComponents(ds, path);
long t2 = System.currentTimeMillis();
if(statistics != null) {
statistics.add(new Long(t2 - t1));
// if(t2 - t1 > 30) {
// System.out.println("--->" + statistics.size() + " " + (t2 - t1));
// System.out.println("stop");
// }
}
}
postBuild();
}
/*
*
*/
private void loadProjectDependencies(Element root) {
Element dependsOnElement = XMLUtilities.getUniqueChild(root, "depends-on-projects"); //$NON-NLS-1$
if(dependsOnElement != null) {
Element[] paths = XMLUtilities.getChildren(dependsOnElement, "project"); //$NON-NLS-1$
for (int i = 0; i < paths.length; i++) {
String p = paths[i].getAttribute("name"); //$NON-NLS-1$
if(p == null || p.trim().length() == 0) continue;
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(p);
if(project == null || !project.isAccessible()) continue;
SeamProject sp = (SeamProject)SeamCorePlugin.getSeamProject(project, false);
if(sp != null) {
dependsOn.add(sp);
sp.addDependentSeamProject(this);
}
}
}
Element usedElement = XMLUtilities.getUniqueChild(root, "used-by-projects"); //$NON-NLS-1$
if(usedElement != null) {
Element[] paths = XMLUtilities.getChildren(usedElement, "project"); //$NON-NLS-1$
for (int i = 0; i < paths.length; i++) {
String p = paths[i].getAttribute("name"); //$NON-NLS-1$
if(p == null || p.trim().length() == 0) continue;
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(p);
if(project == null || !project.isAccessible()) continue;
SeamProject sp = (SeamProject)SeamCorePlugin.getSeamProject(project, false);
if(sp != null) usedBy.add(sp);
}
}
}
/*
*
*/
private File getStorageFile() {
SeamCorePlugin plugin = SeamCorePlugin.getDefault();
//The plug-in instance can be null at shutdown, when the plug-in is stopped.
if(plugin != null) {
IPath path = plugin.getStateLocation();
File file = new File(path.toFile(), "projects/" + project.getName()); //$NON-NLS-1$
return file;
} else {
return null;
}
}
public void clearStorage() {
File f = getStorageFile();
if(f != null && f.isFile()) f.delete();
}
public boolean hasNoStorage() {
File f = getStorageFile();
return f == null || !f.isFile();
}
/*
* (non-Javadoc)
* @see org.jboss.tools.seam.core.ISeamProject#getValidationContext()
*/
public ProjectValidationContext getValidationContext() {
if(validationContext==null) {
validationContext = new ProjectValidationContext();
}
return validationContext;
}
/**
*
* @param name
* @return
*/
public ISeamComponent getComponentByName(String name) {
return components.getByName(name);
}
/**
*
*/
public ISeamComponent[] getComponents() {
return components.getAllComponentsArray();
}
/**
* Package local method called by builder.
* @param seamComponent
* @param source
*/
public void registerComponents(LoadedDeclarations ds, IPath source) {
source = UniquePaths.getInstance().intern(source);
boolean isThisProject = pathCheck.isThisProject(source);
ISeamNamespace[] ns = ds.getNamespaces().toArray(new ISeamNamespace[0]);
ISeamComponentDeclaration[] components = ds.getComponents().toArray(new ISeamComponentDeclaration[0]);
ISeamFactory[] factories = ds.getFactories().toArray(new ISeamFactory[0]);
if(ns.length == 0 && components.length == 0 && factories.length == 0 && ds.getImports().isEmpty()) {
pathRemoved(source);
if(EclipseResourceUtil.isJar(source.toString())) {
if(!sourcePaths.contains(source)) sourcePaths.add(source);
sourcePaths2.put(source, ds);
}
return;
}
if(!sourcePaths.contains(source)) sourcePaths.add(source);
sourcePaths2.put(source, ds);
if(ns.length > 0) {
namespaces.addPath(source, ns);
}
if(!ds.getImports().isEmpty()) {
setImports(source, ds.getImports());
} else {
removeImports(source);
}
Map<Object,ISeamComponentDeclaration> currentComponents = findComponentDeclarations(source);
Set<ISeamComponent> affectedComponents = new HashSet<ISeamComponent>();
List<Change> addedComponents = null;
for (int i = 0; i < components.length; i++) {
SeamComponentDeclaration loaded = (SeamComponentDeclaration)components[i];
adopt(loaded);
SeamComponentDeclaration current = (SeamComponentDeclaration)currentComponents.remove(loaded.getId());
loaded.setSourcePath(source);
String name = getComponentName(loaded);
String oldName = getComponentName(current);
boolean nameChanged = current != null && !stringsEqual(name, oldName);
SeamComponent c = getComponent(name);
if(c != null) {
affectedComponents.add(c);
}
String oldClassName = c == null ? null : c.getClassName();
String loadedClassName = getClassName(loaded);
Set<ISeamXmlComponentDeclaration> nameless = new HashSet<ISeamXmlComponentDeclaration>();
if(current != null) {
String currentClassName = getClassName(current);
List<Change> changes = current.merge(loaded);
if(isClassNameChanged(currentClassName, loadedClassName)) {
this.components.onClassNameChanged(currentClassName, loadedClassName, current);
}
if(changes != null && !changes.isEmpty()) {
Change cc = new Change(c, null, null, null);
cc.addChildren(changes);
List<Change> cchanges = Change.addChange(null, cc);
fireChanges(cchanges, isThisProject);
//TODO if java, fire to others
}
if(nameChanged) {
Map<Object,ISeamComponentDeclaration> old = new HashMap<Object, ISeamComponentDeclaration>();
old.put(current.getId(), current);
SeamComponent oc = getComponent(oldName);
if(oc != null) {
ISeamXmlComponentDeclaration[] xds = oc.getXmlDeclarations().toArray(new ISeamXmlComponentDeclaration[0]);
for (ISeamXmlComponentDeclaration x: xds) {
String n = x.getName();
if(loadedClassName != null && loadedClassName.equals(x.getClassName()) && (n == null || n.length() == 0)) {
old.put(((SeamXmlComponentDeclaration)x).getId(), x);
nameless.add(x);
}
}
}
componentDeclarationsRemoved(old);
loaded = current;
current = null;
c = getComponent(name);
if(c != null) {
affectedComponents.add(c);
}
} else {
if(loaded instanceof ISeamXmlComponentDeclaration && c != null) {
ISeamXmlComponentDeclaration xml = (ISeamXmlComponentDeclaration)loaded;
onXMLLoadedDeclaration(c, oldClassName, xml);
}
continue;
}
}
this.components.addDeclaration(loaded);
if(c == null && name != null) {
ScopeType scopeType = loaded.getScope();
c = newComponent(name, scopeType);
affectedComponents.add(c);
this.components.addComponent(c);
addVariable(c);
c.addDeclaration(loaded);
if(nameless != null && nameless.size() > 0) {
for (ISeamComponentDeclaration d: nameless) c.addDeclaration(d);
}
addedComponents = Change.addChange(addedComponents, new Change(this, null, null, c));
} else if(c != null) {
c.addDeclaration(loaded);
List<Change> changes = Change.addChange(null, new Change(c, null, null, loaded));
fireChanges(changes, isThisProject);
}
if(loaded instanceof ISeamJavaComponentDeclaration) {
SeamJavaComponentDeclaration jd = (SeamJavaComponentDeclaration)loaded;
Set<ISeamComponent> cs = getComponentsByClass(jd.getClassName());
for (ISeamComponent ci: cs) {
if(ci == c) continue;
SeamComponent cii = (SeamComponent)ci;
cii.addDeclaration(loaded);
List<Change> changes = Change.addChange(null, new Change(ci, null, null, loaded));
fireChanges(changes, isThisProject);
affectedComponents.add(cii);
}
SeamComponent empty = this.components.getByName("");
if(empty != null && name != null && name.length() > 0) {
ISeamXmlComponentDeclaration[] xds = empty.getXmlDeclarations().toArray(new ISeamXmlComponentDeclaration[0]);
for (ISeamXmlComponentDeclaration x: xds) {
if(jd.getClassName().equals(x.getClassName())) {
empty.removeDeclaration(x);
List<Change> changes = Change.addChange(null, new Change(empty, null, x, null));
c.addDeclaration(x);
changes = Change.addChange(changes, new Change(empty, null, null, x));
fireChanges(changes, isThisProject);
}
}
}
if(oldClassName != null && isClassNameChanged(oldClassName, loadedClassName)) {
nameless.clear();
Map<Object,ISeamComponentDeclaration> old = new HashMap<Object, ISeamComponentDeclaration>();
ISeamXmlComponentDeclaration[] xds = c.getXmlDeclarations().toArray(new ISeamXmlComponentDeclaration[0]);
for (ISeamXmlComponentDeclaration x: xds) {
String n = x.getName();
if(oldClassName.equals(x.getClassName()) && (n == null || n.length() == 0)) {
old.put(((SeamXmlComponentDeclaration)x).getId(), x);
nameless.add(x);
}
}
componentDeclarationsRemoved(old);
if(nameless.size() > 0) {
if(empty == null) {
empty = newComponent("", nameless.iterator().next().getScope());
affectedComponents.add(empty);
this.components.addComponent(empty);
}
List<Change> changes = null;
for (ISeamXmlComponentDeclaration d: nameless) {
empty.addDeclaration(d);
changes = Change.addChange(changes, new Change(empty, null, null, d));
}
fireChanges(changes, isThisProject);
}
}
} else if(loaded instanceof ISeamXmlComponentDeclaration) {
ISeamXmlComponentDeclaration xml = (ISeamXmlComponentDeclaration)loaded;
onXMLLoadedDeclaration(c, oldClassName, xml);
}
}
for (ISeamComponent c: affectedComponents) {
SeamComponent sc = (SeamComponent)c;
addedComponents = sc.revalidate(addedComponents);
}
fireChanges(addedComponents, isThisProject);
componentDeclarationsRemoved(currentComponents);
// revalidate();
Map<Object, ISeamFactory> currentFactories = findFactoryDeclarations(source);
List<Change> addedFactories = null;
for (int i = 0; i < factories.length; i++) {
AbstractContextVariable loaded = (AbstractContextVariable)factories[i];
AbstractContextVariable current = (AbstractContextVariable)currentFactories.remove(loaded.getId());
if(current != null && current.getClass() != loaded.getClass()) {
this.factories.removeFactory((ISeamFactory)current);
current = null;
}
if(current != null) {
List<Change> changes = current.merge(loaded);
fireChanges(changes, isThisProject);
continue;
}
if(factories[i].getParent() == null) {
adopt(factories[i]);
}
this.factories.addFactory(factories[i]);
addedFactories = Change.addChange(addedFactories, new Change(this, null, null, loaded));
}
fireChanges(addedFactories, isThisProject);
factoryDeclarationsRemoved(currentFactories);
variables.revalidate(source);
try {
registerComponentsInDependentProjects(ds, source);
} catch (CloneNotSupportedException e) {
SeamCorePlugin.getPluginLog().logError(e);
}
}
private String getComponentName(SeamComponentDeclaration d) {
if(d == null) return null;
String name = d.getName();
if((name == null || name.length() == 0) && d instanceof SeamXmlComponentDeclaration) {
String className = getClassName(d);
if(className != null && className.length() > 0) {
SeamJavaComponentDeclaration jd = components.getJavaDeclaration(className);
if(jd != null) {
name = jd.getName();
}
}
}
return name;
}
private static String getClassName(ISeamComponentDeclaration d) {
if(d instanceof ISeamJavaComponentDeclaration) {
return ((ISeamJavaComponentDeclaration)d).getClassName();
} else if(d instanceof ISeamXmlComponentDeclaration) {
return ((ISeamXmlComponentDeclaration)d).getClassName();
}
return null;
}
private Set<IPath> sourcesInRegistering = new HashSet<IPath>();
/**
*
* @param ds
* @param source
* @throws CloneNotSupportedException
*/
public void registerComponentsInDependentProjects(LoadedDeclarations ds, IPath source) throws CloneNotSupportedException {
if(usedBy.isEmpty()) return;
if(EclipseResourceUtil.isJar(source.toString())) return;
if(sourcesInRegistering.contains(source)) {
return;
}
synchronized (sourcesInRegistering) {
sourcesInRegistering.add(source);
}
try {
for (SeamProject p : usedBy) {
if(p.sourcesInRegistering.contains(source)) continue;
p.resolve();
LoadedDeclarations ds1 = new LoadedDeclarations();
for (ISeamNamespace n: ds.getNamespaces()) {
ds1.getNamespaces().add(n); //no need to clone, it is read-only.
}
for (ISeamComponentDeclaration d: ds.getComponents()) {
ds1.getComponents().add(d.clone());
}
for (ISeamFactory f : ds.getFactories()) {
ds1.getFactories().add(f.clone());
}
ds1.getImports().addAll(ds.getImports());
p.registerComponents(ds1, source);
}
} finally {
synchronized (sourcesInRegistering) {
sourcesInRegistering.remove(source);
}
}
}
/**
*
* @param s1
* @param s2
* @return
*/
boolean stringsEqual(String s1, String s2) {
return s1 == null ? s2 == null : s1.equals(s2);
}
/*
*
* @param oldClassName
* @param newClassName
* @return
*/
private boolean isClassNameChanged(String oldClassName, String newClassName) {
if(oldClassName == null || oldClassName.length() == 0) return false;
if(newClassName == null || newClassName.length() == 0) return false;
return !oldClassName.equals(newClassName);
}
/*
*
*/
private void onXMLLoadedDeclaration(SeamComponent c, String oldClassName, ISeamXmlComponentDeclaration xml) {
String className = xml.getClassName();
List<Change> changes = null;
if(isClassNameChanged(oldClassName, className)) {
ISeamComponentDeclaration[] ds1 = c.getAllDeclarations().toArray(new ISeamComponentDeclaration[0]);
for (int i1 = 0; i1 < ds1.length; i1++) {
if(!(ds1[i1] instanceof ISeamJavaComponentDeclaration)) continue;
ISeamJavaComponentDeclaration jcd = (ISeamJavaComponentDeclaration)ds1[i1];
if(jcd.getClassName().equals(className)) continue;
// We cannot remove declaration if it declares the same component.
// This is an error to be reported by Seam Validator.
if(c.getName().equals(jcd.getName())) continue;
c.removeDeclaration(jcd);
changes = Change.addChange(changes, new Change(c, null, jcd, null));
}
}
SeamJavaComponentDeclaration j = components.getJavaDeclaration(className);
if(j != null && !c.getAllDeclarations().contains(j)) {
c.addDeclaration(j);
changes = Change.addChange(changes, new Change(c, null, null, j));
}
if(changes != null) c.revalidate(changes);
fireChanges(changes, pathCheck.isThisProject(xml.getSourcePath()));
}
public boolean isPathLoaded(IPath source) {
return sourcePaths2.containsKey(source);
}
/**
* Package local method called by builder.
* @param source
*/
public void pathRemoved(IPath source) {
if(!sourcePaths.contains(source) && !sourcePaths2.containsKey(source)) return;
sourcePaths.remove(source);
sourcePaths2.remove(source);
namespaces.removePath(source);
removeImports(source);
List<Change> changes = null;
Set<SeamComponentDeclaration> ds = components.getDeclarationsBySource(source);
if(ds != null) for (SeamComponentDeclaration d: ds) {
Set<SeamComponent> cs = new HashSet<SeamComponent>();
cs.addAll(d.getComponents());
for (SeamComponent c: cs) {
c.removeDeclaration(d);
changes = Change.addChange(changes, new Change(c, null, d, null));
if(isComponentEmpty(c)) {
changes = removeEmptyComponent(c);
}
}
}
components.removePath(source);
fireChanges(changes, false);
// revalidate();
changes = null;
Set<ISeamFactory> fs = this.factories.removePath(source);
if(fs != null) for (ISeamFactory f: fs) {
changes = Change.addChange(changes, new Change(this, null, f, null));
}
fireChanges(changes, false);
firePathRemovedToDependentProjects(source);
}
public void firePathRemovedToDependentProjects(IPath source) {
if(usedBy.isEmpty()) return;
if(EclipseResourceUtil.isJar(source.toString())) return;
for (SeamProject p : usedBy) {
p.resolve();
p.pathRemoved(source);
}
}
/**
*
* @param source
* @return
*/
public Map<Object,ISeamComponentDeclaration> findComponentDeclarations(IPath source) {
Map<Object,ISeamComponentDeclaration> map = new HashMap<Object, ISeamComponentDeclaration>();
Set<SeamComponentDeclaration> ds = components.getDeclarationsBySource(source);
if(ds != null) for (ISeamComponentDeclaration d: ds) {
SeamComponentDeclaration di = (SeamComponentDeclaration)d;
map.put(di.getId(), di);
}
return map;
}
/**
*
* @param removed
*/
void componentDeclarationsRemoved(Map<Object,ISeamComponentDeclaration> removed) {
if(removed == null || removed.isEmpty()) return;
List<Change> changes = null;
for (ISeamComponentDeclaration declaration: removed.values()) {
SeamComponentDeclaration d = (SeamComponentDeclaration)declaration;
components.removeDeclaration(d);
Set<SeamComponent> sc = new HashSet<SeamComponent>();
sc.addAll(d.getComponents());
for (SeamComponent c: sc) {
c.removeDeclaration(d);
changes = Change.addChange(changes, new Change(c, null, d, null));
Set<ISeamComponentDeclaration> ds = c.getAllDeclarations();
if(ds.size() == 1) {
ISeamComponentDeclaration d1 = ds.iterator().next();
if(d1 instanceof ISeamJavaComponentDeclaration
&& !c.getName().equals(d1.getName())) {
c.removeDeclaration(d1);
changes = Change.addChange(changes, new Change(c, null, d1, null));
}
}
if(isComponentEmpty(c)) {
changes = removeEmptyComponent(c);
}
}
}
fireChanges(changes, false);
}
/*
*
*/
private List<Change> removeEmptyComponent(SeamComponent c) {
components.removeComponent(c);
List<Change> changes = c.removeFromModel(null);
removeVariable(c);
changes = Change.addChange(changes, new Change(this, null, c, null));
return changes;
}
/*
*
*/
private boolean isComponentEmpty(SeamComponent c) {
if(c.getAllDeclarations().isEmpty()) return true;
for (ISeamComponentDeclaration d: c.getAllDeclarations()) {
if(c.getName().equals(d.getName())) return false;
}
return true;
}
/**
*
* @param source
* @return
*/
public Map<Object,ISeamFactory> findFactoryDeclarations(IPath source) {
Map<Object,ISeamFactory> map = new HashMap<Object, ISeamFactory>();
Set<ISeamFactory> fs = factories.getFactoriesBySource(source);
if(fs != null) for (ISeamFactory c: fs) {
AbstractContextVariable ci = (AbstractContextVariable)c;
map.put(ci.getId(), c);
}
return map;
}
/**
*
* @param removed
*/
void factoryDeclarationsRemoved(Map<Object,ISeamFactory> removed) {
if(removed == null || removed.isEmpty()) return;
Iterator<ISeamFactory> iterator = removed.values().iterator();
List<Change> changes = null;
while(iterator.hasNext()) {
ISeamFactory c = iterator.next();
factories.removeFactory(c);
removeVariable(c);
changes = Change.addChange(changes, new Change(this, null, c, null));
}
fireChanges(changes, false);
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#getComponentsByClass(java.lang.String)
*/
public Set<ISeamComponent> getComponentsByClass(String className) {
Set<ISeamComponent> result = new HashSet<ISeamComponent>();
if(className == null) {
return result;
}
Set<SeamComponentDeclaration> ds = components.getDeclarationsByClasName(className);
if(ds == null) return result;
for (SeamComponentDeclaration d: ds) {
for (ISeamComponent c: d.getComponents()) {
if(result.contains(c)) continue;
if(c.getSeamProject() != this) continue;
if(className.equals(c.getClassName())) result.add(c);
}
}
return result;
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#getComponentsByScope(org.jboss.tools.seam.core.ScopeType)
*/
public Set<ISeamComponent> getComponentsByScope(ScopeType type) {
return getComponentsByScope(type, false);
}
/**
*
*/
public Set<ISeamComponent> getComponentsByScope(ScopeType type, boolean addVisibleScopes) {
Set<ISeamComponent> result = new HashSet<ISeamComponent>();
//TODO map needed
for(SeamComponent component: components.allComponents.values()) {
if(isVisibleInScope(component, type, addVisibleScopes)) {
result.add(component);
}
}
return result;
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#addComponent(org.jboss.tools.seam.core.ISeamComponent)
*/
public void addComponent(ISeamComponent component) {
components.addComponent(component);
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#removeComponent(org.jboss.tools.seam.core.ISeamComponent)
*/
public void removeComponent(ISeamComponent component) {
components.removeComponent(component);
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#getVariables()
*/
public Set<ISeamContextVariable> getVariables() {
return variables.getVariablesCopy();
}
public void addVariable(ISeamContextVariable v) {
variables.add(v);
}
public void removeVariable(ISeamContextVariable v) {
variables.remove(v);
}
public void setImports(IPath source, List<SeamImport> paths) {
if(equalLists(imports.importsBySource.get(source), paths)) return;
inc();;
synchronized(variables) {
variables.allVariablesPlusShort = null;
variables.byName = null;
}
imports.setPath(source, paths);
}
private boolean equalLists(List<SeamImport> s1, List<SeamImport> s2) {
if(s1 == null || s2 == null) return s1 == s2;
if(s1.size() != s2.size()) return false;
for (int i = 0; i < s1.size(); i++) {
if(!s1.get(i).getSeamPackage().equals(s2.get(i).getSeamPackage())) return false;
}
return true;
}
public void removeImports(IPath source) {
if(!imports.importsBySource.containsKey(source)) return;
inc();;
synchronized(variables) {
variables.allVariablesPlusShort = null;
}
imports.removePath(source);
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#getVariables()
*/
public Set<ISeamContextVariable> getVariables(boolean includeShortNames) {
if(!includeShortNames) {
return variables.getVariablesCopy();
} else {
return variables.getVariablesPlusShort();
}
}
public Set<ISeamContextVariable> getVariables(ISeamJavaComponentDeclaration context) {
Set<ISeamContextVariable> result = getVariables(true);
Set<String> imports = new HashSet<String>();
if(context != null) {
imports.addAll(((SeamJavaComponentDeclaration)context).getImports());
List<SeamImport> is = getPackageImports(context);
if(is != null) {
for (SeamImport i: is) imports.add(i.getSeamPackage());
}
}
if(!imports.isEmpty()) {
Set<ISeamContextVariable> vs = result;
result = new HashSet<ISeamContextVariable>();
result.addAll(vs);
for (ISeamContextVariable v: vs) {
if(v instanceof ISeamContextShortVariable) continue;
for (String q: imports) {
if(v.getName().startsWith(q + ".")) {
result.add(new SeamContextShortVariable(v, q + "."));
}
}
}
}
return result;
}
public boolean isImportedPackage(String packageName) {
for (IPath s: imports.importsBySource.keySet()) {
List<SeamImport> list = imports.importsBySource.get(s);
for (SeamImport i: list) {
if(i.getJavaPackage() == null) {
if(i.getSeamPackage().equals(packageName)) return true;
}
}
}
return false;
}
public List<SeamImport> getPackageImports(ISeamJavaComponentDeclaration declaration) {
IMember m = declaration.getSourceMember();
IType type = null;
if(m instanceof IType) type = (IType)m;
if(type != null && type.getPackageFragment() != null) {
String n = type.getPackageFragment().getElementName();
return imports.importsByJavaPackage.get(n);
}
return new ArrayList<SeamImport>();
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#getVariablesByName(java.lang.String)
*/
public Set<ISeamContextVariable> getVariablesByName(String name) {
return variables.getByName(name);
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#getVariablesByScope(org.jboss.tools.seam.core.ScopeType)
*/
public Set<ISeamContextVariable> getVariablesByScope(ScopeType scope) {
return getVariablesByScope(scope, false);
}
/**
*
*/
public Set<ISeamContextVariable> getVariablesByScope(ScopeType scope, boolean addVisibleScopes) {
Set<ISeamContextVariable> result = new HashSet<ISeamContextVariable>();
for (ISeamContextVariable v: getVariables(true)) {
if(isVisibleInScope(v, scope, addVisibleScopes)) {
result.add(v);
}
}
return result;
}
public Set<IBijectedAttribute> getBijectedAttributes() {
Set<IBijectedAttribute> result = new HashSet<IBijectedAttribute>();
ISeamJavaComponentDeclaration[] ds = components.getJavaDeclarationsArray();
for (ISeamJavaComponentDeclaration d: ds) {
Set<IBijectedAttribute> as = d.getBijectedAttributes();
if(as != null) result.addAll(as);
}
return result;
}
public Set<IBijectedAttribute> getBijectedAttributesByType(BijectedAttributeType type) {
Set<IBijectedAttribute> result = new HashSet<IBijectedAttribute>();
ISeamJavaComponentDeclaration[] ds = components.getJavaDeclarationsArray();
for (ISeamJavaComponentDeclaration d: ds) {
Set<IBijectedAttribute> as = d.getBijectedAttributesByType(type);
if(as != null) result.addAll(as);
}
return result;
}
public Set<IBijectedAttribute> getBijectedAttributesByName(String name, BijectedAttributeType type) {
Set<IBijectedAttribute> result = new HashSet<IBijectedAttribute>();
ISeamJavaComponentDeclaration[] ds = components.getJavaDeclarationsArray();
for (ISeamJavaComponentDeclaration d: ds) {
Set<IBijectedAttribute> as = d.getBijectedAttributes();
for (IBijectedAttribute a: as) {
if(name != null && !name.equals(a.getName())) continue;
if(type != null && !a.isOfType(type)) continue;
result.add(a);
}
}
return result;
}
/**
*
* @param v
* @param scope
* @param addVisibleScopes
* @return
*/
private boolean isVisibleInScope(ISeamContextVariable v, ScopeType scope, boolean addVisibleScopes) {
if(scope == v.getScope()) {
return true;
} else if(addVisibleScopes && scope != null && v.getScope() != null) {
if(v.getScope().getPriority() >= scope.getPriority()) {
return true;
}
}
return false;
}
/**
*
*/
public void addFactory(ISeamFactory factory) {
factories.addFactory(factory);
}
/**
*
*/
public ISeamFactory[] getFactories() {
return factories.getAllFactoriesArray();
}
/**
*
*/
public Set<ISeamFactory> getFactories(String name, ScopeType scope) {
Set<ISeamFactory> result = new HashSet<ISeamFactory>();
for (ISeamFactory f: getFactories()) {
if(name.equals(f.getName()) && scope.equals(f.getScope())) result.add(f);
}
return result;
}
/**
*
*/
public Set<ISeamFactory> getFactoriesByName(String name) {
Set<ISeamFactory> result = new HashSet<ISeamFactory>();
for (ISeamFactory f: getFactories()) {
if(name.equals(f.getName())) result.add(f);
}
return result;
}
/**
*
*/
public Set<ISeamFactory> getFactoriesByScope(ScopeType scope) {
return getFactoriesByScope(scope, false);
}
/**
*
*/
public Set<ISeamFactory> getFactoriesByScope(ScopeType scope, boolean addVisibleScopes) {
Set<ISeamFactory> result = new HashSet<ISeamFactory>();
for (ISeamFactory f: getFactories()) {
if(isVisibleInScope(f, scope, addVisibleScopes)) {
result.add(f);
}
}
return result;
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#getFactoriesByPath(org.eclipse.core.runtime.IPath)
*/
public Set<ISeamFactory> getFactoriesByPath(IPath path) {
Set<ISeamFactory> result = new HashSet<ISeamFactory>();
Set<ISeamFactory> fs = factories.getFactoriesBySource(path);
if(fs != null) result.addAll(fs);
return result;
}
/**
*
*/
public void removeFactory(ISeamFactory factory) {
factories.removeFactory(factory);
removeVariable(factory);
}
/**
* Returns map of all java classes that contain seam annotations.
* They may be seam components, as well as cases of incomplete annotating
* that does not create a seam component.
* @return
*/
public ISeamJavaComponentDeclaration[] getAllJavaComponentDeclarations() {
return components.getJavaDeclarationsArray();
}
public ISeamJavaComponentDeclaration getJavaComponentDeclaration(String className) {
return components.getJavaDeclaration(className);
}
/**
* Returns set of java classes that contain seam annotations with specified path.
* They may be seam components, as well as cases of incomplete annotating
* that does not create a seam component.
* @return
*/
public Set<ISeamJavaComponentDeclaration> findJavaDeclarations(IPath source) {
//TODO map needed
Set<ISeamJavaComponentDeclaration> set = new HashSet<ISeamJavaComponentDeclaration>();
for (ISeamJavaComponentDeclaration d: components.getJavaDeclarationsArray()) {
if(source.equals(d.getSourcePath())) set.add(d);
}
return set;
}
/**
*
*/
public SeamComponent getComponent(String name) {
return components.getByName(name);
}
public static String MESSAGES_COMPONENT_NAME = "org.jboss.seam.core.messages";
/**
*
* @param name
* @param scopeType
* @return
*/
SeamComponent newComponent(String name, ScopeType scopeType) {
SeamComponent c =
MESSAGES_COMPONENT_NAME.equals(name) ? new SeamMessagesComponent()
: new SeamComponent();
c.setName(name);
c.setId(name);
c.setParent(getScope(scopeType));
((SeamScope)getScope(scopeType)).addComponent(c);
return c;
}
List<Change> postponedChanges = null;
public void postponeFiring() {
if(postponedChanges == null) {
postponedChanges = new ArrayList<Change>();
}
}
public void fireChanges() {
if(postponedChanges == null) return;
List<Change> changes = postponedChanges;
postponedChanges = null;
fireChanges(changes, false);
}
/**
*
* @param changes
*/
void fireChanges(List<Change> changes, boolean increaseModification) {
if(changes == null || changes.isEmpty()) return;
if(increaseModification) inc();;
if(postponedChanges != null) {
postponedChanges.addAll(changes);
return;
}
SeamProjectChangeEvent event = new SeamProjectChangeEvent(this, changes);
ISeamProjectChangeListener[] ls = null;
synchronized(this) {
ls = listeners.toArray(new ISeamProjectChangeListener[0]);
}
if(ls != null) {
for (int i = 0; i < ls.length; i++) {
ls[i].projectChanged(event);
}
}
SeamCorePlugin.fire(event);
}
/**
*
*/
public synchronized void addSeamProjectListener(ISeamProjectChangeListener listener) {
if(listeners.contains(listener)) return;
listeners.add(listener);
}
/**
*
*/
public synchronized void removeSeamProjectListener(ISeamProjectChangeListener listener) {
listeners.remove(listener);
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#getComponentsByResource(org.eclipse.core.resources.IResource)
*/
public Set<ISeamComponent> getComponentsByPath(IPath path) {
Set<ISeamComponent> result = new HashSet<ISeamComponent>();
Set<SeamComponentDeclaration> ds = components.getDeclarationsBySource(path);
if(ds != null) for (SeamComponentDeclaration d: ds) {
Set<SeamComponent> cs = d.getComponents();
for (SeamComponent c: cs) {
if(c.getSeamProject() == this) result.add(c);
}
}
return result;
}
/**
* @see org.jboss.tools.seam.core.ISeamProject#getVariablesByPath(org.eclipse.core.runtime.IPath)
*/
public Set<ISeamContextVariable> getVariablesByPath(IPath path) {
return variables.getByPath(path);
}
/**
*
*/
void revalidate() {
// if(revalidateLock > 0) return;
// revalidateScopes();
// revalidatePackages();
}
/**
*
*/
// void revalidateScopes() {
// List<Change> changes = null;
// for(SeamComponent c : allComponents.values()) {
// SeamScope pc = (SeamScope)c.getParent();
// SeamScope pn = getScope(c.getScope());
// if(pc == pn) continue;
// c.setParent(pn);
// if(pc != null) {
// pc.removeComponent(c);
// changes = Change.addChange(changes, new Change(pc, null, c, null));
// }
// pn.addComponent(c);
// changes = Change.addChange(changes, new Change(pn, null, null, c));
// }
// for (int i = 0; i < scopes.length; i++) {
// scopes[i].revalidatePackages();
// }
// fireChanges(changes);
// }
/**
*
*/
// void revalidatePackages() {
// List<Change> changes = SeamPackageUtil.revalidatePackages(this, allComponents, getComponents(), packages);
// fireChanges(changes);
// }
/**
*
* @return
* @throws CloneNotSupportedException
*/
Map<IPath, LoadedDeclarations> getAllDeclarations() throws CloneNotSupportedException {
Map<IPath, LoadedDeclarations> map = new HashMap<IPath, LoadedDeclarations>();
for (ISeamComponent c : getComponents()) {
for (ISeamComponentDeclaration d : c.getAllDeclarations()) {
IPath p = d.getSourcePath();
if(p == null || EclipseResourceUtil.isJar(p.toString())) continue;
LoadedDeclarations ds = map.get(p);
if(ds == null) {
ds = new LoadedDeclarations();
map.put(p, ds);
}
ds.getComponents().add(d.clone());
}
}
for (String uri : namespaces.namespacesByURI.keySet()) {
Set<ISeamNamespace> s = namespaces.namespacesByURI.get(uri);
for (ISeamNamespace n : s) {
IPath p = n.getSourcePath();
if(p == null || EclipseResourceUtil.isJar(p.toString())) continue;
LoadedDeclarations ds = map.get(p);
if(ds == null) {
ds = new LoadedDeclarations();
map.put(p, ds);
}
ds.getNamespaces().add(n);
}
}
for (ISeamFactory f : getFactories()) {
IPath p = f.getSourcePath();
if(p == null || EclipseResourceUtil.isJar(p.toString())) continue;
LoadedDeclarations ds = map.get(p);
if(ds == null) {
ds = new LoadedDeclarations();
map.put(p, ds);
}
ds.getFactories().add(f.clone());
}
for (IPath p: imports.importsBySource.keySet()) {
if(p == null || EclipseResourceUtil.isJar(p.toString())) continue;
LoadedDeclarations ds = map.get(p);
if(ds == null) {
ds = new LoadedDeclarations();
map.put(p, ds);
}
ds.getImports().addAll(imports.importsBySource.get(p));
}
return map;
}
public void postBuild() {
if(factories.messages != null) {
factories.messages.revalidate();
}
ISeamComponent m = getComponent(MESSAGES_COMPONENT_NAME);
if(m instanceof SeamMessagesComponent) {
((SeamMessagesComponent)m).revalidate();
}
}
/**
*
* @param builderID
* @throws CoreException
*/
protected void addToBuildSpec(String builderID) throws CoreException {
IProjectDescription description = getProject().getDescription();
ICommand command = null;
ICommand commands[] = description.getBuildSpec();
for (int i = 0; i < commands.length && command == null; ++i) {
if (commands[i].getBuilderName().equals(builderID))
command = commands[i];
}
if (command == null) {
command = description.newCommand();
command.setBuilderName(builderID);
ICommand[] oldCommands = description.getBuildSpec();
ICommand[] newCommands = new ICommand[oldCommands.length + 1];
System.arraycopy(oldCommands, 0, newCommands, 0, oldCommands.length);
newCommands[oldCommands.length] = command;
description.setBuildSpec(newCommands);
getProject().setDescription(description, null);
}
}
/**
*
*/
static String EXTERNAL_TOOL_BUILDER = "org.eclipse.ui.externaltools.ExternalToolBuilder"; //$NON-NLS-1$
/**
*
*/
static final String LAUNCH_CONFIG_HANDLE = "LaunchConfigHandle"; //$NON-NLS-1$
/**
*
* @param builderID
* @throws CoreException
*/
protected void removeFromBuildSpec(String builderID) throws CoreException {
IProjectDescription description = getProject().getDescription();
ICommand[] commands = description.getBuildSpec();
for (int i = 0; i < commands.length; ++i) {
String builderName = commands[i].getBuilderName();
if (!builderName.equals(builderID)) {
if(!builderName.equals(EXTERNAL_TOOL_BUILDER)) continue;
Object handle = commands[i].getArguments().get(LAUNCH_CONFIG_HANDLE);
if(handle == null || handle.toString().indexOf(builderID) < 0) continue;
}
ICommand[] newCommands = new ICommand[commands.length - 1];
System.arraycopy(commands, 0, newCommands, 0, i);
System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1);
description.setBuildSpec(newCommands);
getProject().setDescription(description, null);
return;
}
}
public void validatePackage(SeamComponent c) {
SeamPackage p = (SeamPackage)SeamPackageUtil.findOrCreatePackage(this, packages, SeamPackageUtil.getPackageName(c));
c.setProjectPackage(p);
p.getComponents().add(c);
}
class Storage {
protected int modifications = 0;
protected void increaseModification(IPath path) {
if(pathCheck.isThisProject(path)) inc();;
}
}
class NamespaceStorage extends Storage {
Map<IPath, Set<ISeamNamespace>> namespacesBySource = new HashMap<IPath, Set<ISeamNamespace>>();
Map<String, Set<ISeamNamespace>> namespacesByURI = new HashMap<String, Set<ISeamNamespace>>();
public void clear() {
namespacesBySource.clear();
namespacesByURI.clear();
}
public Set<ISeamNamespace> getNamespacesBySource(IPath path) {
return namespacesBySource.get(path);
}
public void addPath(IPath source, ISeamNamespace[] ns) {
Set<ISeamNamespace> sd = namespacesBySource.get(source);
if(sd == null && ns.length == 0) return;
if(ns.length == 0) {
removePath(source);
} else {
//TODO replace this with merge!
removePath(source);
for (int i = 0; i < ns.length; i++) {
addNamespace(ns[i]);
}
}
}
public void addNamespace(ISeamNamespace n) {
String uri = n.getURI();
if(uri != null) {
Set<ISeamNamespace> s = namespacesByURI.get(uri);
if(s == null) {
s = new HashSet<ISeamNamespace>();
namespacesByURI.put(n.getURI(), s);
}
if(s.add(n)) increaseModification(n.getSourcePath());
}
IPath path = n.getSourcePath();
if(path != null) {
Set<ISeamNamespace> fs = namespacesBySource.get(path);
if(fs == null) {
fs = new HashSet<ISeamNamespace>();
namespacesBySource.put(path, fs);
}
if(fs.add(n)) {
increaseModification(n.getSourcePath());
}
}
}
public void removePath(IPath path) {
Set<ISeamNamespace> sd = namespacesBySource.get(path);
if(sd == null) return;
for (ISeamNamespace d: sd) {
if(d.getURI() != null) {
if(namespacesByURI.remove(d.getURI()) != null) {
increaseModification(d.getSourcePath());
}
}
}
namespacesBySource.remove(path);
}
public void removeNamespace(ISeamNamespace n) {
if(namespacesByURI.remove(n.getURI()) != null) {
increaseModification(n.getSourcePath());
}
IPath path = n.getSourcePath();
if(path != null) {
Set<ISeamNamespace> fs = namespacesBySource.get(path);
if(fs != null) {
if(fs.remove(n)) increaseModification(n.getSourcePath());
}
if(fs.isEmpty()) {
namespacesBySource.remove(fs);
}
}
}
}
class ImportStorage extends Storage {
Map<IPath, List<SeamImport>> importsBySource = new HashMap<IPath, List<SeamImport>>();
Map<String, List<SeamImport>> importsByJavaPackage = new HashMap<String, List<SeamImport>>();
public void clear() {
importsBySource.clear();
importsByJavaPackage.clear();
}
public List<SeamImport> getImportsBySource(IPath path) {
return importsBySource.get(path);
}
public void setPath(IPath source, List<SeamImport> ns) {
List<SeamImport> sd = importsBySource.get(source);
if(sd == null && ns.isEmpty()) return;
if(ns.isEmpty()) {
removePath(source);
} else {
if(!equalLists(sd, ns)) {
removePath(source);
importsBySource.put(source, ns);
if(ns.get(0).getJavaPackage() != null) {
importsByJavaPackage.put(ns.get(0).getJavaPackage(), ns);
}
}
}
}
public void removePath(IPath path) {
List<SeamImport> sd = importsBySource.get(path);
if(sd == null) return;
for (SeamImport d: sd) {
String jp = d.getJavaPackage();
importsByJavaPackage.remove(jp);
}
importsBySource.remove(path);
}
}
class ComponentStorage extends Storage {
private Set<ISeamComponent> allComponentsSet = new HashSet<ISeamComponent>();
Map<String, SeamComponent> allComponents = new HashMap<String, SeamComponent>();
Map<String, SeamJavaComponentDeclaration> javaDeclarations = new HashMap<String, SeamJavaComponentDeclaration>();
ISeamJavaComponentDeclaration[] javaDeclarationsArray = null;
Map<IPath, Set<SeamComponentDeclaration>> declarationsBySource = new HashMap<IPath, Set<SeamComponentDeclaration>>();
Map<String, Set<SeamComponentDeclaration>> declarationsByClassName = new HashMap<String, Set<SeamComponentDeclaration>>();
public void clear() {
synchronized(allComponentsSet) {
allComponentsSet.clear();
}
allComponents.clear();
synchronized(javaDeclarations) {
javaDeclarations.clear();
javaDeclarationsArray = null;
}
declarationsBySource.clear();
declarationsByClassName.clear();
modifications = 1;
}
public ISeamComponent[] getAllComponentsArray() {
synchronized(allComponentsSet) {
return components.allComponentsSet.toArray(new ISeamComponent[0]);
}
}
public ISeamJavaComponentDeclaration[] getJavaDeclarationsArray() {
ISeamJavaComponentDeclaration[] result = javaDeclarationsArray;
if(result == null) {
synchronized(javaDeclarations) {
javaDeclarationsArray = new ISeamJavaComponentDeclaration[javaDeclarations.values().size()];
result = javaDeclarationsArray;
int i = 0;
for (ISeamJavaComponentDeclaration d: javaDeclarations.values()) {
javaDeclarationsArray[i++] = d;
}
}
}
return result;
}
public SeamComponent getByName(String name) {
if(name == null) return null;
synchronized(allComponentsSet) {
return allComponents.get(name);
}
}
public void removeComponent(ISeamComponent c) {
synchronized(allComponentsSet) {
allComponentsSet.remove(c);
}
allComponents.remove(c.getName());
}
public void addComponent(ISeamComponent c) {
synchronized(allComponentsSet) {
allComponentsSet.add(c);
}
allComponents.put(c.getName(), (SeamComponent)c);
}
public void addDeclaration(SeamComponentDeclaration d) {
IPath path = d.getSourcePath();
Set<SeamComponentDeclaration> sc = declarationsBySource.get(path);
if(sc == null) {
sc = new HashSet<SeamComponentDeclaration>();
declarationsBySource.put(path, sc);
}
synchronized(sc) {
if(sc.add(d)) increaseModification(d.getSourcePath());
}
if(d instanceof ISeamJavaComponentDeclaration) {
SeamJavaComponentDeclaration jd = (SeamJavaComponentDeclaration)d;
for (ISeamContextVariable v: jd.getDeclaredVariables()) addVariable(v);
synchronized(javaDeclarations) {
if(javaDeclarations.put(jd.getClassName(), jd) != jd) increaseModification(jd.getSourcePath());
javaDeclarationsArray = null;
}
addDeclaration(jd.getClassName(), jd);
} else if(d instanceof ISeamXmlComponentDeclaration) {
ISeamXmlComponentDeclaration xd = (ISeamXmlComponentDeclaration)d;
String className = xd.getClassName();
if(className != null && className.length() > 0) {
addDeclaration(className, d);
}
}
}
public void removeDeclaration(SeamComponentDeclaration d) {
IPath path = d.getSourcePath();
Set<SeamComponentDeclaration> sc = declarationsBySource.get(path);
if(sc != null) {
synchronized(sc) {
if(sc.remove(d)) increaseModification(d.getSourcePath());
}
if(sc.isEmpty()) declarationsBySource.remove(path);
}
removeDeclarationWithClass(d);
}
public Set<SeamComponentDeclaration> getDeclarationsBySource(IPath path) {
Set<SeamComponentDeclaration> result = declarationsBySource.get(path);
if (result != null) {
Set<SeamComponentDeclaration> copy = new HashSet<SeamComponentDeclaration>();
synchronized(result) {
copy.addAll(result);
}
result = copy;
}
return result;
}
public SeamJavaComponentDeclaration getJavaDeclaration(String className) {
synchronized(javaDeclarations) {
return javaDeclarations.get(className);
}
}
public Set<SeamComponentDeclaration> getDeclarationsByClasName(String className) {
return declarationsByClassName.get(className);
}
public void removePath(IPath path) {
Set<SeamComponentDeclaration> sd = declarationsBySource.get(path);
if(sd == null) return;
synchronized(sd) {
for (SeamComponentDeclaration d: sd) {
removeDeclarationWithClass(d);
}
}
if(declarationsBySource.remove(path) != null) increaseModification(path);
}
private void removeDeclarationWithClass(SeamComponentDeclaration d) {
if(d instanceof ISeamJavaComponentDeclaration) {
SeamJavaComponentDeclaration jd = (SeamJavaComponentDeclaration)d;
synchronized(javaDeclarations) {
if(javaDeclarations.remove(jd.getClassName()) != null) increaseModification(jd.getSourcePath());
javaDeclarationsArray = null;
}
for (ISeamContextVariable v: jd.getDeclaredVariables()) removeVariable(v);
removeDeclaration(jd.getClassName(), d);
} else if(d instanceof ISeamXmlComponentDeclaration) {
ISeamXmlComponentDeclaration xd = (ISeamXmlComponentDeclaration)d;
String className = xd.getClassName();
if(className != null && className.length() > 0) {
removeDeclaration(className, d);
}
}
}
public void onClassNameChanged(String oldClassName, String newClassName, SeamComponentDeclaration d) {
if(oldClassName != null) {
removeDeclaration(oldClassName, d);
}
if(newClassName != null) {
addDeclaration(newClassName, d);
}
}
private void addDeclaration(String className, SeamComponentDeclaration d) {
Set<SeamComponentDeclaration> sc = declarationsByClassName.get(className);
if(sc == null) {
sc = new HashSet<SeamComponentDeclaration>();
declarationsByClassName.put(className, sc);
}
if(sc.add(d)) increaseModification(d.getSourcePath());
}
private void removeDeclaration(String className, SeamComponentDeclaration d) {
Set<SeamComponentDeclaration> sc = declarationsByClassName.get(className);
if(sc != null) {
if(sc.remove(d)) increaseModification(d.getSourcePath());
if(sc.isEmpty()) {
declarationsByClassName.remove(className);
}
}
}
}
class FactoryStorage extends Storage {
private Set<ISeamFactory> allFactories = new HashSet<ISeamFactory>();
private ISeamFactory[] allFactoriesArray = null;
Map<IPath, Set<ISeamFactory>> factoriesBySource = new HashMap<IPath, Set<ISeamFactory>>();
SeamMessages messages = null;
public void clear() {
synchronized(allFactories) {
allFactories.clear();
allFactoriesArray = null;
}
factoriesBySource.clear();
messages = null;
modifications = 1;
}
public ISeamFactory[] getAllFactoriesArray() {
ISeamFactory[] result = allFactoriesArray;
if(result == null) {
synchronized(allFactories) {
allFactoriesArray = allFactories.toArray(new ISeamFactory[0]);
result = allFactoriesArray;
}
}
return result;
}
public Set<ISeamFactory> getFactoriesBySource(IPath path) {
return factoriesBySource.get(path);
}
public void addFactory(ISeamFactory f) {
synchronized(allFactories) {
if(allFactories.add(f)) increaseModification(f.getSourcePath());
allFactoriesArray = null;
}
IPath path = f.getSourcePath();
if(path != null) {
Set<ISeamFactory> fs = factoriesBySource.get(path);
if(fs == null) {
fs = new HashSet<ISeamFactory>();
factoriesBySource.put(path, fs);
}
if(fs.add(f)) increaseModification(f.getSourcePath());
}
addVariable(f);
if(f instanceof SeamMessages && f != messages) {
messages = (SeamMessages)f;
inc();;
}
}
public void removeFactory(ISeamFactory f) {
synchronized(allFactories) {
if(allFactories.remove(f)) increaseModification(f.getSourcePath());
allFactoriesArray = null;
}
IPath path = f.getSourcePath();
if(path != null) {
Set<ISeamFactory> fs = factoriesBySource.get(path);
if(fs != null) {
if(fs.remove(f)) increaseModification(f.getSourcePath());
}
if(fs.isEmpty()) {
factoriesBySource.remove(fs);
}
}
removeVariable(f);
if(f == messages && f != null) {
messages = null;
increaseModification(f.getSourcePath());
}
}
public Set<ISeamFactory> removePath(IPath path) {
Set<ISeamFactory> fs = factoriesBySource.get(path);
if(fs == null) return null;
for (ISeamFactory f: fs) {
synchronized(allFactories) {
if(allFactories.remove(f)) increaseModification(f.getSourcePath());
allFactoriesArray = null;
}
removeVariable(f);
if(f == messages) {
messages = null;
inc();;
}
}
if(factoriesBySource.remove(path) != null) increaseModification(path);
return fs;
}
}
class VariablesStorage {
Set<ISeamContextVariable> allVariables = new HashSet<ISeamContextVariable>();
Set<ISeamContextVariable> allVariablesCopy = null;
Set<ISeamContextVariable> allVariablesPlusShort = null;
Map<IPath, Set<ISeamContextVariable>> byPath = null;
Map<String, Set<ISeamContextVariable>> byName = null;
public void clear() {
allVariables.clear();
clearCopies();
modifications = 1;
}
synchronized void clearCopies() {
allVariablesCopy = null;
allVariablesPlusShort = null;
byName = null;
byPath = null;
}
public Set<ISeamContextVariable> getVariablesCopy() {
Set<ISeamContextVariable> vs = allVariablesCopy;
if(vs == null) {
synchronized(this) {
allVariablesCopy = new HashSet<ISeamContextVariable>();
allVariablesCopy.addAll(allVariables);
vs = allVariablesCopy;
}
}
return vs;
}
public Set<ISeamContextVariable> getVariablesPlusShort() {
Set<ISeamContextVariable> vs = getVariablesCopy();
Set<ISeamContextVariable> result = allVariablesPlusShort;
if(result != null) return result;
synchronized (this) {
result = new HashSet<ISeamContextVariable>();
result.addAll(vs);
for (ISeamContextVariable v: vs) {
String n = v.getName();
int i = n.lastIndexOf('.');
if(i < 0) continue;
String packageName = n.substring(0, i);
if(isImportedPackage(packageName)) {
result.add(new SeamContextShortVariable(v));
}
}
allVariablesPlusShort = result;
}
return result;
}
public synchronized void add(ISeamContextVariable v) {
if(allVariables.contains(v)) return;
clearCopies();
allVariables.add(v);
}
public synchronized void remove(ISeamContextVariable v) {
if(!allVariables.contains(v)) return;
clearCopies();
allVariables.remove(v);
}
public synchronized void revalidate(IPath path) {
byPath = null;
byName = null;
}
private void create() {
byName = new HashMap<String, Set<ISeamContextVariable>>();
byPath = new HashMap<IPath, Set<ISeamContextVariable>>();
Set<ISeamContextVariable> q = getVariablesPlusShort();
for (ISeamContextVariable v : q) {
if(v instanceof ISeamComponent) {
ISeamComponent c = (ISeamComponent)v;
for (ISeamComponentDeclaration d: c.getAllDeclarations()) {
SeamComponentDeclaration di = (SeamComponentDeclaration)d;
addForPath(di.getSourcePath(), v);
}
} else {
IResource variableResource = v.getResource();
if(variableResource != null) {
addForPath(variableResource.getFullPath(), v);
}
}
String n = "" + v.getName();
Set<ISeamContextVariable> s = byName.get(n);
if(s == null) {
s = new HashSet<ISeamContextVariable>();
byName.put(n, s);
}
s.add(v);
}
}
private void addForPath(IPath p, ISeamContextVariable v) {
if(p == null) return;
Set<ISeamContextVariable> s = byPath.get(p);
if(s == null) {
s = new HashSet<ISeamContextVariable>();
byPath.put(p, s);
}
s.add(v);
}
public synchronized Set<ISeamContextVariable> getByName(String n) {
if(byName == null) {
create();
}
return byName.get(n);
}
public synchronized Set<ISeamContextVariable> getByPath(IPath p) {
if(byPath == null) {
create();
}
return byPath.get(p);
}
}
PathCheck pathCheck = new PathCheck();
class PathCheck {
Map<IPath, Boolean> paths = new HashMap<IPath, Boolean>();
public boolean isThisProject(IPath path) {
Boolean b = paths.get(path);
if(b == null) {
if(path != null && path.toString().endsWith(".jar")) { //$NON-NLS-1$
b = true;
} else {
IFile f = path.segmentCount() < 2 ? null : ResourcesPlugin.getWorkspace().getRoot().getFile(path);
b = !(f != null && f.exists() && f.getProject() != project);
}
paths.put(UniquePaths.getInstance().intern(path), b);
}
return b.booleanValue();
}
}
}