package org.bindgen.processor.config;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import org.bindgen.binding.AbstractBinding;
import org.bindgen.processor.CurrentEnv;
import org.bindgen.processor.util.ClassName;
import org.bindgen.processor.util.ConfUtil;
/**
* Bindgen configuration.
*
* This class encapsulates all code that is responsible for making
* decisions that can be affected by configuration options.
*
* @author igor.vaynberg
*/
public class BindgenConfig {
private static final String SCOPE_PARAM = "scope";
private final Map<String, String> options = new HashMap<String, String>();
private final Scope<ClassName> bindingScope;
public BindgenConfig(ProcessingEnvironment env) {
this.loadDefaultOptions();
this.loadAptKeyValueOptions(env);
this.loadBindgenDotProperties(env);
this.bindingScope = this.getBindingScope();
}
public boolean shouldGenerateBindingFor(TypeElement type) {
return this.shouldGenerateBindingFor(new ClassName(type.getQualifiedName().toString()));
}
public boolean shouldGenerateBindingFor(ClassName name) {
return this.bindingScope.includes(name);
}
public boolean logEnabled() {
return this.isEnabled("log");
}
public boolean skipBindKeyword() {
return this.isEnabled("skipBindKeyword");
}
public boolean skipExistingBindingCheck() {
String explicit = this.options.get("skipExistingBindingCheck");
if (explicit != null) {
return "true".equals(explicit);
}
// javac doesn't like skipping existing bindings , so default to true if in javac
return CurrentEnv.get().getClass().getName().startsWith("com.sun");
}
public String baseNameForBinding(ClassName cn) {
String pn = cn.getPackageName();
if (pn.startsWith("java.") || pn.startsWith("javax.")) {
pn = "org.bindgen." + pn;
}
if (pn.isEmpty()) {
return cn.getSimpleName();
} else {
return pn + "." + cn.getSimpleName();
}
}
/** @return the fully qualified name of the super class of all Bindings - useful for integration */
public String bindingPathSuperClassName() {
return this.options.get("bindingPathSuperClass");
}
/** @return a list of class names to match void methods against for callable bindings */
public String[] blockTypesToAttempt() {
String attempts = this.options.get("blockTypes");
if (attempts == null) {
attempts = "java.lang.Runnable";
} else {
attempts += ",java.lang.Runnable";
}
return attempts.split(",");
}
/** @return whether the {@code @Generated} annotations should be added to the source output */
public boolean skipGeneratedTimestamps() {
return this.isEnabled("skipGeneratedTimestamps");
}
/** @return whether the field/method {@code name} of {@code element} should be skipped */
public boolean skipAttribute(Element element, String name) {
return this.isEnabled("skipAttribute." + element.toString() + "." + name);
}
/** @return the type parameter to fill in for a raw type or null */
public String fixedRawType(Element element, String name) {
return this.options.get("fixRawType." + element.toString() + "." + name);
}
private boolean isEnabled(String key) {
return "true".equals(this.options.get(key));
}
private Scope<ClassName> getBindingScope() {
final String scopeExpression = this.options.get(SCOPE_PARAM);
if (scopeExpression != null && scopeExpression.trim().length() > 0) {
return new PackageExpressionScope(scopeExpression);
} else {
return new GlobalScope<ClassName>();
}
}
// Default properties--this is ugly, but I could not get a bindgen.properties to be found on the classpath
private void loadDefaultOptions() {
this.options.put("fixRawType.javax.servlet.ServletConfig.initParameterNames", "String");
this.options.put("fixRawType.javax.servlet.ServletContext.attributeNames", "String");
this.options.put("fixRawType.javax.servlet.ServletContext.initParameterNames", "String");
this.options.put("fixRawType.javax.servlet.ServletRequest.attributeNames", "String");
this.options.put("fixRawType.javax.servlet.ServletRequest.parameterNames", "String");
this.options.put("fixRawType.javax.servlet.ServletRequest.locales", "Locale");
this.options.put("fixRawType.javax.servlet.ServletRequest.parameterMap", "String, String[]");
this.options.put("fixRawType.javax.servlet.http.HttpServletRequest.headerNames", "String");
this.options.put("fixRawType.javax.servlet.http.HttpSession.attributeNames", "String");
this.options.put("skipAttribute.javax.servlet.http.HttpSession.sessionContext", "true");
this.options.put("skipAttribute.javax.servlet.http.HttpServletRequest.requestedSessionIdFromUrl", "true");
this.options.put("skipAttribute.javax.servlet.ServletContext.servletNames", "true");
this.options.put("skipAttribute.javax.servlet.ServletContext.servlets", "true");
this.options.put("skipAttribute.java.lang.Object.getClass", "true");
this.options.put("skipAttribute.java.lang.Object.notify", "true");
this.options.put("skipAttribute.java.lang.Object.notifyAll", "true");
this.options.put("bindingPathSuperClass", AbstractBinding.class.getName());
}
private void loadBindgenDotProperties(ProcessingEnvironment env) {
this.options.putAll(ConfUtil.loadProperties(env, "bindgen.properties"));
}
private void loadAptKeyValueOptions(ProcessingEnvironment env) {
for (Map.Entry<String, String> entry : env.getOptions().entrySet()) {
this.options.put(entry.getKey(), entry.getValue());
}
}
}