package jfun.yan.xml;
import java.beans.IntrospectionException;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jfun.util.Misc;
import jfun.util.dict.Dict;
import jfun.util.dict.DictFactory;
import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.Creator;
import jfun.yan.ParameterBinder;
import jfun.yan.PropertyBinder;
import jfun.yan.Registrar;
import jfun.yan.containers.ManualContainer;
import jfun.yan.factory.Factory;
import jfun.yan.lifecycle.DefaultLifecycleManager;
import jfun.yan.util.deserializer.Deserializer;
import jfun.yan.util.resource.ClassLoader2ResourceLoader;
import jfun.yan.util.resource.ResourceLoader;
import jfun.yan.xml.nut.Nut;
import jfun.yan.xml.nut.NutDescriptor;
import jfun.yan.xml.nut.NutIntrospector;
import org.xml.sax.InputSource;
/**
* The main class that parses an xml config file and populates
* container and lifecycle manager with the information stored
* in the config file.
* <p>
* @author Ben Yu
*
*/
public class NutsProcessor implements java.io.Serializable{
private Map getDeserializers(){
final Map deserializers = NutsUtils.getDeserializers();
deserializers.put(File.class, new Deserializer(){
public Object deserialize(String str) throws Exception {
return NutsUtils.toFile(getBaseDir(), str);
}
});
deserializers.put(Class.class, new Deserializer(){
public Object deserialize(String str) throws Exception {
return MyUtil.getClass(getClassLoader(), str);
}
});
deserializers.put(URL.class, new Deserializer(){
public Object deserialize(String str) throws Exception {
return NutsUtils.toUrl(getBaseDir(), str);
}
});
deserializers.put(SingletonMode.class, new SingletonModeEditor());
return deserializers;
}
private final DefaultLifecycleManager manager;
private final Container yan;
private final ClassLoader cloader;
private final ResourceLoader rloader;
private final File basedir;
private final Map deserializers = getDeserializers();
private final Map services = new Hashtable();
private final Map external_nuts = new Hashtable();
private final Map eager_instantiations = new Hashtable();
private final Map variables = new Hashtable();
private ParameterBinder param_wiring = null;
private PropertyBinder prop_wiring = null;
private SingletonMode singleton_mode = Modes.simple_singleton;
private static final NutIntrospector introspector = new NutIntrospector();
private static final class CustomWiringModes implements AutoWiringMap{
private final Map prop_wiring_modes = new Hashtable();
private final Map param_wiring_modes = new Hashtable();
void addWiringMode(String name, ParameterBinder pmode){
param_wiring_modes.put(canonicalize(name),
pmode);
}
void addWiringMode(String name, PropertyBinder pmode){
prop_wiring_modes.put(canonicalize(name), pmode);
}
private static String canonicalize(String name){
return NutsUtils.canonicalizeAttributeName(name);
}
public ParameterBinder getParameterWiringMode(String mode_name) {
return (ParameterBinder)param_wiring_modes.get(canonicalize(mode_name));
}
public PropertyBinder getPropertyWiringMode(String mode_name) {
return (PropertyBinder)prop_wiring_modes.get(canonicalize(mode_name));
}
}
private final CustomWiringModes custom_wiring_modes = new CustomWiringModes();
private Interpreter createInterpreter(){
return new Interpreter(this, getInitialFrame(), this.getInitialCompileContext());
}
private Dict bindVariables(Dict ctxt){
synchronized(variables){
final Object[] keys = variables.keySet().toArray();
final Object[] vals = new Object[keys.length];
for(int i=0; i<keys.length; i++){
vals[i] = variables.get(keys[i]);
}
return ctxt.puts(keys, vals);
//.put(Constants.THIS_CONTAINER, Components.thisContainer());
}
}
private Dict getInitialFrame(){
return bindVariables(DictFactory.safeInstance().put(Constants.NULL, null));
}
private Dict getInitialCompileContext(){
return bindVariables(DictFactory.instance()
.put(Constants.NULL, MyUtil.value(null, new Location("SYSTEM", 0, 0)))
);
}
private String[] processModule(Module module){
module.register(toRegistry(yan));
registerDynamics(this.yan);
return (String[])module.getDependencies().clone();
}
/**
* Create a NutsProcessor object.
* <p>
* The ClassLoader object that loads this class
* is used to load the nut classes and the component classes.
* </p>
*/
public NutsProcessor(){
this(NutsProcessor.class.getClassLoader());
}
/**
* Create an NutsProcessor object.
* @param classloader the ClassLoader object to load component classes and resources.
*/
public NutsProcessor(ClassLoader classloader){
this(classloader, new ClassLoader2ResourceLoader(classloader));
}
/**
* Create an NutsProcessor object.
* @param classloader the ClassLoader object to load component classes.
* @param rloader the ResourceLoader object to load resources.
*/
public NutsProcessor(ClassLoader classloader, ResourceLoader rloader){
this(classloader, rloader, new ManualContainer());
}
/**
* Create an NutsProcessor object.
* @param cloader the ClassLoader object to load component classes and resources.
* @param yan the container that registers the components.
* @param manager the life cycle manager.
* @param basedir the base directory against which relative paths
* found in the config file can be resolved.
*/
public NutsProcessor(ClassLoader cloader, Container yan,
DefaultLifecycleManager manager,
File basedir) {
this(cloader, new ClassLoader2ResourceLoader(cloader), yan, manager, basedir);
}
/**
* Create an NutsProcessor object.
* @param cloader the ClassLoader object to load component classes.
* @param rloader the ResourceLoader object to load resources.
* @param yan the container that registers the components.
* @param manager the life cycle manager.
* @param basedir the base directory against which relative paths
* found in the config file can be resolved.
*/
public NutsProcessor(ClassLoader cloader, ResourceLoader rloader,
Container yan,
DefaultLifecycleManager manager,
File basedir) {
this.basedir = basedir;
this.cloader = cloader;
this.rloader = rloader;
this.manager = manager;
this.yan = yan;
this.variables.put(Constants.THIS_CONTAINER, Components.thisContainer());
this.variables.put(Constants.RESOURCE_LOADER, rloader);
}
/**
* Create an NutsProcessor object.
* @param cloader the ClassLoader to load the component classes and resources.
* @param yan the container that registeres the components.
*/
public NutsProcessor(ClassLoader cloader, Container yan){
this(cloader, new ClassLoader2ResourceLoader(cloader), yan);
}
/**
* Create an NutsProcessor object.
* @param cloader the ClassLoader to load the component classes.
* @param rloader the ResourceLoader to load resources.
* @param yan the container that registeres the components.
*/
public NutsProcessor(ClassLoader cloader, ResourceLoader rloader,
Container yan){
this(cloader, rloader, yan,
new DefaultLifecycleManager(), new File(".").getAbsoluteFile());
}
/**
* Convert a string literal to an object of a certain type.
* A PropertyEditor is searched if the deserialization of the target type
* is not supported by the framework by default.
* @param type the target type.
* @param v the string literal.
* @return the object of the target type.
* @throws Throwable when any error happens.
*/
public Object deserialize(Class type, String v)
throws Throwable{
final Deserializer des = (Deserializer)deserializers.get(type);
if(des != null) return des.deserialize(v);
else{
final PropertyEditor editor = PropertyEditorManager.findEditor(type);
if(editor==null){
throw new IllegalArgumentException("cannot convert to "+
Misc.getTypeName(type));
}
else{
editor.setAsText(v);
return editor.getValue();
}
}
}
/**
* To determine if string literal can be converted to the target type.
* PropertyEditor is also searched if the type is not by default
* deserializable by the framework
* @param type the target type.
* @return true if convertible.
*/
public boolean isDeserializable(Class type){
return type.isAssignableFrom(String.class)
|| deserializers.get(type)!=null
|| PropertyEditorManager.findEditor(type)!=null;
}
private synchronized String[] process(Object id, final InputSource in)
throws IOException{
return processModule(createInterpreter()
.interpret(id, in));
}
/**
* Process a resource from the component class loader as an xml configuration.
* @param resourcename the resource name.
* @return an array of dependency names that the module requires
* to be present in the container in order for the module to
* wire up properly.
* An empty array is returned if there's no dependency required.
* @throws IOException when resource reading fails.
*/
public synchronized String[] processResource(final String resourcename)
throws IOException{
return processModule(createInterpreter()
.interpretResource(resourcename));
}
/**
* Process a config file.
* @param filename the configuration file name.
* @return an array of dependency names that the module requires
* to be present in the container in order for the module to
* wire up properly.
* An empty array is returned if there's no dependency required.
* @throws IOException if file reading fails.
*/
public synchronized String[] processFile(String filename)
throws IOException{
return processFile(new File(filename));
//processModule(createInterpreter().interpretFile(filename));
}
/**
* Process a config file.
* @param file the configuration file.
* @return an array of dependency names that the module requires
* to be present in the container in order for the module to
* wire up properly.
* An empty array is returned if there's no dependency required. An empty array is returned if there's no dependency required.
* @throws IOException if file reading fails.
*/
public synchronized String[] processFile(File file)
throws IOException{
return processModule(createInterpreter()
.interpretFile(file));
}
/**
* Process bytes read from an InputStream.
* @param id the module id.
* @param in the InputStream object.
* @return an array of dependency names that the module requires
* to be present in the container in order for the module to
* wire up properly.
* An empty array is returned if there's no dependency required.
* @throws IOException any io error.
*/
public synchronized String[] process(Object id, InputStream in)
throws IOException{
return processModule(createInterpreter().interpret(id, in));
}
/**
* Pre-initialize eagerly instantiated components.
* @param container the container to resolve dependency for these components.
* @param store the Map object to collect the instantiated results.
* The map key is {@link UID}, which is a combination of the module id and the component id.
* @return reference to the Map object.
*/
public Map preInstantiate(Container container, Map store){
final UID[] keys = getOrderedUIDs();
for(int i=0; i<keys.length; i++){
final UID key = keys[i];
final Creator c = (Creator)eager_instantiations.get(key);
store.put(key, container.instantiateComponent(key, c));
}
return store;
}
/**
* Pre-initialize eagerly instantiated components.
* @param container the container to resolve dependency for these components.
* @return the Map object to collect the instantiated results.
* The map key is {@link UID}, which is a combination of the module id and the component id.
*/
public Map preInstantiate(Container container){
return preInstantiate(container, new HashMap());
}
/**
* Pre-initialize eagerly instantiated components.
* @param store the Map object to collect the instantiated results.
* The map key is {@link UID}, which is a combination of the module id and the component id.
* @return reference to the Map object.
*/
public Map preInstantiate(Map store){
return preInstantiate(yan, store);
}
/**
* Pre-initialize eagerly instantiated components.
* @return the Map object to collect the instantiated results.
* The map key is {@link UID}, which is a combination of the module id and the component id.
*/
public Map preInstantiate(){
return preInstantiate(yan);
}
/**
* To get the lifecycle manager used by this processor.
*/
public DefaultLifecycleManager getLifecycleManager() {
return manager;
}
/**
* To get the container used by this processor.
*/
public Container getContainer() {
return yan;
}
/**
* To get the base directory used by the processor.
*/
public File getBaseDir() {
return basedir;
}
/**
* To get the ClassLoader used to load component classes.
*/
public ClassLoader getClassLoader() {
return cloader;
}
/**
* To get the ResourceLoader used to load resources.
*/
public ResourceLoader getResourceLoader(){
return rloader;
}
/**
* Register a property autowiring mode. Any existent mode or predefined mode
* with the same name will be overriden.
* @param mode_name the mode name.
* @param mode the PropertyBinder object encapsulating the autowiring logic.
*/
public void registerAutoWiring(String mode_name, PropertyBinder mode){
custom_wiring_modes.addWiringMode(mode_name, mode);
}
/**
* Register a parameter autowiring mode. Any existent mode or predefined mode
* with the same name will be overriden.
* @param mode_name the mode name.
* @param mode the ParameterBinder object encapsulating the autowiring logic.
*/
public void registerAutoWiring(String mode_name, ParameterBinder mode){
custom_wiring_modes.addWiringMode(mode_name, mode);
}
/**
* To register a Deserializer.
* @param type the type that uses the Deserializer to convert
* literal string to objects of this type.
* @param deserializer the Deserializer object.
* @param overriding whether override the existent Deserializer if any.
* @param mandatory true if this registration has to go through.
* @exception IllegalArgumentException if the registration is mandatory but not overriding
* and an Deserializer object is already registered for the target type.
*/
public void registerDeserializer(Class type, Deserializer deserializer,
boolean overriding, boolean mandatory)
throws IllegalArgumentException{
if(!overriding){
if(deserializers.containsKey(type)){
if(mandatory){
throw new IllegalArgumentException("Deserializer for "
+ type + " already exists");
}
else return;
}
}
deserializers.put(type, deserializer);
}
/**
* To find the service object registered using
* {@link #registerService(Object, Object)}.
* @param key the key to the service object.
* @return the service object.
* null is returned if no object is registered under this key.
*/
public Object findService(Object key){
return services.get(key);
}
/**
* To register a service object that can be read by customized Nuts classes
* through the call of {@link NutEnvironment#findService(Object)}.
* <p>
* register and unregister are thread safe.
* </p>
* @param key the service key.
* @param service the service object.
*/
public void registerService(Object key, Object service){
services.put(key, service);
}
/**
* To unregister a service object. No-op if the key is not found.
* @param key the key of the service object.
*/
public void unregisterService(Object key){
services.remove(key);
}
/**
* Get the set of the keys of the service objects.
*/
public Set getServiceKeys(){
return services.keySet();
}
/**
* Add an external nut descriptor for the processor to use.
* @param key the key of the nut.
* @param desc the descriptor.
*/
public void registerNut(String key, NutDescriptor desc){
external_nuts.put(key, desc);
}
/**
* Get a NutDescriptor registered by putNut().
* @param key the key of the NutDescriptor.
* @return the NutDescriptor object.
* Null is returned if the key is not found.
*/
public NutDescriptor findNut(String key){
return (NutDescriptor)external_nuts.get(key);
}
/**
* Unregister a NutDescriptor.
* @param key the key of the NutDescriptor.
*/
public void removeNut(String key){
external_nuts.remove(key);
}
/**
* Register a variable that can be referenced in the xml file
* using "$varname" syntax.
* @param key the variable name.
* @param val the variable value.
*/
public void registerVariable(String key, Object val){
variables.put(key, val);
}
/**
* To get a variable value.
* @param key the variable name.
* @return the variable value. Or null if not found.
*/
public Object getVariable(String key){
return variables.get(key);
}
/**
* Checks whether a variable name exists.
* @param key the variable name.
*/
public boolean hasVariable(String key){
return variables.containsKey(key);
}
/**
* To remove a registration of a variable.
* @param key the variable name.
*/
public void removeVariable(String key){
variables.remove(key);
}
/**
* Get the set of keys of Nut descriptors.
*/
public Set getNutKeys(){
return external_nuts.keySet();
}
/**
* Get the default parameter auto wiring mode.
*/
public synchronized ParameterBinder getParameterWiring() {
return param_wiring;
}
/**
* Set the default parameter auto-wiring mode.
* @param param_wiring the wiring mode. Null if auto-wiring is disabled.
*/
public synchronized void setParameterWiring(ParameterBinder param_wiring) {
this.param_wiring = param_wiring;
}
/**
* Get the default property auto-wiring mode.
*/
public synchronized PropertyBinder getPropertyWiring() {
return prop_wiring;
}
/**
* Set the default property auto-wiring mode.
* @param prop_wiring the wiring mode.
* Null if auto-wiring is disabled.
*/
public synchronized void setPropertyWiring(PropertyBinder prop_wiring) {
this.prop_wiring = prop_wiring;
}
/**
* Get the default singleton mode.
*/
public synchronized SingletonMode getSingletonMode() {
return singleton_mode;
}
/**
* Set the default singleton mode.
* @param singleton_mode the singleton mode.
* Null if prototype is used.
*/
public synchronized void setSingletonMode(SingletonMode singleton_mode) {
this.singleton_mode = singleton_mode;
}
/**
* Create an NutsProcessor object that's gonna be used to
* load meta configuration of Nut classes.
* <p>
* The default singleton mode is "off" and the default parameter auto-wiring
* mode is "bytype".
* </p>
* <p>
* All the service objects and externally registered nuts descriptors
* will be copied to this new NutsProcessor object.
* </p>
* <p>
* It is fine to create an NutsProcessor object by calling
* the constructor directly.
* Any NutsProcessor object can be used to interpret meta configuration.
* </p>
* <p>
* This method just makes it more convenient
* to set the default settings and copy the existing service objects
* and externally registered nut descriptors.
* </p>
* @param loader The class loader to load classes.
* @param rloader the ResourceLoader to load resources.
* @return the new NutsProcessor object.
*/
public synchronized NutsProcessor createMetaProcessor(ClassLoader loader,
ResourceLoader rloader){
final NutsProcessor aux = new NutsProcessor(loader, rloader, new ManualContainer(),
manager, basedir);
aux.setSingletonMode(null);
aux.setParameterWiring(Modes.params_bytype);
aux.services.putAll(services);
aux.external_nuts.putAll(external_nuts);
return aux;
}
/**
* Create an NutsProcessor object that's gonna be used to
* load meta configuration of Nut classes.
* <p>
* The default singleton mode is "off" and the default parameter auto-wiring
* mode is "bytype".
* </p>
* <p>
* All the service objects and externally registered nuts descriptors
* will be copied to this new NutsProcessor object.
* </p>
* <p>
* It is fine to create an NutsProcessor object by calling
* the constructor directly.
* Any NutsProcessor object can be used to interpret meta configuration.
* </p>
* <p>
* This method just makes it more convenient
* to set the default settings and copy the existing service objects
* and externally registered nut descriptors.
* </p>
* @param loader The class loader to load classes and resources.
* @return the new NutsProcessor object.
*/
public NutsProcessor createMetaProcessor(ClassLoader loader){
return createMetaProcessor(loader, new ClassLoader2ResourceLoader(loader));
}
/**
* Create an NutsProcessor object that's gonna be used to
* load meta configuration of Nut classes.
* <p>
* The component classloader is used to load classes.
* </p>
* <p>
* The default singleton mode is "off" and the default parameter auto-wiring
* mode is "bytype".
* </p>
* <p>
* All the service objects and externally registered nuts descriptors
* will be copied to this new NutsProcessor object.
* </p>
* <p>
* It is fine to create an NutsProcessor object by calling
* the constructor directly.
* Any NutsProcessor object can be used to interpret meta configuration.
* </p>
* <p>
* This method just makes it more convenient
* to set the default settings and copy the existing service objects
* and externally registered nut descriptors.
* </p>
* @return the new NutsProcessor object.
*/
public NutsProcessor createMetaInterpreter(){
return createMetaProcessor(cloader, rloader);
}
/**
* Load descriptors of the nut classes registered in a Container.
* @param nuts the container containing nut components.
*/
public synchronized void loadNutsFromContainer(Container nuts){
final HashMap descs = new HashMap();
populateNuts(nuts, descs);
addNuts(nuts, descs);
}
private static void populateNuts(Container nuts, Map descs){
final Set nutkeys = nuts.keys();
for(Iterator it=nutkeys.iterator(); it.hasNext();){
final Object key = it.next();
if(!(key instanceof String)){
//non-configured component, skip.
continue;
}
final Component c = nuts.getComponent(key);
final Class type = c.getType();
if(type==null){
throw new IllegalArgumentException("unknown type for nut component "+key
+ ", consider using 'type' attribute to explicitly specify the type for it");
}
if(!Nut.class.isAssignableFrom(type)){
//not nut class, helper type.
continue;
/*
if(type.isAssignableFrom(Nut.class)){
throw new IllegalArgumentException("nut component "+key
+ " is of type " + Misc.getTypeName(type)
+ ", not a subtype of Nut.\nconsider using 'type' attribute to explicitly specify the type.");
}
else{
throw new IllegalArgumentException("nut component "+key
+ " is of type "+Misc.getTypeName(type)
+", not a subtype of Nut.");
}*/
}
try{
final NutDescriptor desc = introspector.getNutDescriptor(type);
descs.put(key, desc);
}
catch(IntrospectionException e){
throw new IllegalArgumentException("failed to introspect type "+Misc.getTypeName(type));
}
//nuts.registerComponent(key, c.factory());
}
}
private synchronized void addNuts(Container nuts, Map descs){
for(Iterator it=descs.keySet().iterator();it.hasNext();){
final Object key = it.next();
final NutDescriptor desc = (NutDescriptor)descs.get(key);
final Factory factory = nuts.getFactory(key);
desc.setFactory(factory);
registerNut(key.toString(), desc);
}
}
private void prewireNuts(Object id, ClassLoader loader, ResourceLoader rloader, InputSource in)
throws IOException{
final NutsProcessor aux = createMetaProcessor(loader, rloader);
final Container nuts = aux.getContainer();
aux.process(id, in);
loadNutsFromContainer(nuts);
}
/**
* Load a configuration file that wires Nut classes.
* The Nut descriptors and their ids loaded from this file will be used
* during interpretation of regular configuration files for components.
* <p>
* By default, singleton mode in a nuts meta file is disabled.
* </p>
* @param loader the class loader to load classes during interpretation.
* @param rloader the
* @param filename the config file containing the nuts class wiring.
* @throws IOException when file reading fails.
*/
public void loadNutsMetaFile(ClassLoader loader, ResourceLoader rloader,
String filename)
throws IOException{
final File file = Misc.getAbsolutePath(basedir, new File(filename));
prewireNuts(file, loader, rloader, new InputSource(filename));
}
/**
* Load configuration information from an InputStream and wires Nut classes.
* The Nut descriptors and their ids loaded from this InputStream will be used
* during interpretation of regular configuration files for components.
* <p>
* By default, singleton mode is disabled.
* </p>
* @param loader the class loader to load classes during interpretation.
* @param rloader the ResourceLoader to load resources during interpretation.
* @param in the stream containing meta configuration information.
* @throws IOException when file reading fails.
*/
public void loadNutsMetaData(Object id, ClassLoader loader,
ResourceLoader rloader, InputStream in)
throws IOException{
prewireNuts(id, loader, rloader, new InputSource(in));
}
/**
* Load a configuration file that wires Nut classes.
* The Nut descriptors and their ids loaded from this file will be used
* during interpretation of regular configuration files for components.
* <p>
* By default, singleton mode in a nuts meta file is disabled.
* </p>
* <p>
* The component classloader is used to load these nuts classes.
* </p>
* @param filename the config file containing the nuts class wiring.
* @throws IOException when file reading fails.
*/
public void loadNutsMetaFile(String filename)
throws IOException{
loadNutsMetaFile(filename);
}
/**
* Load configuration information from an InputStream and wires Nut classes.
* The Nut descriptors and their ids loaded from this InputStream will be used
* during interpretation of regular configuration files for components.
* <p>
* By default, singleton mode is disabled.
* </p>
* <p>
* The component classloader is used to load these nuts classes.
* </p>
* @param in the stream containing meta configuration information.
* @throws IOException when file reading fails.
*/
public void loadNutsMetaData(Object id, InputStream in)
throws IOException{
loadNutsMetaData(id, cloader, rloader, in);
}
/**
* Load configuration information from a resource loaded
* by the component class loader.
* Nuts classes are wired using this configuration information.
* <p>
* The Nut descriptors and their ids loaded from this InputStream will be used
* during interpretation of regular configuration files for components.
* </p>
* <p>
* By default, singleton mode is disabled.
* </p>
* <p>
* The component classloader is used to load these nuts classes.
* </p>
* @param resourcename the name of the resource containing meta configuration
* information.
* @throws IOException when file reading fails.
*/
public void loadNutsMetaResource(String resourcename)
throws IOException{
final URL url = rloader.getResource(resourcename);
final InputStream in = MyUtil.readResource(this.rloader, resourcename);
try{
loadNutsMetaData(url, this.cloader, rloader, in);
}
finally{
in.close();
}
}
private static Registry toRegistry(final Registrar reg){
return new Registry(){
public void put(String key, Object v, Location loc){
reg.registerComponent(key, NutsUtils.asComponent(v));
}
public String toString(){
return reg.toString();
}
};
}
private final List modules_involved = new ArrayList();
void registerModuleImport(Object module_id){
modules_involved.add(module_id);
}
void registerEagerInstantiation(UID key, Component c){
this.eager_instantiations.put(key, c);
}
Map getExternalNuts(){
return external_nuts;
}
AutoWiringMap getCustomWiringModes(){
return custom_wiring_modes;
}
Map getServices(){
return this.services;
}
private UID[] getOrderedUIDs(){
final Set uids = this.eager_instantiations.keySet();
final UID[] result = new UID[uids.size()];
uids.toArray(result);
Arrays.sort(result, getUIDComparator());
return result;
}
private Comparator getUIDComparator(){
final HashMap module_sequence = new HashMap();
final int sz = modules_involved.size();
for(int i=0; i<sz; i++){
module_sequence.put(modules_involved.get(i), new Integer(i));
}
return new Comparator(){
public int compare(Object arg0, Object arg1) {
final UID id1 = (UID)arg0;
final UID id2 = (UID)arg1;
final Integer module_seq1 = (Integer)module_sequence.get(id1.getModuleId());
final Integer module_seq2 = (Integer)module_sequence.get(id2.getModuleId());
int result = module_seq1.intValue() - module_seq2.intValue();
if(result==0){
result = id1.getDeclarationSequence() - id2.getDeclarationSequence();
if(result == 0){
result = id1.getEvaluationSequence()-id2.getEvaluationSequence();
}
}
return result;
}
public String toString(){
return "UID comparator";
}
};
}
private final NutsRegistrar dynamic_registered = new NutsRegistrar();
void register(Object key, Object val, boolean overridable,
boolean overriding, Location loc){
dynamic_registered.register(key, val, overridable, overriding, loc);
}
private void registerDynamics(Registrar reg){
for(Iterator it=dynamic_registered.keySet().iterator(); it.hasNext();){
final Object key = it.next();
final NutsRegistrar.Entry entry = dynamic_registered.getEntry(key);
if(reg.containsKey(key)){
throw new ConfigurationException("component "+key+" already registered.",
entry.getLocation());
}
reg.registerComponent(key, NutsUtils.asComponent(entry.getValue()));
}
}
}