/*
 *  Copyright 2013, Arondor
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.arondor.common.reflection.service;

import java.rmi.RemoteException;
import java.util.Collection;
import java.util.List;

import com.arondor.common.reflection.api.catalog.AccessibleClassCatalog;
import com.arondor.common.reflection.api.parser.AccessibleClassParser;
import com.arondor.common.reflection.api.parser.AccessibleClassProvider;
import com.arondor.common.reflection.api.service.ReflectionService;
import com.arondor.common.reflection.model.java.AccessibleClass;
import com.arondor.common.reflection.xstream.catalog.AccessibleClassCatalagParser;

public class DefaultReflectionService implements ReflectionService
{
    private AccessibleClassCatalog accessibleClassCatalog;

    public AccessibleClassCatalog getAccessibleClassCatalog()
    {
        return accessibleClassCatalog;
    }

    public void setAccessibleClassCatalog(AccessibleClassCatalog accessibleClassCatalog)
    {
        this.accessibleClassCatalog = accessibleClassCatalog;
    }

    public void setCatalogFile(String resource)
    {
        setAccessibleClassCatalog(AccessibleClassCatalagParser.parseFromResource(resource));
    }

    private AccessibleClassParser accessibleClassParser;

    public AccessibleClassParser getAccessibleClassParser()
    {
        return accessibleClassParser;
    }

    public void setAccessibleClassParser(AccessibleClassParser accessibleClassParser)
    {
        this.accessibleClassParser = accessibleClassParser;
    }

    @Override
    public AccessibleClass getAccessibleClass(String clazzName) throws RemoteException
    {
        if (getAccessibleClassCatalog() != null)
        {
            AccessibleClass clazz = getAccessibleClassCatalog().getAccessibleClass(clazzName);
            if (clazz != null)
            {
                return clazz;
            }
        }
        Class<?> clazz;
        try
        {
            clazz = Class.forName(clazzName);
            return getAccessibleClassParser().parseAccessibleClass(clazz);
        }
        catch (ClassNotFoundException e)
        {
            throw new RemoteException("Could not get class", e);
        }
    }

    @Override
    public Collection<AccessibleClass> getImplementingAccessibleClasses(String name) throws RemoteException
    {
        return getAccessibleClassCatalog().getImplementingAccessibleClasses(name);
    }

    public void setAccessibleClassProviders(List<AccessibleClassProvider> providers)
    {
        for (AccessibleClassProvider provider : providers)
        {
            provider.provideClasses(getAccessibleClassCatalog());
        }
    }
}

@@ -725,16 +725,117 @@
 il.List;
+%0Aimport java.util.regex.Pattern;%0Aimport java.util.stream.Collectors;%0A%0Aimport org.apache.log4j.Logger;
 %0A%0Aimport
@@ -1178,16 +1178,81 @@
 eClass;%0A
+import com.arondor.common.reflection.model.java.AccessibleField;%0A
 import c
@@ -1396,16 +1396,105 @@
 rvice%0A%7B%0A
+    private static final Logger LOG = Logger.getLogger(DefaultReflectionService.class);%0A%0A
     priv
@@ -1973,24 +1973,1388 @@
 e));%0A    %7D%0A%0A
+    public void setFilter(List%3CString%3E filters)%0A    %7B%0A        for (String filter : filters)%0A        %7B%0A            LOG.info(%22Filtering using filter '%22 + filter + %22'%22);%0A            Pattern pattern = Pattern.compile(filter.replace(%22*%22, %22.*%22));%0A            for (AccessibleClass clazz : accessibleClassCatalog%0A                    .getImplementingAccessibleClasses(Object.class.getName()))%0A            %7B%0A                List%3CString%3E excluded = clazz.getAccessibleFields().values().stream().filter(f -%3E %7B%0A                    return matches(clazz, f, pattern);%0A                %7D).map(f -%3E %7B%0A                    return f.getName();%0A                %7D).collect(Collectors.toList());%0A                if (!excluded.isEmpty())%0A                %7B%0A                    excluded.forEach(key -%3E clazz.getAccessibleFields().remove(key));%0A                %7D%0A            %7D%0A        %7D%0A    %7D%0A%0A    private boolean matches(AccessibleClass clazz, AccessibleField field, Pattern pattern)%0A    %7B%0A        String value = clazz.getName() + %22.%22 + field.getName() + %22:%22 + field.getClassName();%0A        if (pattern.matcher(value).matches())%0A        %7B%0A            return true;%0A        %7D%0A        value = field.getDeclaredInClass() + %22.%22 + field.getName() + %22:%22 + field.getClassName();%0A        if (pattern.matcher(value).matches())%0A        %7B%0A            return true;%0A        %7D%0A        return false;%0A    %7D%0A%0A
     private 
@@ -3762,38 +3762,170 @@
 RemoteException%0A
-
     %7B%0A
+        if (clazzName == null)%0A        %7B%0A            throw new IllegalArgumentException(%22Invalid null class provided !%22);%0A        %7D%0A
         if (getA

Support for class filtering