// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/bean/ClassSpecDescription.java
// public class ClassSpecDescription implements Comparable<ClassSpecDescription> {
// 
//     private Element classElement;
//     private TypeSpec spec;
// 
//     public ClassSpecDescription(Element classElement, TypeSpec spec) {
//         this.classElement = classElement;
//         this.spec = spec;
//     }
// 
//     public Element getClassElement() {
//         return classElement;
//     }
// 
//     public TypeSpec getSpec() {
//         return spec;
//     }
// 
//     public void setSpec(TypeSpec spec) {
//         this.spec = spec;
//     }
// 
//     public JavaFile asJavaFile() {
//         return JavaFile.builder(
//                 ((PackageElement) getClassElement().getEnclosingElement()).getQualifiedName().toString(),
//                 getSpec()
//         ).build();
//     }
// 
//     public void mergeWithParentFrom(Map<Element, ClassSpecDescription> classes) {
//         ClassSpecDescription container = classes.computeIfAbsent(
//                 getClassElement().getEnclosingElement(),
//                 enclosing -> new ClassSpecDescription(
//                         getClassElement().getEnclosingElement(),
//                         MethodsCollector.commonClassPart(enclosing).build()
//                 )
//         );
// 
//         container.setSpec(
//                 container.getSpec()
//                         .toBuilder()
//                         .addType(getSpec())
//                         .build()
//         );
//     }
// 
//     @Override
//     public int compareTo(ClassSpecDescription o) {
//         return Comparator.comparing(ClassSpecDescription::depthOf).compare(this, o);
//     }
// 
//     private static long depthOf(ClassSpecDescription element) {
//         return ElementParentsIterable.stream(element.getClassElement())
//                 .filter(hasParentPackageElement().negate())
//                 .count();
//     }
// }
// 
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/processing/ProcessingException.java
// public class ProcessingException extends RuntimeException {
// 
//     public ProcessingException(String message, String simpleName, JavaFileObject.Kind kind, Exception cause) {
//         super(String.format("%s: %s (%s)", message, simpleName, kind), cause);
//     }
// 
// }
// 
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/processing/ProcessingPredicates.java
// public final class ProcessingPredicates {
// 
//     /**
//      * Walks through parent chain and if any contains
//      * {@link DoNotGenerateMatcher} annotation, skips this element
//      *
//      * @return predicate to help filter fields for matcher generation
//      */
//     public static Predicate<Element> shouldGenerateMatcher() {
//         return element -> ElementParentsIterable.stream(element)
//                 .noneMatch(next -> nonNull(next.getAnnotation(DoNotGenerateMatcher.class)));
//     }
// 
//     /**
//      * Syntax sugar for {@link #hasParentPackageElement()}
//      */
//     public static Predicate<ClassSpecDescription> isEntryWithParentPackageElement() {
//         return entry -> hasParentPackageElement().test(entry.getClassElement());
//     }
// 
//     /**
//      * To help filter nested classes
//      */
//     public static Predicate<Element> hasParentPackageElement() {
//         return entry -> entry.getEnclosingElement() instanceof PackageElement;
//     }
// }
// 
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/MatchersGenProperties.java
// static MatchersGenProperties props() {
//     return PropertyLoader.newInstance().populate(MatchersGenProperties.class);
// }
// 
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/processing/MethodsCollector.java
// public static MethodsCollector collectingMethods() {
//     return new MethodsCollector();
// }
// 
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/processing/ProcessingPredicates.java
// public static Predicate<ClassSpecDescription> isEntryWithParentPackageElement() {
//     return entry -> hasParentPackageElement().test(entry.getClassElement());
// }


import com.squareup.javapoet.JavaFile;
import ru.yandex.qatools.processors.matcher.gen.bean.ClassSpecDescription;
import ru.yandex.qatools.processors.matcher.gen.processing.ProcessingException;
import ru.yandex.qatools.processors.matcher.gen.processing.ProcessingPredicates;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
import static java.lang.String.format;
import static java.util.Comparator.reverseOrder;
import static java.util.stream.Collectors.groupingBy;
import static ru.yandex.qatools.processors.matcher.gen.MatchersGenProperties.props;
import static ru.yandex.qatools.processors.matcher.gen.processing.MethodsCollector.collectingMethods;
import static ru.yandex.qatools.processors.matcher.gen.processing.ProcessingPredicates.isEntryWithParentPackageElement;
package ru.yandex.qatools.processors.matcher.gen;




