// Path: src/main/java/ru/vyarus/guice/validator/group/annotation/MethodGroupsFactory.java
// @Singleton
// public class MethodGroupsFactory {
// 
//     /**
//      * System property or environment variable name to disable cache.
//      * If value is 'false' - cache disabled, otherwise cache enabled.
//      */
//     public static final String CACHE_PROPERTY = MethodGroupsFactory.class.getName() + ".cache";
//     // lock will not affect performance for cached descriptors, just to make sure nothing was build two times
//     private static final ReentrantLock LOCK = new ReentrantLock();
// 
//     private final Map<Method, Class<?>[]> cache = new HashMap<>();
// 
//     private final boolean addDefaultGroup;
// 
//     @Inject
//     public MethodGroupsFactory(@Named("guice.validator.addDefaultGroup") final boolean addDefaultGroup) {
//         this.addDefaultGroup = addDefaultGroup;
//     }
// 
//     public Class<?>[] create(final Method method) {
//         Class<?>[] groups = cache.get(method);
//         if (groups == null) {
//             LOCK.lock();
//             try {
//                 // groups could be created while thread wait for LOCK
//                 groups = cache.get(method);
//                 if (groups == null) {
//                     groups = buildGroups(method);
//                     if (isCacheEnabled()) {
//                         // internal check
//                         Preconditions.checkState(cache.get(method) == null,
//                                 "Bad concurrency: groups already present in cache");
//                         cache.put(method, groups);
//                     }
//                 }
//             } finally {
//                 LOCK.unlock();
//             }
//         }
//         return groups;
//     }
// 
//     private Class<?>[] buildGroups(final Method method) {
//         final List<ValidationGroups> annotations = GroupUtils.findAnnotations(method);
//         // remove duplicates
//         final Set<Class<?>> result = new LinkedHashSet<>();
//         for (ValidationGroups group : annotations) {
//             Collections.addAll(result, group.value());
//         }
//         if (addDefaultGroup) {
//             result.add(Default.class);
//         }
//         return result.toArray(new Class<?>[0]);
//     }
// 
//     /**
//      * Clears cached contexts (already parsed).
//      * Cache could be completely disabled using system property or environment variable
//      *
//      * @see #CACHE_PROPERTY
//      */
//     public void clearCache() {
//         LOCK.lock();
//         try {
//             cache.clear();
//         } finally {
//             LOCK.unlock();
//         }
//     }
// 
//     /**
//      * Disables descriptors cache.
//      */
//     public static void disableCache() {
//         System.setProperty(CACHE_PROPERTY, Boolean.FALSE.toString());
//     }
// 
//     /**
//      * @return true is cache enabled, false otherwise
//      */
//     public static boolean isCacheEnabled() {
//         final String no = Boolean.FALSE.toString();
//         return !no.equals(System.getenv(CACHE_PROPERTY))
//                 && !no.equals(System.getProperty(CACHE_PROPERTY));
//     }
// }
// 
// Path: src/test/java/ru/vyarus/guice/validator/group/support/groups/FooGroup.java
// public interface FooGroup {
// }
// 
// Path: src/test/java/ru/vyarus/guice/validator/group/support/groups/FooGroup2.java
// public interface FooGroup2 {
// }
// 
// Path: src/test/java/ru/vyarus/guice/validator/group/support/groups/RootFooGroup.java
// public interface RootFooGroup {
// }


