1 /* 2 * Copyright (C) 2015 Square, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.squareup.javapoet; 17 18 import java.io.IOException; 19 import java.lang.reflect.Type; 20 import java.util.ArrayList; 21 import java.util.Collections; 22 import java.util.List; 23 import java.util.Set; 24 import javax.lang.model.SourceVersion; 25 import javax.lang.model.element.Modifier; 26 27 import static com.squareup.javapoet.Util.checkArgument; 28 import static com.squareup.javapoet.Util.checkNotNull; 29 import static com.squareup.javapoet.Util.checkState; 30 31 /** A generated field declaration. */ 32 public final class FieldSpec { 33 public final TypeName type; 34 public final String name; 35 public final CodeBlock javadoc; 36 public final List<AnnotationSpec> annotations; 37 public final Set<Modifier> modifiers; 38 public final CodeBlock initializer; 39 FieldSpec(Builder builder)40 private FieldSpec(Builder builder) { 41 this.type = checkNotNull(builder.type, "type == null"); 42 this.name = checkNotNull(builder.name, "name == null"); 43 this.javadoc = builder.javadoc.build(); 44 this.annotations = Util.immutableList(builder.annotations); 45 this.modifiers = Util.immutableSet(builder.modifiers); 46 this.initializer = (builder.initializer == null) 47 ? CodeBlock.builder().build() 48 : builder.initializer; 49 } 50 hasModifier(Modifier modifier)51 public boolean hasModifier(Modifier modifier) { 52 return modifiers.contains(modifier); 53 } 54 emit(CodeWriter codeWriter, Set<Modifier> implicitModifiers)55 void emit(CodeWriter codeWriter, Set<Modifier> implicitModifiers) throws IOException { 56 codeWriter.emitJavadoc(javadoc); 57 codeWriter.emitAnnotations(annotations, false); 58 codeWriter.emitModifiers(modifiers, implicitModifiers); 59 codeWriter.emit("$T $L", type, name); 60 if (!initializer.isEmpty()) { 61 codeWriter.emit(" = "); 62 codeWriter.emit(initializer); 63 } 64 codeWriter.emit(";\n"); 65 } 66 equals(Object o)67 @Override public boolean equals(Object o) { 68 if (this == o) return true; 69 if (o == null) return false; 70 if (getClass() != o.getClass()) return false; 71 return toString().equals(o.toString()); 72 } 73 hashCode()74 @Override public int hashCode() { 75 return toString().hashCode(); 76 } 77 toString()78 @Override public String toString() { 79 StringBuilder out = new StringBuilder(); 80 try { 81 CodeWriter codeWriter = new CodeWriter(out); 82 emit(codeWriter, Collections.emptySet()); 83 return out.toString(); 84 } catch (IOException e) { 85 throw new AssertionError(); 86 } 87 } 88 builder(TypeName type, String name, Modifier... modifiers)89 public static Builder builder(TypeName type, String name, Modifier... modifiers) { 90 checkNotNull(type, "type == null"); 91 checkArgument(SourceVersion.isName(name), "not a valid name: %s", name); 92 return new Builder(type, name) 93 .addModifiers(modifiers); 94 } 95 builder(Type type, String name, Modifier... modifiers)96 public static Builder builder(Type type, String name, Modifier... modifiers) { 97 return builder(TypeName.get(type), name, modifiers); 98 } 99 toBuilder()100 public Builder toBuilder() { 101 Builder builder = new Builder(type, name); 102 builder.javadoc.add(javadoc); 103 builder.annotations.addAll(annotations); 104 builder.modifiers.addAll(modifiers); 105 builder.initializer = initializer.isEmpty() ? null : initializer; 106 return builder; 107 } 108 109 public static final class Builder { 110 private final TypeName type; 111 private final String name; 112 113 private final CodeBlock.Builder javadoc = CodeBlock.builder(); 114 private CodeBlock initializer = null; 115 116 public final List<AnnotationSpec> annotations = new ArrayList<>(); 117 public final List<Modifier> modifiers = new ArrayList<>(); 118 Builder(TypeName type, String name)119 private Builder(TypeName type, String name) { 120 this.type = type; 121 this.name = name; 122 } 123 addJavadoc(String format, Object... args)124 public Builder addJavadoc(String format, Object... args) { 125 javadoc.add(format, args); 126 return this; 127 } 128 addJavadoc(CodeBlock block)129 public Builder addJavadoc(CodeBlock block) { 130 javadoc.add(block); 131 return this; 132 } 133 addAnnotations(Iterable<AnnotationSpec> annotationSpecs)134 public Builder addAnnotations(Iterable<AnnotationSpec> annotationSpecs) { 135 checkArgument(annotationSpecs != null, "annotationSpecs == null"); 136 for (AnnotationSpec annotationSpec : annotationSpecs) { 137 this.annotations.add(annotationSpec); 138 } 139 return this; 140 } 141 addAnnotation(AnnotationSpec annotationSpec)142 public Builder addAnnotation(AnnotationSpec annotationSpec) { 143 this.annotations.add(annotationSpec); 144 return this; 145 } 146 addAnnotation(ClassName annotation)147 public Builder addAnnotation(ClassName annotation) { 148 this.annotations.add(AnnotationSpec.builder(annotation).build()); 149 return this; 150 } 151 addAnnotation(Class<?> annotation)152 public Builder addAnnotation(Class<?> annotation) { 153 return addAnnotation(ClassName.get(annotation)); 154 } 155 addModifiers(Modifier... modifiers)156 public Builder addModifiers(Modifier... modifiers) { 157 Collections.addAll(this.modifiers, modifiers); 158 return this; 159 } 160 initializer(String format, Object... args)161 public Builder initializer(String format, Object... args) { 162 return initializer(CodeBlock.of(format, args)); 163 } 164 initializer(CodeBlock codeBlock)165 public Builder initializer(CodeBlock codeBlock) { 166 checkState(this.initializer == null, "initializer was already set"); 167 this.initializer = checkNotNull(codeBlock, "codeBlock == null"); 168 return this; 169 } 170 build()171 public FieldSpec build() { 172 return new FieldSpec(this); 173 } 174 } 175 } 176