// 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/elements/ElementParentsIterable.java
// public class ElementParentsIterable implements Iterable<Element> {
//     private final Element start;
// 
//     public ElementParentsIterable(Element start) {
//         this.start = Objects.requireNonNull(start, "element can't be null");
//     }
// 
//     @Override
//     public Iterator<Element> iterator() {
//         return new Iterator<Element>() {
//             private Element current = start;
// 
//             @Override
//             public boolean hasNext() {
//                 return nonNull(current.getEnclosingElement());
//             }
// 
//             @Override
//             public Element next() {
//                 Element next = current;
//                 current = current.getEnclosingElement();
//                 return next;
//             }
//         };
//     }
// 
//     /**
//      * Creates stream with parent chain
//      *
//      * @param element element to start with (will be included to chain)
//      * @return stream with elements from current with his parents until package (inclusive)
//      */
//     public static Stream<Element> stream(Element element) {
//         return StreamSupport.stream(new ElementParentsIterable(element).spliterator(), false);
//     }
// }


import ru.yandex.qatools.processors.matcher.gen.annotations.DoNotGenerateMatcher;
import ru.yandex.qatools.processors.matcher.gen.bean.ClassSpecDescription;
import ru.yandex.qatools.processors.matcher.gen.elements.ElementParentsIterable;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import java.util.function.Predicate;
import static java.util.Objects.nonNull;
package ru.yandex.qatools.processors.matcher.gen.processing;




/**
 * @author lanwen (Merkushev Kirill)
 */
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()}
     */
// 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/elements/ElementParentsIterable.java
// public class ElementParentsIterable implements Iterable<Element> {
//     private final Element start;
// 
//     public ElementParentsIterable(Element start) {
//         this.start = Objects.requireNonNull(start, "element can't be null");
//     }
// 
//     @Override
//     public Iterator<Element> iterator() {
//         return new Iterator<Element>() {
//             private Element current = start;
// 
//             @Override
//             public boolean hasNext() {
//                 return nonNull(current.getEnclosingElement());
//             }
// 
//             @Override
//             public Element next() {
//                 Element next = current;
//                 current = current.getEnclosingElement();
//                 return next;
//             }
//         };
//     }
// 
//     /**
//      * Creates stream with parent chain
//      *
//      * @param element element to start with (will be included to chain)
//      * @return stream with elements from current with his parents until package (inclusive)
//      */
//     public static Stream<Element> stream(Element element) {
//         return StreamSupport.stream(new ElementParentsIterable(element).spliterator(), false);
//     }
// }


// Path: feature-matcher-generator/src/main/java/ru/yandex/qatools/processors/matcher/gen/processing/ProcessingPredicates.java
import ru.yandex.qatools.processors.matcher.gen.annotations.DoNotGenerateMatcher;
import ru.yandex.qatools.processors.matcher.gen.bean.ClassSpecDescription;
import ru.yandex.qatools.processors.matcher.gen.elements.ElementParentsIterable;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import java.util.function.Predicate;
import static java.util.Objects.nonNull;

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




/**
 * @author lanwen (Merkushev Kirill)
 */
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() {