001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     bstefanescu
011 */
012package org.nuxeo.ecm.automation.core.impl;
013
014import java.lang.reflect.ParameterizedType;
015import java.lang.reflect.Type;
016import java.util.Collection;
017import java.util.Iterator;
018import java.util.List;
019import java.util.ListIterator;
020
021import org.nuxeo.ecm.automation.OutputCollector;
022import org.nuxeo.ecm.automation.core.collectors.DocumentModelCollector;
023import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
024
025/**
026 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
027 */
028public class IterableInputHelper {
029
030    // protected static ConcurrentMap<String,String> cache;
031
032    private IterableInputHelper() {
033    }
034
035    public static Class<?> getIterableType(Class<?> cl) {
036        // TODO first look into a cache
037        // Class<?> cl = cache.get(cl.getName());
038        return findIterableType(cl);
039    }
040
041    @SuppressWarnings("rawtypes")
042    public static Type[] findCollectorTypes(Class<? extends OutputCollector> cl) {
043        for (Type itf : cl.getGenericInterfaces()) {
044            if (itf instanceof ParameterizedType) {
045                ParameterizedType ptype = (ParameterizedType) itf;
046                if (ptype.getRawType() == OutputCollector.class) {
047                    return ptype.getActualTypeArguments();
048                }
049            }
050        }
051        throw new IllegalArgumentException("Invalid output collector class: " + cl
052                + ". The class must explicitely impelement the OutputCollector interface.");
053    }
054
055    public static Class<?> findIterableType(Class<?> cl) {
056        if (!Iterable.class.isAssignableFrom(cl)) {
057            return null;
058        }
059        // try generic super class
060        Type superType = cl.getGenericSuperclass();
061        if (superType instanceof ParameterizedType) {
062            ParameterizedType ptype = (ParameterizedType) superType;
063            return (Class<?>) ptype.getActualTypeArguments()[0];
064        }
065        // try generic interfaces
066        for (Type itf : cl.getGenericInterfaces()) {
067            if (itf instanceof ParameterizedType) {
068                ParameterizedType ptype = (ParameterizedType) itf;
069                if (ptype.getRawType() == Iterable.class || ptype.getRawType() == Collection.class
070                        || ptype.getRawType() == List.class) {
071                    return (Class<?>) ptype.getActualTypeArguments()[0];
072                }
073            }
074        }
075        // if not descend into the super type and continue.
076        if (superType != null) {
077            Class<?> superClass = cl.getSuperclass();
078            if (superClass != null) {
079                return getIterableType(superClass);
080            }
081        }
082        return null;
083    }
084
085    public static void main(String[] args) {
086        DocumentModelListImpl o1 = new DocumentModelListImpl();
087        DocumentModelCollector o2 = new DocumentModelCollector();
088        MyIt o3 = new MyIt();
089        MyList o4 = new MyList();
090        MyCol o5 = new MyCol();
091        System.out.println(getIterableType(o1.getClass()));
092        System.out.println(getIterableType(o2.getClass()));
093        System.out.println(getIterableType(o3.getClass()));
094        System.out.println(getIterableType(o4.getClass()));
095        System.out.println(getIterableType(o5.getClass()));
096    }
097
098    static class MyIt implements Iterable<String> {
099        @Override
100        public Iterator<String> iterator() {
101            return null;
102        }
103    }
104
105    static class MyList implements List<String> {
106
107        @Override
108        public int size() {
109            return 0;
110        }
111
112        @Override
113        public boolean isEmpty() {
114            return false;
115        }
116
117        @Override
118        public boolean contains(Object o) {
119            return false;
120        }
121
122        @Override
123        public Iterator<String> iterator() {
124            return null;
125        }
126
127        @Override
128        public Object[] toArray() {
129            return null;
130        }
131
132        @Override
133        public <T> T[] toArray(T[] a) {
134            return null;
135        }
136
137        @Override
138        public boolean add(String e) {
139            return false;
140        }
141
142        @Override
143        public boolean remove(Object o) {
144            return false;
145        }
146
147        @Override
148        public boolean containsAll(Collection<?> c) {
149            return false;
150        }
151
152        @Override
153        public boolean addAll(Collection<? extends String> c) {
154            return false;
155        }
156
157        @Override
158        public boolean addAll(int index, Collection<? extends String> c) {
159            return false;
160        }
161
162        @Override
163        public boolean removeAll(Collection<?> c) {
164            return false;
165        }
166
167        @Override
168        public boolean retainAll(Collection<?> c) {
169            return false;
170        }
171
172        @Override
173        public void clear() {
174        }
175
176        @Override
177        public String get(int index) {
178            return null;
179        }
180
181        @Override
182        public String set(int index, String element) {
183            return null;
184        }
185
186        @Override
187        public void add(int index, String element) {
188        }
189
190        @Override
191        public String remove(int index) {
192            return null;
193        }
194
195        @Override
196        public int indexOf(Object o) {
197            return 0;
198        }
199
200        @Override
201        public int lastIndexOf(Object o) {
202            return 0;
203        }
204
205        @Override
206        public ListIterator<String> listIterator() {
207            return null;
208        }
209
210        @Override
211        public ListIterator<String> listIterator(int index) {
212            return null;
213        }
214
215        @Override
216        public List<String> subList(int fromIndex, int toIndex) {
217            return null;
218        }
219
220    }
221
222    static class MyCol implements Collection<String> {
223
224        @Override
225        public int size() {
226            return 0;
227        }
228
229        @Override
230        public boolean isEmpty() {
231            return false;
232        }
233
234        @Override
235        public boolean contains(Object o) {
236            return false;
237        }
238
239        @Override
240        public Iterator<String> iterator() {
241            return null;
242        }
243
244        @Override
245        public Object[] toArray() {
246            return null;
247        }
248
249        @Override
250        public <T> T[] toArray(T[] a) {
251            return null;
252        }
253
254        @Override
255        public boolean add(String e) {
256            return false;
257        }
258
259        @Override
260        public boolean remove(Object o) {
261            return false;
262        }
263
264        @Override
265        public boolean containsAll(Collection<?> c) {
266            return false;
267        }
268
269        @Override
270        public boolean addAll(Collection<? extends String> c) {
271            return false;
272        }
273
274        @Override
275        public boolean removeAll(Collection<?> c) {
276            return false;
277        }
278
279        @Override
280        public boolean retainAll(Collection<?> c) {
281            return false;
282        }
283
284        @Override
285        public void clear() {
286        }
287    }
288
289}