/*******************************************************************************
* Copyright (c) 2011 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.jsf.jsf2.bean.model.impl;
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.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IType;
import org.jboss.tools.common.model.XJob;
import org.jboss.tools.common.model.XJob.XRunnable;
import org.jboss.tools.common.util.FileUtil;
import org.jboss.tools.jsf.JSFModelPlugin;
import org.jboss.tools.jsf.jsf2.bean.build.JSF2ProjectBuilder;
import org.jboss.tools.jsf.jsf2.bean.model.IJSF2ManagedBean;
import org.jboss.tools.jsf.jsf2.bean.model.IJSF2Project;
import org.jboss.tools.jsf.jsf2.bean.model.JSF2ProjectFactory;
import org.jboss.tools.jsf.jsf2.bean.scanner.lib.ClassPathMonitor;
import org.jboss.tools.jst.web.kb.internal.AbstractKbProjectExtension;
import org.jboss.tools.jst.web.kb.internal.IKbProjectExtension;
/**
*
* @author Viacheslav Kabanovich
*
*/
public class JSF2Project extends AbstractKbProjectExtension implements IJSF2Project {
ClassPathMonitor classPath = new ClassPathMonitor(this);
DefinitionContext definitions = new DefinitionContext();
private Set<IJSF2ManagedBean> allBeans = new HashSet<IJSF2ManagedBean>();
private Map<IPath, Set<IJSF2ManagedBean>> beansByPath = new HashMap<IPath, Set<IJSF2ManagedBean>>();
private Map<String, Set<IJSF2ManagedBean>> beansByName = new HashMap<String, Set<IJSF2ManagedBean>>();
private Set<IJSF2ManagedBean> namedBeans = new HashSet<IJSF2ManagedBean>();
private boolean isMetadataComplete = false;
public JSF2Project() {
definitions.setProject(this);
}
@Override
public Set<IJSF2ManagedBean> getManagedBeans() {
Set<IJSF2ManagedBean> result = new HashSet<IJSF2ManagedBean>();
synchronized(this) {
result.addAll(namedBeans);
}
return result;
}
@Override
public Set<IJSF2ManagedBean> getManagedBeans(IPath path) {
Set<IJSF2ManagedBean> result = new HashSet<IJSF2ManagedBean>();
Set<IJSF2ManagedBean> beans = beansByPath.get(path);
if(beans != null && !beans.isEmpty()) result.addAll(beans);
return result;
}
@Override
public Set<IJSF2ManagedBean> getManagedBeans(String name) {
Set<IJSF2ManagedBean> result = new HashSet<IJSF2ManagedBean>();
synchronized(this) {
Set<IJSF2ManagedBean> beans = beansByName.get(name);
if(beans != null) {
result.addAll(beans);
}
}
return result;
}
@Override
public boolean isMetadataComplete() {
return isMetadataComplete;
}
@Override
public void setProject(IProject project) {
super.setProject(project);
classPath.init();
}
@Override
protected void resolveUsedProjectInJob(final IKbProjectExtension project) {
XJob.addRunnableWithPriority(new XRunnable() {
public void run() {
project.resolve();
project.update(true);
}
public String getId() {
return "Build JSF2 Project " + project.getProject().getName();
}
});
}
public List<TypeDefinition> getAllTypeDefinitions() {
Set<IKbProjectExtension> ps = getUsedProjects(true);
if(ps == null || ps.isEmpty()) {
return getDefinitions().getTypeDefinitions();
}
List<TypeDefinition> ds = getDefinitions().getTypeDefinitions();
List<TypeDefinition> result = new ArrayList<TypeDefinition>();
result.addAll(ds);
Set<IType> types = new HashSet<IType>();
for (TypeDefinition d: ds) {
IType t = d.getType();
if(t != null) types.add(t);
}
for (IKbProjectExtension p: ps) {
List<TypeDefinition> ds2 = ((JSF2Project)p).getDefinitions().getTypeDefinitions();
for (TypeDefinition d: ds2) {
IType t = d.getType();
if(t != null && !types.contains(t)) {
types.add(t);
result.add(d);
}
}
}
return result;
}
public DefinitionContext getDefinitions() {
return definitions;
}
@Override
public void pathRemoved(IPath path) {
definitions.getWorkingCopy().clean(path);
}
public ClassPathMonitor getClassPath() {
return classPath;
}
protected void build() {
try {
new JSF2ProjectBuilder(this);
} catch (CoreException e) {
JSFModelPlugin.getDefault().logError(e);
}
}
public void clean() {
File file = getStorageFile();
if(file != null && file.isFile()) {
file.delete();
}
isBuilt = false;
classPath.clean();
postponeFiring();
fireChanges();
}
public void update(boolean updateDependent) {
FacesConfigDefinition fc = definitions.getFacesConfig();
isMetadataComplete = fc != null && fc.isMetadataComplete();
List<TypeDefinition> typeDefinitions = getAllTypeDefinitions();
List<IJSF2ManagedBean> beans = new ArrayList<IJSF2ManagedBean>();
for (TypeDefinition typeDefinition : typeDefinitions) {
if(typeDefinition.isManagedBean()) { //improve for managed properties
JSF2ManagedBean bean = new JSF2ManagedBean();
bean.setDefinition(typeDefinition);
beans.add(bean);
}
}
synchronized (this) {
beansByPath.clear();
beansByName.clear();
namedBeans.clear();
allBeans.clear();
}
if(!isMetadataComplete) {
//No JSF2 beans in model when metadata is complete.
for (IJSF2ManagedBean bean: beans) {
addBean(bean);
}
}
if(updateDependent) {
Collection<IKbProjectExtension> dependent = new ArrayList<IKbProjectExtension>(usedBy);
for (IKbProjectExtension p: dependent) {
p.update(false);
}
}
}
public void addBean(IJSF2ManagedBean bean) {
String name = bean.getName();
if(name != null && name.length() > 0) {
synchronized (this) {
Set<IJSF2ManagedBean> bs = beansByName.get(name);
if(bs == null) {
bs = new HashSet<IJSF2ManagedBean>();
beansByName.put(name, bs);
}
bs.add(bean);
namedBeans.add(bean);
}
}
IPath path = bean.getSourcePath();
synchronized (this) {
Set<IJSF2ManagedBean> bs = beansByPath.get(path);
if(bs == null) {
bs = new HashSet<IJSF2ManagedBean>();
beansByPath.put(path, bs);
}
bs.add(bean);
allBeans.add(bean);
}
}
public void store() throws IOException {
isBuilt = true;
// File file = getStorageFile();
}
private File getStorageFile() {
IPath path = JSFModelPlugin.getDefault().getStateLocation();
File file = new File(path.toFile(), "projects/" + project.getName()); //$NON-NLS-1$
return file;
}
public void clearStorage() {
File f = getStorageFile();
if(f == null || !f.exists()) return;
FileUtil.clear(f);
f.delete();
}
public boolean hasNoStorage() {
if(isBuilt) return false;
File f = getStorageFile();
return f == null || !f.exists();
}
@Override
protected IKbProjectExtension loadWithFactory(IProject project, boolean resolve) {
return JSF2ProjectFactory.getJSF2Project(project, resolve);
}
@Override
public void dispose() {
classPath.dispose();
}
}