import com.google.common.collect.Sets;
import org.junit.Assert;
import org.junit.Test;
import ru.vyarus.guice.validator.group.annotation.MethodGroupsFactory;
import ru.vyarus.guice.validator.group.support.groups.FooGroup;
import ru.vyarus.guice.validator.group.support.groups.FooGroup2;
import ru.vyarus.guice.validator.group.support.groups.RootFooGroup;
import ru.vyarus.guice.validator.group.support.groups.ann.Group1;
import ru.vyarus.guice.validator.group.support.groups.ann.Group2;
import ru.vyarus.guice.validator.group.support.groups.ann.RootGroup;
import ru.vyarus.guice.validator.group.support.simple.*;
        Assert.assertArrayEquals(new Class[]{Group1.class},
                factory.create(SimpleAnnService.class.getMethod("custom")));

        Assert.assertEquals(Sets.newHashSet(Group1.class, Group2.class),
                Sets.newHashSet(factory.create(SimpleAnnService.class.getMethod("custom2"))));
    }

    @Test
    public void checkCompositeCases() throws Throwable {
        Assert.assertArrayEquals(new Class[]{RootGroup.class},
                factory.create(CompositeAnnService.class.getMethod("nothing")));

        Assert.assertEquals(Sets.newHashSet(RootGroup.class, FooGroup.class),
                Sets.newHashSet(factory.create(CompositeAnnService.class.getMethod("single"))));

        Assert.assertEquals(Sets.newHashSet(RootGroup.class, FooGroup.class, FooGroup2.class),
                Sets.newHashSet(factory.create(CompositeAnnService.class.getMethod("multiple"))));

        Assert.assertEquals(Sets.newHashSet(RootGroup.class, Group1.class),
                Sets.newHashSet(factory.create(CompositeAnnService.class.getMethod("custom"))));

        Assert.assertEquals(Sets.newHashSet(RootGroup.class, Group1.class, Group2.class),
                Sets.newHashSet(factory.create(CompositeAnnService.class.getMethod("custom2"))));
    }

    @Test
    public void checkCompositeCases2() throws Throwable {
        Assert.assertArrayEquals(new Class[]{RootFooGroup.class},
                factory.create(CompositeAnnService2.class.getMethod("nothing")));

// Path: src/main/java/ru/vyarus/guice/validator/group/annotation/MethodGroupsFactory.java
// @Singleton
// public class MethodGroupsFactory {
// 
//     /**
//      * System property or environment variable name to disable cache.
//      * If value is 'false' - cache disabled, otherwise cache enabled.
//      */
//     public static final String CACHE_PROPERTY = MethodGroupsFactory.class.getName() + ".cache";
//     // lock will not affect performance for cached descriptors, just to make sure nothing was build two times
//     private static final ReentrantLock LOCK = new ReentrantLock();
// 
//     private final Map<Method, Class<?>[]> cache = new HashMap<>();
// 
//     private final boolean addDefaultGroup;
// 
//     @Inject
//     public MethodGroupsFactory(@Named("guice.validator.addDefaultGroup") final boolean addDefaultGroup) {
//         this.addDefaultGroup = addDefaultGroup;
//     }
// 
//     public Class<?>[] create(final Method method) {
//         Class<?>[] groups = cache.get(method);
//         if (groups == null) {
//             LOCK.lock();
//             try {
//                 // groups could be created while thread wait for LOCK
//                 groups = cache.get(method);
//                 if (groups == null) {
//                     groups = buildGroups(method);
//                     if (isCacheEnabled()) {
//                         // internal check
//                         Preconditions.checkState(cache.get(method) == null,
//                                 "Bad concurrency: groups already present in cache");
//                         cache.put(method, groups);
//                     }
//                 }
//             } finally {
//                 LOCK.unlock();
//             }
//         }
//         return groups;
//     }
// 
//     private Class<?>[] buildGroups(final Method method) {
//         final List<ValidationGroups> annotations = GroupUtils.findAnnotations(method);
//         // remove duplicates
//         final Set<Class<?>> result = new LinkedHashSet<>();
//         for (ValidationGroups group : annotations) {
//             Collections.addAll(result, group.value());
//         }
//         if (addDefaultGroup) {
//             result.add(Default.class);
//         }
//         return result.toArray(new Class<?>[0]);
//     }
// 
//     /**
//      * Clears cached contexts (already parsed).
//      * Cache could be completely disabled using system property or environment variable
//      *
//      * @see #CACHE_PROPERTY
//      */
//     public void clearCache() {
//         LOCK.lock();
//         try {
//             cache.clear();
//         } finally {
//             LOCK.unlock();
//         }
//     }
// 
//     /**
//      * Disables descriptors cache.
//      */
//     public static void disableCache() {
//         System.setProperty(CACHE_PROPERTY, Boolean.FALSE.toString());
//     }
// 
//     /**
//      * @return true is cache enabled, false otherwise
//      */
//     public static boolean isCacheEnabled() {
//         final String no = Boolean.FALSE.toString();
//         return !no.equals(System.getenv(CACHE_PROPERTY))
//                 && !no.equals(System.getProperty(CACHE_PROPERTY));
//     }
// }
// 
// Path: src/test/java/ru/vyarus/guice/validator/group/support/groups/FooGroup.java
// public interface FooGroup {
// }
// 
// Path: src/test/java/ru/vyarus/guice/validator/group/support/groups/FooGroup2.java
// public interface FooGroup2 {
// }
// 
// Path: src/test/java/ru/vyarus/guice/validator/group/support/groups/RootFooGroup.java
// public interface RootFooGroup {
// }


// Path: src/test/java/ru/vyarus/guice/validator/group/GroupRecognitionTest.java
import com.google.common.collect.Sets;
import org.junit.Assert;
import org.junit.Test;
import ru.vyarus.guice.validator.group.annotation.MethodGroupsFactory;
import ru.vyarus.guice.validator.group.support.groups.FooGroup;
import ru.vyarus.guice.validator.group.support.groups.FooGroup2;
import ru.vyarus.guice.validator.group.support.groups.RootFooGroup;
import ru.vyarus.guice.validator.group.support.groups.ann.Group1;
import ru.vyarus.guice.validator.group.support.groups.ann.Group2;
import ru.vyarus.guice.validator.group.support.groups.ann.RootGroup;
import ru.vyarus.guice.validator.group.support.simple.*;

        Assert.assertArrayEquals(new Class[]{Group1.class},
                factory.create(SimpleAnnService.class.getMethod("custom")));

        Assert.assertEquals(Sets.newHashSet(Group1.class, Group2.class),
                Sets.newHashSet(factory.create(SimpleAnnService.class.getMethod("custom2"))));
    }

    @Test
    public void checkCompositeCases() throws Throwable {
        Assert.assertArrayEquals(new Class[]{RootGroup.class},
                factory.create(CompositeAnnService.class.getMethod("nothing")));

        Assert.assertEquals(Sets.newHashSet(RootGroup.class, FooGroup.class),
                Sets.newHashSet(factory.create(CompositeAnnService.class.getMethod("single"))));

        Assert.assertEquals(Sets.newHashSet(RootGroup.class, FooGroup.class, FooGroup2.class),
                Sets.newHashSet(factory.create(CompositeAnnService.class.getMethod("multiple"))));

        Assert.assertEquals(Sets.newHashSet(RootGroup.class, Group1.class),
                Sets.newHashSet(factory.create(CompositeAnnService.class.getMethod("custom"))));

        Assert.assertEquals(Sets.newHashSet(RootGroup.class, Group1.class, Group2.class),
                Sets.newHashSet(factory.create(CompositeAnnService.class.getMethod("custom2"))));
    }

    @Test
    public void checkCompositeCases2() throws Throwable {
        Assert.assertArrayEquals(new Class[]{RootFooGroup.class},
                factory.create(CompositeAnnService2.class.getMethod("nothing")));

        Assert.assertEquals(Sets.newHashSet(RootFooGroup.class, FooGroup.class),