MentaContainer

Rev

Rev 4 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package org.mentacontainer.impl;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.mentacontainer.Container;

public class MentaContainer implements Container {
       
        private Map<String, Component> beans = new HashMap<String, Component>();
       
        private Map<String, Object> singletons = new HashMap<String, Object>();
       
        private Set<Dependency> dependencies = new HashSet<Dependency>();

        public Object get(String key) {

                if (!beans.containsKey(key)) throw new RuntimeException("Container does not have this bean set: " + key);
               
                Component c = beans.get(key);
               
                Object target = null;
               
                try {
                       
                        if (c.isSingleton()) {
                               
                                if (singletons.containsKey(key)) {
                                       
                                        target = singletons.get(key);
                                       
                                        return target;
                                       
                                } else {
                                       
                                        target = c.getInstance();
                                       
                                        singletons.put(key, target);
                                }
                               
                        } else {
               
                                target = c.getInstance();
                               
                        }
                       
                        if (target != null) {
                               
                                for(Dependency d : dependencies) {

                                    // has dependency ?
                                    Method m = d.getMethod(target.getClass());
                                   
                                    if (m != null) {
                                       
                                        boolean hasAlreadyReceived = d.hasAlreadyReceived(target);
                                       
                                        // has already received the dependency?
                                        if (!hasAlreadyReceived) {
                                               
                                                String sourceKey = d.getSource();
                                               
                                                // get dependency from action input
                                               
                                                if (sourceKey.equals(key)) {
                                                       
                                                        // cannot depend on itself...
                                                        // also avoid recusive StackOverflow...
                                                       
                                                        continue;
                                                       
                                                }
                                               
                                                Object source = get(sourceKey);
                                               
                                                boolean isAssignable = source != null && d.getDependencyClass().isAssignableFrom(source.getClass());
                                                       
                                               
                                            // check if we can find the dependency and if it is assignable to the target dependency
                                            if (isAssignable) {
                       
                                                    try {
                                                       
                       
                                                        // inject
                                                        m.invoke(target, source);
                       
                                                        // flag it has received
                                                        d.setAlreadyReceived(target);
                                                       
                       
                                                    } catch(Exception e) {
                                                       
                                                       
                                                        throw new RuntimeException("AutoWiringFilter cannot inject dependency: method = " + (m != null ? m.getName() : "NULL") + " / source = " + (source != null ? source : "NULL") + " / target = " + target, e);
                                                       
                                                    }
                       
                                            }
                                        }
                                    }
                                }
                        }

                        return target; // return target nicely with all the dependencies injected
                       
                       
                       
                       
                       
                } catch(Exception e) {
                       
                        throw new RuntimeException(e);
                }
        }

        public Container ioc(String key, Class<? extends Object> klass, boolean singleton) {
               
                if (beans.containsKey(key)) throw new RuntimeException("Container already set for the bean key: " + key);
               
                Component c = new Component(klass, singleton);
               
                beans.put(key, c);
               
                return this;
        }
       
        public Container ioc(String key, Class<? extends Object> klass) {
               
                return ioc(key, klass, false);
        }

        public Container autowire(String property, Class<? extends Object> klass, String source) {
               
                Dependency d = new Dependency(property, klass, source);
               
                if (dependencies.contains(d)) throw new RuntimeException("Dependency is already set: " + property);
               
                dependencies.add(d);
               
                return this;
        }

        public Container autowire(String property, Class<? extends Object> klass) {
                return autowire(property, klass, property);
        }

        public Container init(String key, Object value) {

                if (!beans.containsKey(key)) throw new RuntimeException("Container does not have this bean set: " + key);
               
                Component c = beans.get(key);
               
                c.addInitValue(value);
               
                return this;
        }

        public Container set(String key, String name, Object value) {
               
                if (!beans.containsKey(key)) throw new RuntimeException("Container does not have this bean set: " + key);
               
                Component c = beans.get(key);
               
                c.addProperty(name, value);
               
                return this;
        }

        public Container populate(Object bean) {
                // TODO Auto-generated method stub
                return null;
        }
}