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