1/* 2 * Copyright (C) 2007-2010 Júlio Vilmar Gesser. 3 * Copyright (C) 2011, 2013-2016 The JavaParser Team. 4 * 5 * This file is part of JavaParser. 6 * 7 * JavaParser can be used either under the terms of 8 * a) the GNU Lesser General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * b) the terms of the Apache License 12 * 13 * You should have received a copy of both licenses in LICENCE.LGPL and 14 * LICENCE.APACHE. Please refer to those files for details. 15 * 16 * JavaParser is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU Lesser General Public License for more details. 20 */ 21 22package com.github.javaparser.ast; 23 24import static com.github.javaparser.ast.expr.NameExpr.*; 25import static com.github.javaparser.utils.Utils.ensureNotNull; 26 27import java.util.Arrays; 28import java.util.EnumSet; 29import java.util.List; 30import java.util.stream.Collectors; 31 32import com.github.javaparser.ast.expr.NameExpr; 33import com.github.javaparser.utils.ClassUtils; 34import com.github.javaparser.Range; 35import com.github.javaparser.ast.body.*; 36import com.github.javaparser.ast.comments.Comment; 37import com.github.javaparser.ast.comments.JavadocComment; 38import com.github.javaparser.ast.expr.NameExpr; 39import com.github.javaparser.ast.visitor.GenericVisitor; 40import com.github.javaparser.ast.visitor.VoidVisitor; 41import com.github.javaparser.utils.ClassUtils; 42 43import java.util.Arrays; 44import java.util.EnumSet; 45import java.util.List; 46import java.util.stream.Collectors; 47 48import static com.github.javaparser.utils.Utils.ensureNotNull; 49 50/** 51 * <p> 52 * This class represents the entire compilation unit. Each java file denotes a 53 * compilation unit. 54 * </p> 55 * The CompilationUnit is constructed following the syntax:<br> 56 * 57 * <pre> 58 * {@code 59 * CompilationUnit ::= ( }{@link PackageDeclaration}{@code )? 60 * ( }{@link ImportDeclaration}{@code )* 61 * ( }{@link TypeDeclaration}{@code )* 62 * } 63 * </pre> 64 * 65 * @author Julio Vilmar Gesser 66 */ 67public final class CompilationUnit extends Node { 68 69 private PackageDeclaration pakage; 70 71 private List<ImportDeclaration> imports; 72 73 private List<TypeDeclaration<?>> types; 74 75 public CompilationUnit() { 76 } 77 78 public CompilationUnit(PackageDeclaration pakage, List<ImportDeclaration> imports, List<TypeDeclaration<?>> types) { 79 setPackage(pakage); 80 setImports(imports); 81 setTypes(types); 82 } 83 84 public CompilationUnit(Range range, PackageDeclaration pakage, List<ImportDeclaration> imports, 85 List<TypeDeclaration<?>> types) { 86 super(range); 87 setPackage(pakage); 88 setImports(imports); 89 setTypes(types); 90 } 91 92 @Override 93 public <R, A> R accept(GenericVisitor<R, A> v, A arg) { 94 return v.visit(this, arg); 95 } 96 97 @Override 98 public <A> void accept(VoidVisitor<A> v, A arg) { 99 v.visit(this, arg); 100 } 101 102 /** 103 * Return a list containing all comments declared in this compilation unit. 104 * Including javadocs, line comments and block comments of all types, 105 * inner-classes and other members.<br> 106 * If there is no comment, <code>null</code> is returned. 107 * 108 * @return list with all comments of this compilation unit or 109 * <code>null</code> 110 * @see JavadocComment 111 * @see com.github.javaparser.ast.comments.LineComment 112 * @see com.github.javaparser.ast.comments.BlockComment 113 */ 114 public List<Comment> getComments() { 115 return this.getAllContainedComments(); 116 } 117 118 /** 119 * Retrieves the list of imports declared in this compilation unit or 120 * <code>null</code> if there is no import. 121 * 122 * @return the list of imports or <code>null</code> if there is no import 123 */ 124 public List<ImportDeclaration> getImports() { 125 imports = ensureNotNull(imports); 126 return imports; 127 } 128 129 /** 130 * Retrieves the package declaration of this compilation unit.<br> 131 * If this compilation unit has no package declaration (default package), 132 * <code>null</code> is returned. 133 * 134 * @return the package declaration or <code>null</code> 135 */ 136 public PackageDeclaration getPackage() { 137 return pakage; 138 } 139 140 /** 141 * Return the list of types declared in this compilation unit.<br> 142 * If there is no types declared, <code>null</code> is returned. 143 * 144 * @return the list of types or <code>null</code> null if there is no type 145 * @see AnnotationDeclaration 146 * @see ClassOrInterfaceDeclaration 147 * @see EmptyTypeDeclaration 148 * @see EnumDeclaration 149 */ 150 public List<TypeDeclaration<?>> getTypes() { 151 types = ensureNotNull(types); 152 return types; 153 } 154 155 /** 156 * Sets the list of comments of this compilation unit. 157 * 158 * @param comments 159 * the list of comments 160 */ 161 public CompilationUnit setComments(List<Comment> comments) { 162 throw new RuntimeException("Not implemented!"); 163 } 164 165 /** 166 * Sets the list of imports of this compilation unit. The list is initially 167 * <code>null</code>. 168 * 169 * @param imports 170 * the list of imports 171 */ 172 public CompilationUnit setImports(List<ImportDeclaration> imports) { 173 this.imports = imports; 174 setAsParentNodeOf(this.imports); 175 return this; 176 } 177 178 /** 179 * Sets or clear the package declarations of this compilation unit. 180 * 181 * @param pakage 182 * the pakage declaration to set or <code>null</code> to default 183 * package 184 */ 185 public CompilationUnit setPackage(PackageDeclaration pakage) { 186 this.pakage = pakage; 187 setAsParentNodeOf(this.pakage); 188 return this; 189 } 190 191 /** 192 * Sets the list of types declared in this compilation unit. 193 * 194 * @param types 195 * the lis of types 196 */ 197 public CompilationUnit setTypes(List<TypeDeclaration<?>> types) { 198 this.types = types; 199 setAsParentNodeOf(this.types); 200 return this; 201 } 202 203 /** 204 * sets the package declaration of this compilation unit 205 * 206 * @param name the name of the package 207 * @return this, the {@link CompilationUnit} 208 */ 209 public CompilationUnit setPackageName(String name) { 210 setPackage(new PackageDeclaration(name(name))); 211 return this; 212 } 213 214 /** 215 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 216 * shorthand for {@link #addImport(String, boolean, boolean)} with name,false,false 217 * 218 * @param name the import name 219 * @return this, the {@link CompilationUnit} 220 */ 221 public CompilationUnit addImport(String name) { 222 return addImport(name, false, false); 223 } 224 225 /** 226 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 227 * shorthand for {@link #addImport(String)} with clazz.getName() 228 * 229 * @param clazz the class to import 230 * @return this, the {@link CompilationUnit} 231 */ 232 public CompilationUnit addImport(Class<?> clazz) { 233 if (ClassUtils.isPrimitiveOrWrapper(clazz) || clazz.getName().startsWith("java.lang")) 234 return this; 235 else if (clazz.isArray() && !ClassUtils.isPrimitiveOrWrapper(clazz.getComponentType()) 236 && !clazz.getComponentType().getName().startsWith("java.lang")) 237 return addImport(clazz.getComponentType().getName()); 238 return addImport(clazz.getName()); 239 } 240 241 /** 242 * Add an import to the list of {@link ImportDeclaration} of this compilation unit<br> 243 * <b>This method check if no import with the same name is already in the list</b> 244 * 245 * @param name the import name 246 * @param isStatic is it an "import static" 247 * @param isAsterisk does the import end with ".*" 248 * @return this, the {@link CompilationUnit} 249 */ 250 public CompilationUnit addImport(String name, boolean isStatic, boolean isAsterisk) { 251 if (getImports().stream().anyMatch(i -> i.getName().toString().equals(name))) 252 return this; 253 else { 254 ImportDeclaration importDeclaration = new ImportDeclaration(name(name), isStatic, 255 isAsterisk); 256 getImports().add(importDeclaration); 257 importDeclaration.setParentNode(this); 258 return this; 259 } 260 } 261 262 /** 263 * Add a public class to the types of this compilation unit 264 * 265 * @param name the class name 266 * @return the newly created class 267 */ 268 public ClassOrInterfaceDeclaration addClass(String name) { 269 return addClass(name, Modifier.PUBLIC); 270 } 271 272 /** 273 * Add a class to the types of this compilation unit 274 * 275 * @param name the class name 276 * @param modifiers the modifiers (like Modifier.PUBLIC) 277 * @return the newly created class 278 */ 279 public ClassOrInterfaceDeclaration addClass(String name, Modifier... modifiers) { 280 ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration( 281 Arrays.stream(modifiers) 282 .collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), 283 false, name); 284 getTypes().add(classOrInterfaceDeclaration); 285 classOrInterfaceDeclaration.setParentNode(this); 286 return classOrInterfaceDeclaration; 287 } 288 289 /** 290 * Add a public interface class to the types of this compilation unit 291 * 292 * @param name the interface name 293 * @return the newly created class 294 */ 295 public ClassOrInterfaceDeclaration addInterface(String name) { 296 return addInterface(name, Modifier.PUBLIC); 297 } 298 299 /** 300 * Add an interface to the types of this compilation unit 301 * 302 * @param name the interface name 303 * @param modifiers the modifiers (like Modifier.PUBLIC) 304 * @return the newly created class 305 */ 306 public ClassOrInterfaceDeclaration addInterface(String name, Modifier... modifiers) { 307 ClassOrInterfaceDeclaration classOrInterfaceDeclaration = new ClassOrInterfaceDeclaration( 308 Arrays.stream(modifiers) 309 .collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), 310 true, name); 311 getTypes().add(classOrInterfaceDeclaration); 312 classOrInterfaceDeclaration.setParentNode(this); 313 return classOrInterfaceDeclaration; 314 } 315 316 /** 317 * Add a public enum to the types of this compilation unit 318 * 319 * @param name the enum name 320 * @return the newly created class 321 */ 322 public EnumDeclaration addEnum(String name) { 323 return addEnum(name, Modifier.PUBLIC); 324 } 325 326 /** 327 * Add an enum to the types of this compilation unit 328 * 329 * @param name the enum name 330 * @param modifiers the modifiers (like Modifier.PUBLIC) 331 * @return the newly created class 332 */ 333 public EnumDeclaration addEnum(String name, Modifier... modifiers) { 334 EnumDeclaration enumDeclaration = new EnumDeclaration(Arrays.stream(modifiers) 335 .collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), name); 336 getTypes().add(enumDeclaration); 337 enumDeclaration.setParentNode(this); 338 return enumDeclaration; 339 } 340 341 /** 342 * Add a public annotation declaration to the types of this compilation unit 343 * 344 * @param name the annotation name 345 * @return the newly created class 346 */ 347 public AnnotationDeclaration addAnnotationDeclaration(String name) { 348 return addAnnotationDeclaration(name, Modifier.PUBLIC); 349 } 350 351 /** 352 * Add an annotation declaration to the types of this compilation unit 353 * 354 * @param name the annotation name 355 * @param modifiers the modifiers (like Modifier.PUBLIC) 356 * @return the newly created class 357 */ 358 public AnnotationDeclaration addAnnotationDeclaration(String name, Modifier... modifiers) { 359 AnnotationDeclaration annotationDeclaration = new AnnotationDeclaration(Arrays.stream(modifiers) 360 .collect(Collectors.toCollection(() -> EnumSet.noneOf(Modifier.class))), name); 361 getTypes().add(annotationDeclaration); 362 annotationDeclaration.setParentNode(this); 363 return annotationDeclaration; 364 } 365 366 /** 367 * Try to get a class by its name 368 * 369 * @param className the class name (case-sensitive) 370 * @return null if not found, the class otherwise 371 */ 372 public ClassOrInterfaceDeclaration getClassByName(String className) { 373 return (ClassOrInterfaceDeclaration) getTypes().stream().filter(type -> type.getName().equals(className) 374 && type instanceof ClassOrInterfaceDeclaration && !((ClassOrInterfaceDeclaration) type).isInterface()) 375 .findFirst().orElse(null); 376 } 377 378 /** 379 * Try to get an interface by its name 380 * 381 * @param interfaceName the interface name (case-sensitive) 382 * @return null if not found, the interface otherwise 383 */ 384 public ClassOrInterfaceDeclaration getInterfaceByName(String interfaceName) { 385 return (ClassOrInterfaceDeclaration) getTypes().stream().filter(type -> type.getName().equals(interfaceName) 386 && type instanceof ClassOrInterfaceDeclaration && ((ClassOrInterfaceDeclaration) type).isInterface()) 387 .findFirst().orElse(null); 388 } 389 390 /** 391 * Try to get an enum by its name 392 * 393 * @param enumName the enum name (case-sensitive) 394 * @return null if not found, the enum otherwise 395 */ 396 public EnumDeclaration getEnumByName(String enumName) { 397 return (EnumDeclaration) getTypes().stream().filter(type -> type.getName().equals(enumName) 398 && type instanceof EnumDeclaration) 399 .findFirst().orElse(null); 400 } 401 402 /** 403 * Try to get an annotation by its name 404 * 405 * @param annotationName the annotation name (case-sensitive) 406 * @return null if not found, the annotation otherwise 407 */ 408 public AnnotationDeclaration getAnnotationDeclarationByName(String annotationName) { 409 return (AnnotationDeclaration) getTypes().stream().filter(type -> type.getName().equals(annotationName) 410 && type instanceof AnnotationDeclaration) 411 .findFirst().orElse(null); 412 } 413} 414