org.inferred.freebuilder.processor.util.CompilationUnitWriter.java Source code

Java tutorial

Introduction

Here is the source code for org.inferred.freebuilder.processor.util.CompilationUnitWriter.java

Source

/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.inferred.freebuilder.processor.util;

import static javax.lang.model.util.ElementFilter.typesIn;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;

import org.inferred.freebuilder.processor.util.ImpliedClass.ImpliedNestedClass;

import java.io.Closeable;
import java.io.IOException;
import java.io.Writer;
import java.util.Set;

import javax.annotation.processing.Filer;
import javax.annotation.processing.FilerException;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;

/** Convenience wrapper around the {@link Writer} instances returned by {@link Filer}. */
public class CompilationUnitWriter implements SourceBuilder, Closeable {

    private final Writer writer;
    private final ImportManager importManager;
    private final SourceStringBuilder source;

    CompilationUnitWriter(Filer filer, ImpliedClass classToWrite, Element originatingElement)
            throws FilerException {
        String pkg = classToWrite.getEnclosingElement().getQualifiedName().toString();
        try {
            writer = filer.createSourceFile(classToWrite.getQualifiedName(), originatingElement).openWriter();
            writer.append("// Autogenerated code. Do not modify.\n").append("package ").append(pkg).append(";\n")
                    .append("\n");
        } catch (FilerException e) {
            throw e;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // Write the source code into an intermediate SourceStringBuilder, as the imports need to be
        // written first, but aren't known yet.
        ImportManager.Builder importManagerBuilder = new ImportManager.Builder();
        importManagerBuilder.addImplicitImport(classToWrite);
        for (TypeElement sibling : siblingTypes(classToWrite)) {
            importManagerBuilder.addImplicitImport(sibling);
        }
        addNestedClasses(importManagerBuilder, classToWrite.getNestedClasses());
        importManager = importManagerBuilder.build();
        source = new SourceStringBuilder(importManager, new StringBuilder());
    }

    @Override
    public CompilationUnitWriter add(String fmt, Object... args) {
        source.add(fmt, args);
        return this;
    }

    @Override
    public CompilationUnitWriter addLine(String fmt, Object... args) {
        source.addLine(fmt, args);
        return this;
    }

    @Override
    public void close() {
        try {
            if (!importManager.getClassImports().isEmpty()) {
                for (String classImport : importManager.getClassImports()) {
                    writer.append("import ").append(classImport).append(";\n");
                }
                writer.append("\n");
            }
            writer.append(source.toString());
            writer.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static Iterable<TypeElement> siblingTypes(TypeElement type) {
        return Iterables.concat(ImmutableList.of(type), typesIn(type.getEnclosingElement().getEnclosedElements()));
    }

    private static void addNestedClasses(ImportManager.Builder importManagerBuilder,
            Set<ImpliedNestedClass> nestedClasses) {
        for (ImpliedNestedClass nestedClass : nestedClasses) {
            importManagerBuilder.addImplicitImport(nestedClass);
            addNestedClasses(importManagerBuilder, nestedClass.getNestedClasses());
        }
    }
}