001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2012 GRANITE DATA SERVICES S.A.S.
004    
005      This file is part of Granite Data Services.
006    
007      Granite Data Services is free software; you can redistribute it and/or modify
008      it under the terms of the GNU Library General Public License as published by
009      the Free Software Foundation; either version 2 of the License, or (at your
010      option) any later version.
011    
012      Granite Data Services is distributed in the hope that it will be useful, but
013      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014      FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015      for more details.
016    
017      You should have received a copy of the GNU Library General Public License
018      along with this library; if not, see <http://www.gnu.org/licenses/>.
019    */
020    
021    package org.granite.client.tide.impl;
022    
023    import java.lang.annotation.Annotation;
024    import java.lang.reflect.Array;
025    import java.util.ArrayList;
026    import java.util.HashMap;
027    import java.util.List;
028    import java.util.Map;
029    import java.util.Map.Entry;
030    
031    import org.granite.client.tide.Context;
032    import org.granite.client.tide.InstanceStore;
033    import org.granite.client.tide.server.Component;
034    
035    /**
036     * @author William DRAI
037     */
038    public class SimpleInstanceStore implements InstanceStore {
039        
040            private final Context context;
041            private static final String TYPED = "__TYPED__";
042        private Map<String, Object> instances = new HashMap<String, Object>();
043        
044        public SimpleInstanceStore(Context context) {
045            this.context = context;
046        }
047        
048        @SuppressWarnings("unchecked")
049        public <T> T getNoProxy(String name) {
050            Object instance = instances.get(name);
051            if (instance instanceof Component)
052                return null;
053            return (T)instance;
054        }
055        
056        public void set(String name, Object instance) {
057            context.initInstance(instance, name);
058            instances.put(name, instance);
059        }
060        
061        private int NUM_TYPED_INSTANCE = 1;
062        
063        public void set(Object instance) {
064            if (instance == null)
065                    throw new NullPointerException("Cannot register null component instance");
066            context.initInstance(instance, null);
067            if (!instances.containsValue(instance))
068                    instances.put(TYPED + (NUM_TYPED_INSTANCE++), instance);
069        }
070    
071        @Override
072        public void remove(String name) {
073            instances.remove(name);
074        }
075        
076        @Override
077        public void clear() {
078            instances.clear();
079            }
080        
081        public List<String> allNames() {
082            List<String> names = new ArrayList<String>(instances.size());
083            for (String name : instances.keySet()) {
084                    if (!name.startsWith(TYPED))
085                            names.add(name);
086            }
087            return names;
088        }
089    
090        @SuppressWarnings("unchecked")
091        public <T> T byName(String name, Context context) {
092            return (T)instances.get(name);
093        }
094        
095        protected Object createInstance() {
096            return null;
097        }
098        
099        @SuppressWarnings("unchecked")
100        @Override
101        public <T> T byType(Class<T> type, Context context) {
102            T instance = null;
103            for (Object i : instances.values()) {
104                if (type.isInstance(i)) {
105                    if (instance == null)
106                        instance = (T)i;
107                    else
108                        throw new RuntimeException("Ambiguous component definition for class " + type);
109                }
110            }
111            return instance;
112        }
113    
114        @SuppressWarnings("unchecked")
115        @Override
116        public <T> T[] allByType(Class<T> type, Context context, boolean create) {
117            List<T> list = new ArrayList<T>();
118            for (Object instance : instances.values()) {
119                if (type.isInstance(instance))
120                    list.add((T)instance);
121            }
122            T[] all = (T[])Array.newInstance(type, list.size());
123            return list.size() > 0 ? list.toArray(all) : null;
124        }
125    
126        @Override
127            public Map<String, Object> allByAnnotatedWith(Class<? extends Annotation> annotationClass, Context context) {
128            Map<String, Object> map = new HashMap<String, Object>();
129            for (Entry<String, Object> entry : instances.entrySet()) {
130                if (entry.getValue().getClass().isAnnotationPresent(annotationClass))
131                    map.put(entry.getKey(), entry.getValue());
132            }
133            return map.isEmpty() ? null : map;
134        }
135    
136    }