001package ball.game.scrabble;
002/*-
003 * ##########################################################################
004 * Game Applications and Utilities
005 * $Id: PremiumProcessor.java 5905 2020-05-11 01:35:29Z ball $
006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-game/trunk/src/main/java/ball/game/scrabble/PremiumProcessor.java $
007 * %%
008 * Copyright (C) 2010 - 2020 Allen D. Ball
009 * %%
010 * Licensed under the Apache License, Version 2.0 (the "License");
011 * you may not use this file except in compliance with the License.
012 * You may obtain a copy of the License at
013 *
014 *      http://www.apache.org/licenses/LICENSE-2.0
015 *
016 * Unless required by applicable law or agreed to in writing, software
017 * distributed under the License is distributed on an "AS IS" BASIS,
018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019 * See the License for the specific language governing permissions and
020 * limitations under the License.
021 * ##########################################################################
022 */
023import ball.annotation.ServiceProviderFor;
024import ball.annotation.processing.AnnotatedProcessor;
025import ball.annotation.processing.For;
026import java.util.Set;
027import javax.annotation.processing.Processor;
028import javax.annotation.processing.RoundEnvironment;
029import javax.lang.model.element.Element;
030import javax.lang.model.element.TypeElement;
031import lombok.NoArgsConstructor;
032import lombok.ToString;
033
034import static java.util.stream.Collectors.toSet;
035import static javax.lang.model.element.Modifier.ABSTRACT;
036import static javax.tools.Diagnostic.Kind.ERROR;
037
038/**
039 * {@link Processor} implementation to check {@link Class}es annotated with
040 * {@link LetterPremium} or {@link WordPremium}:
041 * <ol>
042 *   <li value="1">Are an instance of {@link SQ},</li>
043 *   <li value="2">Concrete, and</li>
044 *   <li value="3">
045 *      Are annotated with only one of {@link LetterPremium} or
046 *      {@link WordPremium}
047 *   </li>
048 * </ol>
049 *
050 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
051 * @version $Revision: 5905 $
052 */
053@ServiceProviderFor({ Processor.class })
054@For({ LetterPremium.class, WordPremium.class })
055@NoArgsConstructor @ToString
056public class PremiumProcessor extends AnnotatedProcessor {
057    @Override
058    public void process(RoundEnvironment roundEnv,
059                        TypeElement annotation, Element element) {
060        super.process(roundEnv, annotation, element);
061
062        switch (element.getKind()) {
063        case CLASS:
064            if (withoutModifiers(ABSTRACT).test(element)) {
065                Set<TypeElement> set =
066                    getSupportedAnnotationTypeList()
067                    .stream()
068                    .filter(t -> element.getAnnotation(t) != null)
069                    .map(t -> asTypeElement(t))
070                    .collect(toSet());
071
072                set.remove(annotation);
073
074                if (! set.isEmpty()) {
075                    print(ERROR, element,
076                          "%s annotated with @%s but is also annotated with @%s",
077                          element.getKind(),
078                          annotation.getSimpleName(),
079                          set.iterator().next().getSimpleName());
080                }
081            } else {
082                print(ERROR, element,
083                      "@%s: %s is %s",
084                      annotation.getSimpleName(), element.getKind(), ABSTRACT);
085            }
086            break;
087
088        default:
089            break;
090        }
091    }
092}