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