/*
 * Copyright 2019, TeamDev. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package io.spine.tools.compiler.annotation;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.protobuf.Descriptors;
import io.spine.code.java.ClassName;
import io.spine.code.proto.TypeSet;
import org.jboss.forge.roaster.model.Method;
import org.jboss.forge.roaster.model.impl.AbstractJavaSource;
import org.jboss.forge.roaster.model.source.JavaClassSource;
import org.jboss.forge.roaster.model.source.MethodHolderSource;
import org.jboss.forge.roaster.model.source.MethodSource;

import java.nio.file.Path;
import java.util.stream.Stream;

final class MethodNameAnnotator extends Annotator {

    private final ImmutableSet<MethodPattern> patterns;

    MethodNameAnnotator(ClassName annotation,
                        ImmutableSet<MethodPattern> patterns,
                        ImmutableList<Descriptors.FileDescriptor> descriptors,
                        Path genProtoDir) {
        super(annotation, descriptors, genProtoDir);
        this.patterns = patterns;
    }

    @Override
    public void annotate() {
        if (!patterns.isEmpty()) {
            SourceVisitor<?> visitor = new AnnotateMethods();
            descriptors().stream()
                         .map(TypeSet::messagesAndEnums)
                         .flatMap(typeSet -> typeSet.types().stream())
                         .map(type -> type.javaClassName().resolveFile())
                         .forEach(file -> rewriteSource(file, visitor));
        }
    }

    private final class AnnotateMethods implements ClassInDepthVisitor {

        @Override
        public void accept(AbstractJavaSource<JavaClassSource> source) {
            allClasses(source)
                    .flatMap(classSource -> classSource instanceof MethodHolderSource
                                            ? ((MethodHolderSource<?>) classSource).getMethods()
                                                                                   .stream()
                                            : Stream.<MethodSource<?>>of())
                    .filter(Method::isPublic)
                    .filter(this::matching)
                    .forEach(MethodNameAnnotator.this::addAnnotation);

        }

        private boolean matching(Method<?, ?> method) {
            String methodName = method.getName();
            return patterns.stream()
                           .anyMatch(pattern -> pattern.matches(methodName));
        }
    }
}

@@ -1495,126 +1495,504 @@
 ce;%0A
+%0A
 import 
-org.jboss.forge.roaster.model.source.MethodSource;%0A%0Aimport java.nio.file.Path;%0Aimport java.util.stream.Stream;%0A
+java.nio.file.Path;%0A%0A/**%0A * An %7B@link Annotator%7D which annotates methods matching given patterns.%0A *%0A * %3Cp%3ENote that, unlike other annotator implementations, %7B@code MethodNameAnnotator%7D works with%0A * multiple method patterns rather than just one due to performance considerations. All%0A * the generated classes are parsed and checked. This can take some time. Thus, consider%0A * the selective approach to marking methods unless a pattern or a set of patterns is completely%0A * necessary.%0A */
 %0Afin
@@ -2886,24 +2886,122 @@
    %7D%0A    %7D%0A%0A
+    /**%0A     * A function annotating methods of a given source according to the patterns.%0A     */%0A
     private 

Add some doc.