gt: 				if (qualifiedName.length() > 0) {
context: /*******************************************************************************
   * Copyright (c) 2000, 2017 IBM Corporation and others.
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *     IBM Corporation - initial API and implementation
   *******************************************************************************/
  package org.eclipse.jdt.internal.corext.dom;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.eclipse.jdt.core.dom.AST;
  import org.eclipse.jdt.core.dom.ASTNode;
  import org.eclipse.jdt.core.dom.ASTParser;
  import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
  import org.eclipse.jdt.core.dom.AnnotatableType;
  import org.eclipse.jdt.core.dom.ArrayType;
  import org.eclipse.jdt.core.dom.CompilationUnit;
  import org.eclipse.jdt.core.dom.Dimension;
  import org.eclipse.jdt.core.dom.Expression;
  import org.eclipse.jdt.core.dom.IAnnotationBinding;
  import org.eclipse.jdt.core.dom.IExtendedModifier;
  import org.eclipse.jdt.core.dom.IMethodBinding;
  import org.eclipse.jdt.core.dom.ITypeBinding;
  import org.eclipse.jdt.core.dom.InfixExpression;
  import org.eclipse.jdt.core.dom.InfixExpression.Operator;
  import org.eclipse.jdt.core.dom.LambdaExpression;
  import org.eclipse.jdt.core.dom.MethodDeclaration;
  import org.eclipse.jdt.core.dom.Modifier;
  import org.eclipse.jdt.core.dom.Name;
  import org.eclipse.jdt.core.dom.NodeFinder;
  import org.eclipse.jdt.core.dom.ParameterizedType;
  import org.eclipse.jdt.core.dom.PrimitiveType;
  import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
  import org.eclipse.jdt.core.dom.Type;
  import org.eclipse.jdt.core.dom.TypeDeclaration;
  import org.eclipse.jdt.core.dom.TypeParameter;
  import org.eclipse.jdt.core.dom.UnionType;
  import org.eclipse.jdt.core.dom.VariableDeclaration;
  import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
  import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
  import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
  import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
  
  import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2;
  import org.eclipse.jdt.internal.corext.util.JDTUIHelperClasses;
  
  /**
   * JDT-UI-internal helper methods to create new {@link ASTNode}s.
   * Complements <code>AST#new*(..)</code> and <code>ImportRewrite#add*(..)</code>.
   * 
   * @see JDTUIHelperClasses
   */
  public class ASTNodeFactory {
  
  	private static final String STATEMENT_HEADER= "class __X__ { void __x__() { "; //$NON-NLS-1$
  	private static final String STATEMENT_FOOTER= "}}"; //$NON-NLS-1$
  
  	private static final String TYPE_HEADER= "class __X__ { abstract "; //$NON-NLS-1$
  	private static final String TYPE_FOOTER= " __f__(); }}"; //$NON-NLS-1$
  
  	private static final String TYPEPARAM_HEADER= "class __X__ { abstract <"; //$NON-NLS-1$
  	private static final String TYPEPARAM_FOOTER= "> void __f__(); }}"; //$NON-NLS-1$
  
  	private static class PositionClearer extends GenericVisitor {
  
  		public PositionClearer() {
  			super(true);
  		}
  
  		@Override
  		protected boolean visitNode(ASTNode node) {
  			node.setSourceRange(-1, 0);
  			return true;
  		}
  	}
  
  	private ASTNodeFactory() {
  		// no instance;
  	}
  
  	public static ASTNode newStatement(AST ast, String content) {
  		StringBuffer buffer= new StringBuffer(STATEMENT_HEADER);
  		buffer.append(content);
  		buffer.append(STATEMENT_FOOTER);
  		ASTParser p= ASTParser.newParser(ast.apiLevel());
  		p.setSource(buffer.toString().toCharArray());
  		CompilationUnit root= (CompilationUnit) p.createAST(null);
  		ASTNode result= ASTNode.copySubtree(ast, NodeFinder.perform(root, STATEMENT_HEADER.length(), content.length()));
  		result.accept(new PositionClearer());
  		return result;
  	}
  
  	public static Name newName(AST ast, String qualifiedName) {
  		return ast.newName(qualifiedName);
  	}
  
  	public static TypeParameter newTypeParameter(AST ast, String content) {
  		StringBuffer buffer= new StringBuffer(TYPEPARAM_HEADER);
  		buffer.append(content);
  		buffer.append(TYPEPARAM_FOOTER);
  		ASTParser p= ASTParser.newParser(ast.apiLevel());
  		p.setSource(buffer.toString().toCharArray());
  		CompilationUnit root= (CompilationUnit) p.createAST(null);
  		List<AbstractTypeDeclaration> list= root.types();
  		TypeDeclaration typeDecl= (TypeDeclaration) list.get(0);
  		MethodDeclaration methodDecl= typeDecl.getMethods()[0];
  		TypeParameter tp= (TypeParameter) methodDecl.typeParameters().get(0);
  		ASTNode result= ASTNode.copySubtree(ast, tp);
  		result.accept(new PositionClearer());
  		return (TypeParameter) result;
  	}
  
  
  	public static Type newType(AST ast, String content) {
  		StringBuffer buffer= new StringBuffer(TYPE_HEADER);
  		buffer.append(content);
  		buffer.append(TYPE_FOOTER);
  		ASTParser p= ASTParser.newParser(ast.apiLevel());
  		p.setSource(buffer.toString().toCharArray());
  		CompilationUnit root= (CompilationUnit) p.createAST(null);
  		List<AbstractTypeDeclaration> list= root.types();
  		TypeDeclaration typeDecl= (TypeDeclaration) list.get(0);
  		MethodDeclaration methodDecl= typeDecl.getMethods()[0];
  		ASTNode type= methodDecl.getReturnType2();
  		ASTNode result= ASTNode.copySubtree(ast, type);
  		result.accept(new PositionClearer());
  		return (Type)result;
  	}
  
  	/**
  	 * Returns an {@link ArrayType} that adds one dimension to the given type node.
  	 * If the given node is already an ArrayType, then a new {@link Dimension}
  	 * without annotations is inserted at the first position.
  	 * 
  	 * @param type the type to be wrapped
  	 * @return the array type
  	 * @since 3.10
  	 */
  	public static ArrayType newArrayType(Type type) {
  		if (type instanceof ArrayType) {
  			Dimension dimension= type.getAST().newDimension();
  			ArrayType arrayType= (ArrayType) type;
  			arrayType.dimensions().add(0, dimension); // first dimension is outermost
  			return arrayType;
  		} else {
  			return type.getAST().newArrayType(type);
  		}
  	}
  
  	/**
  	 * Returns the new type node corresponding to the type of the given declaration
  	 * including the extra dimensions.
  	 * @param ast The AST to create the resulting type with.
  	 * @param declaration The variable declaration to get the type from
  	 * @return a new type node created with the given AST.
  	 */
  	public static Type newType(AST ast, VariableDeclaration declaration) {
  		return newType(ast, declaration, null, null);
  	}
  
  	/**
  	 * Returns the new type node corresponding to the type of the given declaration
  	 * including the extra dimensions. If the type is a {@link UnionType}, use the LUB type.
  	 * If the <code>importRewrite</code> is <code>null</code>, the type may be fully-qualified.
  	 * 
  	 * @param ast The AST to create the resulting type with.
  	 * @param declaration The variable declaration to get the type from
  	 * @param importRewrite the import rewrite to use, or <code>null</code>
  	 * @param context the import rewrite context, or <code>null</code>
  	 * @return a new type node created with the given AST.
  	 * 
  	 * @since 3.7.1
  	 */
  	public static Type newType(AST ast, VariableDeclaration declaration, ImportRewrite importRewrite, ImportRewriteContext context) {
  		if (declaration instanceof VariableDeclarationFragment && declaration.getParent() instanceof LambdaExpression) {
  			return newType((LambdaExpression) declaration.getParent(), (VariableDeclarationFragment) declaration, ast, importRewrite, context);
  		}
  
  		Type type= ASTNodes.getType(declaration);
  		if (declaration instanceof SingleVariableDeclaration) {
  			Type type2= ((SingleVariableDeclaration) declaration).getType();
  			if (type2 instanceof UnionType) {
  				ITypeBinding typeBinding= type2.resolveBinding();
  				if (typeBinding != null) {
  					if (importRewrite != null) {
  						type= importRewrite.addImport(typeBinding, ast, context);
  						return type;
  					} else {
  						String qualifiedName= typeBinding.getQualifiedName();
  						if (qualifiedName.length() > 0) {
  							type= ast.newSimpleType(ast.newName(qualifiedName));
  							return type;
  						}
  					}
  				}
  				// XXX: fallback for intersection types or unresolved types: take first type of union
  				type= (Type) ((UnionType) type2).types().get(0);
  				return type;
  			}
  		}
  		
  		type= (Type) ASTNode.copySubtree(ast, type);
  		
  		List<Dimension> extraDimensions= declaration.extraDimensions();
  		if (!extraDimensions.isEmpty()) {
  			ArrayType arrayType;
  			if (type instanceof ArrayType) {
  				arrayType= (ArrayType) type;
  			} else {
  				arrayType= ast.newArrayType(type, 0);
  				type= arrayType;
  			}
  			arrayType.dimensions().addAll(ASTNode.copySubtrees(ast, extraDimensions));
  		}
  		return type;
  	}
  
  	private static Type newType(LambdaExpression lambdaExpression, VariableDeclarationFragment declaration, AST ast, ImportRewrite importRewrite, ImportRewriteContext context) {
  		IMethodBinding method= lambdaExpression.resolveMethodBinding();
  		if (method != null) {
  			ITypeBinding[] parameterTypes= method.getParameterTypes();
  			int index= lambdaExpression.parameters().indexOf(declaration);
  			ITypeBinding typeBinding= parameterTypes[index];
  			if (importRewrite != null) {
  				return importRewrite.addImport(typeBinding, ast, context);
  			} else {
  				String qualifiedName= typeBinding.getQualifiedName();
  