/*******************************************************************************
* 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.text.ext.hyperlink;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.jboss.tools.cdi.core.CDIConstants;
import org.jboss.tools.cdi.core.IBean;
import org.jboss.tools.cdi.core.IBeanMember;
import org.jboss.tools.cdi.core.IInjectionPoint;
import org.jboss.tools.cdi.core.IProducer;
import org.jboss.tools.cdi.text.ext.CDIExtensionsPlugin;
/**
*
* @author Viacheslav Kabanovich
*
*/
public class AssignableBeanFilters {
public static interface Filter {
public void filter(Set<IBean> beans);
}
public static interface FilterContributor {
public void contribute(AssignableBeanFilters filters, IInjectionPoint injectionPoint);
}
static FilterContributor[] contributors = null;
public static int OPTION_UNAVAILABLE_BEANS = 1;
public static int OPTION_DECORATOR = 2;
public static int OPTION_INTERCEPTOR = 3;
public static int OPTION_UNSELECTED_ALTERNATIVE = 4;
public static int OPTION_PRODUCER_IN_UNAVAILABLE_BEAN = 5;
public static int OPTION_SPECIALIZED_BEAN = 6;
public static int OPTION_ELIMINATED_AMBIGUOUS = 7;
public static class Checkbox {
int id;
String label;
Filter filter;
boolean state = true;
Checkbox(int id, String label, Filter filter) {
this.id = id;
this.label = label;
this.filter = filter;
}
Checkbox parent = null;
List<Checkbox> children = new ArrayList<Checkbox>();
Checkbox add(int id, String label, Filter f) {
Checkbox c = new Checkbox(id, label, f);
c.parent = this;
children.add(c);
return c;
}
public String toString() {
return label;
}
public boolean isEnabled() {
return state && (parent == null || parent.isEnabled());
}
public void filter(Set<IBean> beans) {
if(!isEnabled() && filter != null) {
filter.filter(beans);
}
for (Checkbox c: children) {
c.filter(beans);
}
}
}
private Map<Integer, Checkbox> allOptions = new HashMap<Integer, Checkbox>();
private Checkbox root = new Checkbox(0, "", null);
public AssignableBeanFilters() {
initContributors();
}
void initContributors() {
if(contributors == null) {
IConfigurationElement[] cs = Platform.getExtensionRegistry().getExtensionPoint("org.jboss.tools.cdi.text.ext.assignableBeanFilterContributors").getConfigurationElements();
ArrayList<FilterContributor> s = new ArrayList<FilterContributor>();
for (IConfigurationElement c: cs) {
try {
FilterContributor f = (FilterContributor)c.createExecutableExtension("class");
s.add(f);
} catch (CoreException e) {
CDIExtensionsPlugin.getDefault().logError(e);
}
}
contributors = s.toArray(new FilterContributor[s.size()]);
}
}
public void init(IInjectionPoint point) {
allOptions.clear();
allOptions.put(root.id, root);
add(0, OPTION_UNAVAILABLE_BEANS, "Unavailable Beans", null);
add(OPTION_UNAVAILABLE_BEANS, OPTION_DECORATOR, "@Decorator", new DecoratorFilter());
add(OPTION_UNAVAILABLE_BEANS, OPTION_INTERCEPTOR, "@Interceptor", new InterceptorFilter());
add(OPTION_UNAVAILABLE_BEANS, OPTION_UNSELECTED_ALTERNATIVE, "Unselected @Alternative", new UnselectedAlternativeFilter());
add(OPTION_UNAVAILABLE_BEANS, OPTION_PRODUCER_IN_UNAVAILABLE_BEAN, "@Produces in unavailable bean", new ProducerFilter());
add(OPTION_UNAVAILABLE_BEANS, OPTION_SPECIALIZED_BEAN, "Specialized beans", new SpecializedBeanFilter());
add(0, OPTION_ELIMINATED_AMBIGUOUS, "Eliminated ambiguous", new EliminatedAmbiguousFilter());
for (FilterContributor c: contributors) {
c.contribute(this, point);
}
}
public void add(int parentId, int id, String label, Filter f) {
Checkbox parent = getOption(parentId);
if(parent == null) {
parent = root;
}
Checkbox c = parent.add(id, label, f);
allOptions.put(id, c);
}
public Checkbox getRoot() {
return root;
}
public Map<Integer, Checkbox> getAllOptions() {
return allOptions;
}
public Checkbox getOption(int id) {
return allOptions.get(id);
}
public Filter getFilter(int id) {
Checkbox c = getOption(id);
return c == null ? null : c.filter;
}
public static class DecoratorFilter implements Filter {
public void filter(Set<IBean> beans) {
Iterator<IBean> it = beans.iterator();
while(it.hasNext()) {
IBean b = it.next();
if(b.isAnnotationPresent(CDIConstants.DECORATOR_STEREOTYPE_TYPE_NAME)) {
it.remove();
}
}
}
}
public static class InterceptorFilter implements Filter {
public void filter(Set<IBean> beans) {
Iterator<IBean> it = beans.iterator();
while(it.hasNext()) {
IBean b = it.next();
if(b.isAnnotationPresent(CDIConstants.INTERCEPTOR_ANNOTATION_TYPE_NAME)) {
it.remove();
}
}
}
}
public static class UnselectedAlternativeFilter implements Filter {
public void filter(Set<IBean> beans) {
Iterator<IBean> it = beans.iterator();
while(it.hasNext()) {
IBean b = it.next();
if(b.isAlternative() && !b.isSelectedAlternative()) {
it.remove();
}
}
}
}
public static class SpecializedBeanFilter implements Filter {
public void filter(Set<IBean> beans) {
Iterator<IBean> it = beans.iterator();
Set<IBean> specialized = new HashSet<IBean>();
while(it.hasNext()) {
IBean b = it.next();
IBean bean = b.getSpecializedBean();
if(bean != null) {
specialized.add(bean);
}
}
beans.removeAll(specialized);
}
}
public static class ProducerFilter implements Filter {
public void filter(Set<IBean> beans) {
Iterator<IBean> it = beans.iterator();
while(it.hasNext()) {
IBean b = it.next();
if(b instanceof IProducer && ((IProducer) b).getClassBean() != null && !((IProducer) b).getClassBean().isEnabled()) {
it.remove();
}
}
}
}
public class EliminatedAmbiguousFilter implements Filter {
public void filter(Set<IBean> beans) {
Set<IBean> eligible = new HashSet<IBean>(beans);
for (int i = OPTION_UNAVAILABLE_BEANS + 1; i < OPTION_ELIMINATED_AMBIGUOUS; i++) {
Filter f = getFilter(i);
if(f != null) {
f.filter(eligible);
}
}
boolean hasAlternative = false;
for (IBean b: eligible) {
if(b.isEnabled() && b.isAlternative() && b.isSelectedAlternative()) {
hasAlternative = true;
}
}
if(hasAlternative) {
Iterator<IBean> it = beans.iterator();
while(it.hasNext()) {
IBean bean = it.next();
if(!eligible.contains(bean) || bean.isAlternative()) continue;
if(bean instanceof IProducer && bean instanceof IBeanMember) {
IBeanMember p = (IBeanMember)bean;
if(p.getClassBean() != null && p.getClassBean().isAlternative()) continue;
}
it.remove();
}
}
}
}
}