/*******************************************************************************
* 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.cdi.core.extension;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jboss.tools.cdi.core.CDICoreNature;
import org.jboss.tools.cdi.core.extension.feature.IAmbiguousBeanResolverFeature;
import org.jboss.tools.cdi.core.extension.feature.IBuildParticipantFeature;
import org.jboss.tools.cdi.core.extension.feature.ICDIFeature;
import org.jboss.tools.cdi.core.extension.feature.IProcessAnnotatedMemberFeature;
import org.jboss.tools.cdi.core.extension.feature.IProcessAnnotatedTypeFeature;
import org.jboss.tools.cdi.core.extension.feature.IValidatorFeature;
/**
*
* @author Viacheslav Kabanovich
*
*/
public class CDIExtensionManager {
CDICoreNature n;
/**
* Mapping of jar path to CDI extensions declared in it.
*/
Map<String, Set<String>> runtimes = new HashMap<String, Set<String>>();
Set<String> allRuntimes = new HashSet<String>();
/**
* Mapping of extension ids (class names) to instances.
*/
Map<String, ICDIExtension> instances = new HashMap<String, ICDIExtension>();
/**
* Mapping of runtime extension class names to instances.
*/
Map<String, ICDIExtension> instancesByRuntime = new HashMap<String, ICDIExtension>();
/**
* Mapping of feature ids to extension instances.
*/
Map<Class<?>, Set<ICDIExtension>> featureToExtensions = new HashMap<Class<?>, Set<ICDIExtension>>();
Map<Class<? extends ICDIFeature>, Set<?>> featureStorage = new HashMap<Class<? extends ICDIFeature>, Set<?>>();
public CDIExtensionManager() {
}
public void setProject(CDICoreNature n) {
this.n = n;
}
public boolean isCDIExtensionAvailable(String runtimeClassName) {
return allRuntimes.contains(runtimeClassName);
}
public void pathRemoved(String path) {
Set<String> rs = runtimes.remove(path);
if(rs == null) return;
for (String runtime: rs) {
deleteRuntime(runtime);
}
}
public boolean setRuntimes(String path, Set<String> newRuntimes) {
Set<String> oldRuntimes = runtimes.get(path);
if(oldRuntimes == null) {
if(newRuntimes.isEmpty()) {
return false;
}
oldRuntimes = new HashSet<String>();
}
boolean result = false;
for (String runtime: oldRuntimes) {
if(!newRuntimes.contains(runtime)) {
deleteRuntime(runtime);
result = true;
}
}
for (String runtime: newRuntimes) {
if(!oldRuntimes.contains(runtime)) {
addRuntime(runtime);
result = true;
}
}
if(newRuntimes.isEmpty()) runtimes.remove(path); else runtimes.put(path, newRuntimes);
return result;
}
private void addRuntime(String runtime) {
allRuntimes.add(runtime);
CDIExtensionFactory factory = CDIExtensionFactory.getInstance();
Set<String> clss = factory.getExtensionClassesByRuntime(runtime);
if(clss != null) {
for (String cls: clss) {
ICDIExtension ext = factory.createExtensionInstance(cls);
if(ext == null) continue;
instances.put(cls, ext);
instancesByRuntime.put(runtime, ext);
for (Class<?> feature: CDIExtensionFactory.getInstance().getFeatures(ext)) {
Set<ICDIExtension> es = featureToExtensions.get(feature);
if(es == null) {
es = new HashSet<ICDIExtension>();
featureToExtensions.put(feature, es);
}
es.add(ext);
}
featureStorage.clear();
}
}
}
private void deleteRuntime(String runtime) {
allRuntimes.remove(runtime);
instancesByRuntime.remove(runtime);
Set<String> clss = CDIExtensionFactory.getInstance().getExtensionClassesByRuntime(runtime);
if(clss != null) {
for (String cls: clss) {
ICDIExtension ext = instances.remove(cls);
if(ext != null) {
Class<?>[] is = featureToExtensions.keySet().toArray(new Class<?>[0]);
for (Class<?> feature: is) {
Set<ICDIExtension> es = featureToExtensions.get(feature);
if(es != null) {
es.remove(ext);
if(es.isEmpty()) featureToExtensions.remove(feature);
}
}
}
}
if(!clss.isEmpty()) {
featureStorage.clear();
}
}
}
static Set<ICDIExtension> EMPTY = new HashSet<ICDIExtension>();
public Set<ICDIExtension> getExtensions(Class<?> feature) {
return featureToExtensions.containsKey(feature) ? featureToExtensions.get(feature) : EMPTY;
}
public ICDIExtension getExtensionByRuntime(String runtime) {
return instancesByRuntime.get(runtime);
}
public Set<IProcessAnnotatedMemberFeature> getProcessAnnotatedMemberFeatures() {
return getFeatures(IProcessAnnotatedMemberFeature.class);
}
public Set<IProcessAnnotatedTypeFeature> getProcessAnnotatedTypeFeatures() {
return getFeatures(IProcessAnnotatedTypeFeature.class);
}
public Set<IBuildParticipantFeature> getBuildParticipantFeatures() {
return getFeatures(IBuildParticipantFeature.class);
}
public Set<IAmbiguousBeanResolverFeature> getAmbiguousBeanResolverFeatures() {
return getFeatures(IAmbiguousBeanResolverFeature.class);
}
public Set<IValidatorFeature> getValidatorFeatures() {
return getFeatures(IValidatorFeature.class);
}
/**
* Returns set of feature implementation objects by feature class.
*
* @param cls
* @return set of feature implementation objects by feature class
*/
public <F extends ICDIFeature> Set<F> getFeatures(Class<F> cls) {
@SuppressWarnings("unchecked")
Set<F> result = (Set<F>)featureStorage.get(cls);
if(result == null) {
result = new HashSet<F>();
Set<ICDIExtension> extensions = getExtensions(cls);
if(!extensions.isEmpty()) {
for (ICDIExtension ext: extensions) {
F feature = CDIExtensionFactory.adaptTo(ext, cls);
if(feature != null) {
result.add(feature);
}
}
}
featureStorage.put(cls, result);
}
return result;
}
}