001/*
002 *  Copyright 2013 Chris Pheby
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 */
016package org.jadira.scanner;
017
018import java.net.URL;
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.List;
022
023import org.jadira.scanner.classpath.filter.NameFilter;
024import org.jadira.scanner.core.api.Filter;
025import org.jadira.scanner.core.api.Locator;
026import org.jadira.scanner.core.exception.ClasspathAccessException;
027import org.jadira.scanner.core.utils.reflection.ClassLoaderUtils;
028
029public class ConfigurationBuilder implements Configuration {
030    
031    private List<URL> urls = new ArrayList<URL>();
032    
033    private List<Locator<URL>> locators = new ArrayList<Locator<URL>>();
034
035    private List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
036    
037    private List<Filter<?>> filters = new ArrayList<Filter<?>>();
038
039    public ConfigurationBuilder() {
040        ClassLoader[] cls = ClassLoaderUtils.getClassLoaders();
041        for (ClassLoader next : cls) {
042            classLoaders.add(next);
043        }
044    }
045
046    public static ConfigurationBuilder build(final Object... params) {
047        
048        ConfigurationBuilder builder = new ConfigurationBuilder();
049        List<Object> paramsList = flattenParams(params);
050
051        List<ClassLoader> cLoaders = new ArrayList<ClassLoader>();
052        
053        for (Object param : paramsList) {
054            if (param instanceof ClassLoader) {
055                cLoaders.add((ClassLoader) param);
056            } else if (param instanceof URL) {
057                builder.addUrls((URL) param);
058            } else if (param instanceof Locator) {
059                @SuppressWarnings("unchecked") final Locator<URL>[] myParams = new Locator[] {(Locator<URL>)param};
060                builder.addLocators(myParams);
061            } else if (param instanceof Filter) {
062                builder.addFilters((Filter<?>) param);
063            } else if (param instanceof String) {
064                builder.addFilters(new NameFilter((String)param));
065            } else {
066                throw new ClasspathAccessException("Could not handle builder parameter " + param.toString());
067            }
068            
069        }
070
071        builder.setClassLoaders(cLoaders);        
072        return builder;
073    }
074
075    private static List<Object> flattenParams(final Object... params) {
076        List<Object> paramsList = new ArrayList<Object>(params.length);
077        if (params != null) {
078            for (Object param : params) {
079                if (param != null) {
080                    if (param.getClass().isArray()) {
081                        for (Object nextEntry : (Object[]) param) {
082                            if (nextEntry != null) {
083                                paramsList.add(nextEntry); 
084                            }
085                        }
086                    }
087                    else if (param instanceof Iterable) {
088                        for (Object nextEntry : (Iterable<?>) param) {
089                            if (nextEntry != null) {
090                                paramsList.add(nextEntry); }
091                            }
092                        }
093                    else {
094                        paramsList.add(param);
095                    }
096                }
097            }
098        }
099        return paramsList;
100    }
101
102    public Scanner build() {
103        return new Scanner(this);
104    }
105    
106    @Override
107    public List<URL> getUrls() {
108        return urls;
109    }
110
111    ConfigurationBuilder setUrls(final Collection<URL> urls) {
112        this.urls = new ArrayList<URL>(urls);
113        return this;
114    }
115
116    ConfigurationBuilder setUrls(final URL... urls) {
117        this.urls = new ArrayList<URL>(urls.length);
118        for(URL next : urls) {
119            this.urls.add(next);
120        }
121        return this;
122    }
123    
124    ConfigurationBuilder addUrls(final Collection<URL> urls) {
125        this.urls.addAll(urls);
126        return this;
127    }
128    
129    ConfigurationBuilder addUrls(final URL... urls) {
130        for(URL next : urls) {
131            this.urls.add(next);
132        }
133        return this;
134    }
135    
136    @Override
137    public List<Locator<URL>> getLocators() {
138        return locators;
139    }
140
141    ConfigurationBuilder setLocators(final Collection<Locator<URL>> locators) {
142        this.locators = new ArrayList<Locator<URL>>(locators);
143        return this;
144    }
145
146    @SafeVarargs 
147    final ConfigurationBuilder setLocators(final Locator<URL>... locators) {
148        this.locators = new ArrayList<Locator<URL>>(locators.length);
149        for (Locator<URL> next : locators) {
150            this.locators.add(next);
151        }
152        return this;
153    }
154        
155    ConfigurationBuilder addLocators(final Collection<Locator<URL>> locators) {
156        this.locators.addAll(locators);
157        return this;
158    }
159    
160    @SafeVarargs
161    final ConfigurationBuilder addLocators(final Locator<URL>... locators) {
162        for (Locator<URL> next : locators) {
163            this.locators.add(next);
164        }
165        return this;
166    }
167    
168    @Override
169    public List<ClassLoader> getClassLoaders() {
170        return classLoaders;
171    }
172
173    ConfigurationBuilder setClassLoaders(final Collection<ClassLoader> classLoaders) {
174        this.classLoaders = new ArrayList<ClassLoader>(classLoaders);
175        return this;
176    }
177
178    ConfigurationBuilder setClassLoaders(final ClassLoader... classLoaders) {
179        this.classLoaders = new ArrayList<ClassLoader>(classLoaders.length);
180        for (ClassLoader next : classLoaders) {
181            this.classLoaders.add(next);
182        }
183        return this;
184    }
185    
186    ConfigurationBuilder addClassLoaders(final Collection<ClassLoader> classLoaders) {
187        this.classLoaders.addAll(classLoaders);
188        return this;
189    }
190
191    ConfigurationBuilder addClassLoaders(final ClassLoader... classLoaders) {
192        for (ClassLoader next : classLoaders) {
193            this.classLoaders.add(next);
194        }
195        return this;
196    }
197    
198    @Override
199    public List<Filter<?>> getFilters() {
200        return filters;
201    }
202
203    ConfigurationBuilder setFilters(final List<Filter<?>> filters) {
204        this.filters = new ArrayList<Filter<?>>(filters);
205        return this;
206    }
207
208    ConfigurationBuilder setFilters(final Filter<?>... filters) {
209        this.filters = new ArrayList<Filter<?>>(filters.length);
210        for (Filter<?> next : filters) {
211            this.filters.add(next);
212        }
213        return this;
214    }
215    
216    ConfigurationBuilder addFilters(final List<Filter<?>> filters) {
217        this.filters.addAll(filters);
218        return this;
219    }
220    
221    ConfigurationBuilder addFilters(final Filter<?>... filters) {
222        for (Filter<?> next : filters) {
223            this.filters.add(next);
224        }
225        return this;
226    }
227}