package org.jboss.shrinkwrap.impl;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.jboss.shrinkwrap.api.BeanDiscoveryMode;
import org.jboss.shrinkwrap.api.asset.Asset;
public class BeansXml implements Asset {
public static final BeansXml SUPPRESSOR = new BeansXml(Collections.<Class<?>> emptyList(), Collections.<Class<?>> emptyList(), Collections.<Class<?>> emptyList(), Collections.<Class<?>> emptyList(), Collections.<Exclude> emptyList()) {
@Override
public BeanDiscoveryMode getBeanDiscoveryMode() {
return BeanDiscoveryMode.NONE;
}
};
private static final String CLOSING_TAG_PREFIX = "</";
private static final String OPENING_TAG_PREFIX = "<";
private static final String TAG_SUFFIX = ">";
private static final String TAG_SUFFIX_NEW_LINE = ">\n";
private static final String TAG_SUFFIX_SELF_CLOSE_NEW_LINE = " />\n";
private static final String ALTERNATIVES_ELEMENT_NAME = "alternatives";
private static final String CLASS = "class";
private static final String SCAN_ELEMENT_NAME = "scan";
private static final String EXCLUDE_ELEMENT_NAME = "exclude";
private static final String IF_SYSTEM_PROPERTY_ELEMENT_NAME = "if-system-property";
private static final String IF_CLASS_AVAILABLE_ELEMENT_NAME = "if-class-available";
private static final String IF_CLASS_NOT_AVAILABLE_ELEMENT_NAME = "if-class-not-available";
private static final String NAME_ATTRIBUTE_NAME = "name";
private static final String VALUE_ATTRIBUTE_NAME = "value";
private final List<Class<?>> alternatives;
private final List<Class<?>> interceptors;
private final List<Class<?>> decorators;
private final List<Class<?>> stereotypes;
private final List<Exclude> excludeFilters;
private BeanDiscoveryMode mode = BeanDiscoveryMode.ALL;
public static class Exclude {
private final String classFilter;
private final List<Condition> conditions;
private Exclude(String classFilter) {
this.classFilter = classFilter;
conditions = new ArrayList<Condition>();
}
public static Exclude match(String classFilter) {
return new Exclude(classFilter);
}
public static Exclude exact(Class<?> clazz) {
return new Exclude(clazz.getName());
}
public Exclude ifSystemProperty(String name) {
conditions.add(new IfSystemProperty(name, null));
return this;
}
public Exclude ifSystemProperty(String name, String value) {
conditions.add(new IfSystemProperty(name, value));
return this;
}
public Exclude ifClassAvailable(Class<?> clazz) {
return ifClassAvailable(clazz.getName());
}
public Exclude ifClassAvailable(String className) {
conditions.add(new IfClassAvailable(className));
return this;
}
public Exclude ifClassNotAvailable(Class<?> clazz) {
return ifClassNotAvailable(clazz.getName());
}
public Exclude ifClassNotAvailable(String className) {
conditions.add(new IfClassNotAvailable(className));
return this;
}
public String getClassFilter() {
return this.classFilter;
}
public List<Condition> getConditions() {
return this.conditions;
}
private static class Condition {
private final String nameParam;
private final String tagName;
public Condition(String tagName, String nameParam) {
this.tagName = tagName;
this.nameParam = nameParam;
}
public String getName() {
return this.nameParam;
}
public String getTagName() {
return this.tagName;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(OPENING_TAG_PREFIX).append(getTagName());
appendAttribute(NAME_ATTRIBUTE_NAME, getName(), sb);
sb.append(TAG_SUFFIX_SELF_CLOSE_NEW_LINE);
return sb.toString();
}
}
private static class IfSystemProperty extends Condition {
private final String value;
public IfSystemProperty(String name, String value) {
super(IF_SYSTEM_PROPERTY_ELEMENT_NAME, name);
this.value = value;
}
public String getValue() {
return this.value;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(OPENING_TAG_PREFIX).append(getTagName());
appendAttribute(NAME_ATTRIBUTE_NAME, getName(), sb);
if (value != null) {
appendAttribute(VALUE_ATTRIBUTE_NAME, getValue(), sb);
}
sb.append(TAG_SUFFIX_SELF_CLOSE_NEW_LINE);
return sb.toString();
}
}
private static class IfClassAvailable extends Condition {
public IfClassAvailable(String className) {
super(IF_CLASS_AVAILABLE_ELEMENT_NAME, className);
}
}
private static class IfClassNotAvailable extends Condition {
public IfClassNotAvailable(String className) {
super(IF_CLASS_NOT_AVAILABLE_ELEMENT_NAME, className);
}
}
}
public BeansXml() {
this(new ArrayList<Class<?>>(), new ArrayList<Class<?>>(), new ArrayList<Class<?>>(), new ArrayList<Class<?>>(), new ArrayList<Exclude>());
}
public BeansXml(BeanDiscoveryMode mode) {
this();
setBeanDiscoveryMode(mode);
}
private BeansXml(List<Class<?>> alternatives, List<Class<?>> interceptors, List<Class<?>> decorators, List<Class<?>> stereotypes, List<Exclude> excludeFilters) {
this.alternatives = alternatives;
this.interceptors = interceptors;
this.decorators = decorators;
this.stereotypes = stereotypes;
this.excludeFilters = excludeFilters;
}
public BeansXml alternatives(Class<?>... alternatives) {
this.alternatives.addAll(Arrays.asList(alternatives));
return this;
}
public BeansXml interceptors(Class<?>... interceptors) {
this.interceptors.addAll(Arrays.asList(interceptors));
return this;
}
public BeansXml decorators(Class<?>... decorators) {
this.decorators.addAll(Arrays.asList(decorators));
return this;
}
public BeansXml stereotype(Class<?>... stereotypes) {
this.stereotypes.addAll(Arrays.asList(stereotypes));
return this;
}
public BeansXml excludeFilters(Exclude... filters) {
this.excludeFilters.addAll(Arrays.asList(filters));
return this;
}
public BeanDiscoveryMode getBeanDiscoveryMode() {
return mode;
}
public void setBeanDiscoveryMode(BeanDiscoveryMode mode) {
this.mode = mode;
}
@Override
public InputStream openStream() {
StringBuilder xml = new StringBuilder();
xml.append("<beans version=\"1.1\" bean-discovery-mode=\"");
xml.append(getBeanDiscoveryMode().getValue());
xml.append("\">\n");
appendExcludeFilters(excludeFilters, xml);
appendAlternatives(alternatives, stereotypes, xml);
appendSection("interceptors", CLASS, interceptors, xml);
appendSection("decorators", CLASS, decorators, xml);
xml.append("</beans>");
return new ByteArrayInputStream(xml.toString().getBytes());
}
private void appendExcludeFilters(List<Exclude> filters, StringBuilder xml) {
if (filters.size() > 0) {
xml.append(OPENING_TAG_PREFIX).append(SCAN_ELEMENT_NAME).append(TAG_SUFFIX_NEW_LINE);
for(Exclude ex : filters) {
xml.append(OPENING_TAG_PREFIX).append(EXCLUDE_ELEMENT_NAME);
appendAttribute(NAME_ATTRIBUTE_NAME, ex.getClassFilter(), xml);
List<Exclude.Condition> conditions = ex.getConditions();
if(conditions.isEmpty()) {
xml.append(TAG_SUFFIX_SELF_CLOSE_NEW_LINE);
} else {
xml.append(TAG_SUFFIX_NEW_LINE);
for (Exclude.Condition c : conditions) {
xml.append(c.toString());
}
xml.append(CLOSING_TAG_PREFIX).append(EXCLUDE_ELEMENT_NAME).append(TAG_SUFFIX_NEW_LINE);
}
}
xml.append(CLOSING_TAG_PREFIX).append(SCAN_ELEMENT_NAME).append(TAG_SUFFIX_NEW_LINE);
}
}
private static void appendAttribute(String name, String value, StringBuilder xml) {
xml.append(" ").append(name).append("=\"").append(value).append("\"");
}
private static void appendAlternatives(List<Class<?>> alternatives, List<Class<?>> stereotypes, StringBuilder xml) {
if (alternatives.size() > 0 || stereotypes.size() > 0) {
xml.append(OPENING_TAG_PREFIX).append(ALTERNATIVES_ELEMENT_NAME).append(TAG_SUFFIX_NEW_LINE);
appendClasses(CLASS, alternatives, xml);
appendClasses("stereotype", stereotypes, xml);
xml.append(CLOSING_TAG_PREFIX).append(ALTERNATIVES_ELEMENT_NAME).append(TAG_SUFFIX_NEW_LINE);
}
}
private static void appendSection(String name, String subName, List<Class<?>> classes, StringBuilder xml) {
if (classes.size() > 0) {
xml.append(OPENING_TAG_PREFIX).append(name).append(TAG_SUFFIX_NEW_LINE);
appendClasses(subName, classes, xml);
xml.append(CLOSING_TAG_PREFIX).append(name).append(TAG_SUFFIX_NEW_LINE);
}
}
private static void appendClasses(String name, List<Class<?>> classes, StringBuilder xml) {
for (Class<?> clazz : classes) {
xml.append(OPENING_TAG_PREFIX).append(name).append(TAG_SUFFIX).append(clazz.getName()).append(CLOSING_TAG_PREFIX).append(name).append(TAG_SUFFIX_NEW_LINE);
}
}
}