/**
 * @author lanwen (Merkushev Kirill)
 */
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MatcherFactoryGenerator extends AbstractProcessor {

    private static final Logger LOGGER = Logger.getLogger(MatcherFactoryGenerator.class.toString());

    @Override
    public Set<String> getSupportedAnnotationTypes() {
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/bean/ClassSpecDescription.java
// public class ClassSpecDescription implements Comparable<ClassSpecDescription> {
// 
//     private Element classElement;
//     private TypeSpec spec;
// 
//     public ClassSpecDescription(Element classElement, TypeSpec spec) {
//         this.classElement = classElement;
//         this.spec = spec;
//     }
// 
//     public Element getClassElement() {
//         return classElement;
//     }
// 
//     public TypeSpec getSpec() {
//         return spec;
//     }
// 
//     public void setSpec(TypeSpec spec) {
//         this.spec = spec;
//     }
// 
//     public JavaFile asJavaFile() {
//         return JavaFile.builder(
//                 ((PackageElement) getClassElement().getEnclosingElement()).getQualifiedName().toString(),
//                 getSpec()
//         ).build();
//     }
// 
//     public void mergeWithParentFrom(Map<Element, ClassSpecDescription> classes) {
//         ClassSpecDescription container = classes.computeIfAbsent(
//                 getClassElement().getEnclosingElement(),
//                 enclosing -> new ClassSpecDescription(
//                         getClassElement().getEnclosingElement(),
//                         MethodsCollector.commonClassPart(enclosing).build()
//                 )
//         );
// 
//         container.setSpec(
//                 container.getSpec()
//                         .toBuilder()
//                         .addType(getSpec())
//                         .build()
//         );
//     }
// 
//     @Override
//     public int compareTo(ClassSpecDescription o) {
//         return Comparator.comparing(ClassSpecDescription::depthOf).compare(this, o);
//     }
// 
//     private static long depthOf(ClassSpecDescription element) {
//         return ElementParentsIterable.stream(element.getClassElement())
//                 .filter(hasParentPackageElement().negate())
//                 .count();
//     }
// }
// 
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/processing/ProcessingException.java
// public class ProcessingException extends RuntimeException {
// 
//     public ProcessingException(String message, String simpleName, JavaFileObject.Kind kind, Exception cause) {
//         super(String.format("%s: %s (%s)", message, simpleName, kind), cause);
//     }
// 
// }
// 
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/processing/ProcessingPredicates.java
// public final class ProcessingPredicates {
// 
//     /**
//      * Walks through parent chain and if any contains
//      * {@link DoNotGenerateMatcher} annotation, skips this element
//      *
//      * @return predicate to help filter fields for matcher generation
//      */
//     public static Predicate<Element> shouldGenerateMatcher() {
//         return element -> ElementParentsIterable.stream(element)
//                 .noneMatch(next -> nonNull(next.getAnnotation(DoNotGenerateMatcher.class)));
//     }
// 
//     /**
//      * Syntax sugar for {@link #hasParentPackageElement()}
//      */
//     public static Predicate<ClassSpecDescription> isEntryWithParentPackageElement() {
//         return entry -> hasParentPackageElement().test(entry.getClassElement());
//     }
// 
//     /**
//      * To help filter nested classes
//      */
//     public static Predicate<Element> hasParentPackageElement() {
//         return entry -> entry.getEnclosingElement() instanceof PackageElement;
//     }
// }
// 
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/MatchersGenProperties.java
// static MatchersGenProperties props() {
//     return PropertyLoader.newInstance().populate(MatchersGenProperties.class);
// }
// 
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/processing/MethodsCollector.java
// public static MethodsCollector collectingMethods() {
//     return new MethodsCollector();
// }
// 
// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/processing/ProcessingPredicates.java
// public static Predicate<ClassSpecDescription> isEntryWithParentPackageElement() {
//     return entry -> hasParentPackageElement().test(entry.getClassElement());
// }


// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/MatcherFactoryGenerator.java
import com.squareup.javapoet.JavaFile;
import ru.yandex.qatools.processors.matcher.gen.bean.ClassSpecDescription;
import ru.yandex.qatools.processors.matcher.gen.processing.ProcessingException;
import ru.yandex.qatools.processors.matcher.gen.processing.ProcessingPredicates;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
import static java.lang.String.format;
import static java.util.Comparator.reverseOrder;
import static java.util.stream.Collectors.groupingBy;
import static ru.yandex.qatools.processors.matcher.gen.MatchersGenProperties.props;
import static ru.yandex.qatools.processors.matcher.gen.processing.MethodsCollector.collectingMethods;
import static ru.yandex.qatools.processors.matcher.gen.processing.ProcessingPredicates.isEntryWithParentPackageElement;

package ru.yandex.qatools.processors.matcher.gen;




/**
 * @author lanwen (Merkushev Kirill)
 */
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MatcherFactoryGenerator extends AbstractProcessor {

    private static final Logger LOGGER = Logger.getLogger(MatcherFactoryGenerator.class.toString());

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return new HashSet<>(props().annotationsToProcess());