001/*
002 * $Id: AbstractTester.java,v 1.7 2016/12/18 20:19:38 oboehm Exp $
003 *
004 * Copyright (c) 2015 by Oliver Boehm
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 *
018 * (c)reated 07.01.2015 by oliver (ob@oasd.de)
019 */
020
021package patterntesting.runtime.junit;
022
023import java.lang.reflect.Modifier;
024import java.util.*;
025import java.util.regex.Pattern;
026
027import org.apache.logging.log4j.LogManager;
028import org.apache.logging.log4j.*;
029
030/**
031 * This is the common superclass for some tester classes defined in this
032 * package.
033 *
034 * @author oliver
035 * @version $Revision: 1.7 $
036 * @since 1.6 (07.01.2015)
037 */
038public abstract class AbstractTester {
039
040        private static final Logger LOG = LogManager.getLogger(AbstractTester.class);
041
042        /** Utility class - no need to instantiate it. */
043        protected AbstractTester() {
044        }
045
046        /**
047         * Removes "excluded" from the given classes. If one of the "excluded" class
048         * is an interface or abstract class all implementing or subclasses will be
049         * excluded.
050         *
051         * @param classes
052         *            the classes
053         * @param excluded
054         *            the excluded
055         */
056        protected static void removeClasses(final Collection<?> classes, final List<?> excluded) {
057                classes.removeAll(excluded);
058                for (Object obj : excluded) {
059                        Class<?> clazz = (Class<?>) obj;
060                        if (clazz.isInterface() || isAbstract(clazz)) {
061                                removeAssignableClasses(classes, clazz);
062                        }
063                }
064        }
065
066        private static boolean isAbstract(final Class<?> clazz) {
067                return Modifier.isAbstract(clazz.getModifiers());
068        }
069
070        private static void removeAssignableClasses(final Collection<?> classes, final Class<?> superclass) {
071                Collection<Class<?>> toBeDeleted = new ArrayList<>();
072                for (Object obj : classes) {
073                        Class<?> clazz = (Class<?>) obj;
074                        if (superclass.isAssignableFrom(clazz)) {
075                                if (LOG.isTraceEnabled()) {
076                                        LOG.trace("removing " + clazz + " from list of classes...");
077                                }
078                                toBeDeleted.add(clazz);
079                        }
080                }
081                classes.removeAll(toBeDeleted);
082        }
083
084        /**
085         * Removes "excluded" from the given classes.
086         *
087         * @param <T>
088         *            the generic type
089         * @param classes
090         *            the classes
091         * @param excluded
092         *            the excluded
093         */
094        protected static <T> void removeClasses(final Collection<Class<? extends T>> classes, final Pattern... excluded) {
095                final List<Class<? extends T>> toBeExcluded = new ArrayList<>();
096                for (Class<? extends T> clazz : classes) {
097                        if (matches(clazz, excluded)) {
098                                toBeExcluded.add(clazz);
099                        }
100                }
101                removeClasses(classes, toBeExcluded);
102        }
103
104        private static boolean matches(final Class<?> clazz, final Pattern[] excluded) {
105                String classname = clazz.getName();
106                for (int i = 0; i < excluded.length; i++) {
107                        if (excluded[i].matcher(classname).matches()) {
108                                return true;
109                        }
110                }
111                return false;
112        }
113
114}