package net.sourceforge.javautil.groovy.dsl.impl.standard;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;
import groovy.lang.MetaClass;
import net.sourceforge.javautil.common.ReflectionUtil;
import net.sourceforge.javautil.common.classloader.ClassLoaderClassGroup;
import net.sourceforge.javautil.common.classloader.ClassLoaderResource;
import net.sourceforge.javautil.common.classloader.ClassLoaderScanner;
import net.sourceforge.javautil.groovy.dsl.GroovyDSL;
import net.sourceforge.javautil.groovy.dsl.GroovyDSLManager;
import net.sourceforge.javautil.groovy.dsl.GroovyDSLMethod;
import net.sourceforge.javautil.groovy.dsl.GroovyDSLProperty;
/**
* A standard GroovyDSL manager.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public class GroovyDSLManagerStandard implements GroovyDSLManager {
public static final String DEFAULT_RESOURCE = "META-INF/services/net.sf.javautil.dsl";
protected boolean initialized = false;
protected Map<String, List<GroovyDSL>> lookup = new HashMap<String, List<GroovyDSL>>();
protected final String resourceName;
protected final Pattern[] patterns;
public GroovyDSLManagerStandard () { this(DEFAULT_RESOURCE, Pattern.compile(".*DSL.class")); }
public GroovyDSLManagerStandard(String resourceName, Pattern... patterns) {
this.resourceName = resourceName;
this.patterns = patterns;
}
public GroovyDSLManager initialize() {
if (!initialized) {
ClassLoaderScanner scanner = new ClassLoaderScanner();
scanner.setDirectoryResourceName(this.resourceName);
for (Pattern pattern : patterns) scanner.addInclusion(pattern);
ClassLoaderClassGroup group = scanner.getClasses(GroovyDSL.class, Object.class);
List<GroovyDSL> groovyDSLs = group.getInstances(GroovyDSL.class);
for (Class categoryClass : group.getClasses(Object.class)) {
groovyDSLs.add( new GroovyDSLCategoryClass(categoryClass) );
}
this.initialize(groovyDSLs);
}
return this;
}
/**
* This can be called instead of {@link #initialize()} in order to all the
* finding of {@link GroovyDSL}'s to be customized.
*
* @param dsls The list of DSL to use in initializing this manager.
*/
public synchronized void initialize (List<GroovyDSL> dsls) {
if (initialized) return;
initialized = true;
synchronized (lookup) {
for (GroovyDSL dsl : dsls) {
for (Class<?> clazz : dsl.getForClasses()) {
String cname = clazz.getName();
if (!lookup.containsKey(cname)) lookup.put(cname, new CopyOnWriteArrayList<GroovyDSL>());
lookup.get(cname).add(dsl);
}
}
}
}
public synchronized void register(GroovyDSL dsl) {
synchronized (lookup) {
for (Class<?> clazz : dsl.getForClasses()) {
String cname = clazz.getName();
if (!lookup.containsKey(cname)) lookup.put(cname, new ArrayList<GroovyDSL>());
lookup.get(cname).add(dsl);
}
}
}
public GroovyDSLMethod findMethod(MetaClass clazz, Object instance, String name, Object... arguments) {
List<GroovyDSL> dsls = this.lookup.get(instance instanceof Class ? "java.lang.Class" : clazz.getTheClass().getName());
if (dsls != null) {
Iterator<GroovyDSL> dsli = dsls.iterator();
while (dsli.hasNext()) {
GroovyDSL dsl = dsli.next();
GroovyDSLMethod method = dsl.getMethod(clazz, instance, name, arguments);
if (method != null) return method;
}
}
return null;
}
public GroovyDSLProperty findProperty(MetaClass clazz, Object instance, String name) {
List<GroovyDSL> dsls = this.lookup.get(instance instanceof Class ? "java.lang.Class" : clazz.getTheClass().getName());
if (dsls != null) {
Iterator<GroovyDSL> dsli = dsls.iterator();
while (dsli.hasNext()) {
GroovyDSL dsl = dsli.next();
GroovyDSLProperty property = dsl.getProperty(clazz, instance, name);
if (property != null) return property;
}
}
return null;
}
}