001package ball.annotation.processing;
002/*-
003 * ##########################################################################
004 * Utilities
005 * %%
006 * Copyright (C) 2008 - 2022 Allen D. Ball
007 * %%
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *      http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 * ##########################################################################
020 */
021
022import ball.annotation.ServiceProviderFor;
023import java.io.PrintWriter;
024import java.lang.annotation.Annotation;
025import java.util.Map;
026import java.util.Set;
027import java.util.TreeMap;
028import java.util.TreeSet;
029import javax.annotation.processing.Processor;
030import javax.tools.FileObject;
031import javax.tools.JavaFileManager;
032import javax.xml.bind.annotation.XmlRootElement;
033import javax.xml.bind.annotation.XmlType;
034import lombok.NoArgsConstructor;
035import lombok.ToString;
036
037import static java.lang.reflect.Modifier.isAbstract;
038import static javax.tools.StandardLocation.CLASS_OUTPUT;
039
040/**
041 * {@link Processor} implementation to generate {@code jaxb.index} files
042 * from {@link Class}es annotated with JAXB annotations.
043 *
044 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
045 */
046@ServiceProviderFor({ Processor.class })
047@For({ XmlRootElement.class, XmlType.class })
048@NoArgsConstructor @ToString
049public class JAXBIndexProcessor extends AnnotatedProcessor implements ClassFileProcessor {
050    private static final String JAXB_INDEX = "jaxb.index";
051    private static final String DOT = ".";
052
053    private final Set<String> set = new TreeSet<>();
054
055    @Override
056    public void process(Set<Class<?>> set, JavaFileManager fm) throws Exception {
057        Map<String,Set<String>> map = new TreeMap<>();
058
059        for (Class<?> type : set) {
060            if (! isAbstract(type.getModifiers())) {
061                for (Class<? extends Annotation> annotation : getSupportedAnnotationTypeList()) {
062                    if (type.isAnnotationPresent(annotation)) {
063                        String key = type.getPackage().getName();
064                        String value = type.getCanonicalName().substring(key.length());
065
066                        if (value.startsWith(DOT)) {
067                            value = value.substring(DOT.length());
068                        }
069
070                        map.computeIfAbsent(key, k -> new TreeSet<>())
071                            .add(value);
072                    }
073                }
074            }
075        }
076
077        for (Map.Entry<String,Set<String>> entry : map.entrySet()) {
078            String path = JAXB_INDEX;
079            FileObject file = fm.getFileForOutput(CLASS_OUTPUT, entry.getKey(), JAXB_INDEX, null);
080
081            try (PrintWriter writer = new PrintWriter(file.openWriter())) {
082                writer.println("# " + JAXB_INDEX);
083
084                entry.getValue().stream().forEach(t -> writer.println(t));
085            }
086        }
087    }
088}