content: /*******************************************************************************
   * Copyright (c) 2000, 2015 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.wst.jsdt.internal.ui.refactoring.contentassist;
  
  import java.util.Arrays;
  import java.util.List;
  
  import org.eclipse.wst.jsdt.core.CompletionProposal;
  import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
  import org.eclipse.wst.jsdt.core.IJavaScriptElement;
  import org.eclipse.wst.jsdt.core.IPackageFragment;
  import org.eclipse.wst.jsdt.core.IType;
  import org.eclipse.wst.jsdt.core.Signature;
  import org.eclipse.wst.jsdt.internal.corext.util.JavaModelUtil;
  import org.eclipse.wst.jsdt.internal.corext.util.TypeFilter;
  import org.eclipse.wst.jsdt.internal.ui.JavaPluginImages;
  import org.eclipse.wst.jsdt.internal.ui.viewsupport.JavaElementImageProvider;
  
  public class JavaTypeCompletionProcessor extends CUPositionCompletionProcessor {
  	
  	public static final String DUMMY_CLASS_NAME= "$$__$$"; //$NON-NLS-1$
  	
  	/**
  	 * The CU name to be used if no parent IJavaScriptUnit is available.
  	 * The main type of this class will be filtered out from the proposals list.
  	 */
  	public static final String DUMMY_CU_NAME= DUMMY_CLASS_NAME + JavaModelUtil.DEFAULT_CU_SUFFIX;
  	
  	/**
  	 * Creates a <code>JavaTypeCompletionProcessor</code>.
  	 * The completion context must be set via {@link #setPackageFragment(IPackageFragment)}.
  	 * 
  	 * @param enableBaseTypes complete java base types iff <code>true</code>
  	 * @param enableVoid complete <code>void</code> base type iff <code>true</code>
  	 */
  	public JavaTypeCompletionProcessor(boolean enableBaseTypes, boolean enableVoid) {
  		this(enableBaseTypes, enableVoid, false);
  	}
  	
  	/**
  	 * Creates a <code>JavaTypeCompletionProcessor</code>.
  	 * The completion context must be set via {@link #setPackageFragment(IPackageFragment)}.
  	 * 
  	 * @param enableBaseTypes complete java base types iff <code>true</code>
  	 * @param enableVoid complete <code>void</code> base type iff <code>true</code>
  	 * @param fullyQualify always complete to fully qualifies type iff <code>true</code>
  	 */
  	public JavaTypeCompletionProcessor(boolean enableBaseTypes, boolean enableVoid, boolean fullyQualify) {
  		super(new TypeCompletionRequestor(enableBaseTypes, enableVoid, fullyQualify));
  	}
  	
  	public char[] getCompletionProposalAutoActivationCharacters() {
  		// disable auto activation in dialog fields, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=89476
  		return null;
  	}
  
  	/**
  	 * @param packageFragment the new completion context
  	 */
  	public void setPackageFragment(IPackageFragment packageFragment) {
  		//TODO: Some callers have a better completion context and should include imports
  		// and nested classes of their declaring CU in WC's source.
  		if (packageFragment == null) {
  			setCompletionContext(null, null, null);
  		} else {
  			String before= "public class " + DUMMY_CLASS_NAME + " { ";  //$NON-NLS-1$//$NON-NLS-2$
  			String after= " }"; //$NON-NLS-1$
  			setCompletionContext(packageFragment.getJavaScriptUnit(DUMMY_CU_NAME), before, after);
  		}
  	}
  	
  	public void setExtendsCompletionContext(IJavaScriptElement javaElement) {
  		if (javaElement instanceof IPackageFragment) {
  			IPackageFragment packageFragment= (IPackageFragment) javaElement;
  			IJavaScriptUnit cu= packageFragment.getJavaScriptUnit(DUMMY_CU_NAME);
  			setCompletionContext(cu, "public class " + DUMMY_CLASS_NAME + " extends ", " {}"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
  		} else if (javaElement instanceof IType) {
  			// pattern: public class OuterType { public class Type extends /*caret*/  {} }
  			IType type= (IType) javaElement;
  			StringBuilder before =  new StringBuilder("public class "); //$NON-NLS-1$
  			before.append(type.getElementName());
  			before.append(" extends "); //$NON-NLS-1$
  			StringBuilder after= new StringBuilder(" {}"); //$NON-NLS-1$
  			IJavaScriptElement parent= type.getParent();
  			while (parent instanceof IType) {
  				type= (IType) parent;
  				before.append("public class "); //$NON-NLS-1$
  				before.append(type.getElementName());
  				before.append(' ').append('{');
  				after.append('}');
  				parent= type.getParent();
  			}
  			IJavaScriptUnit cu= type.getJavaScriptUnit();
  			setCompletionContext(cu, before.toString(), after.toString());
  		} else {
  			setCompletionContext(null, null, null);
  		}
  	}
  
  //	public void setImplementsCompletionContext(IPackageFragment packageFragment) {
  //		IJavaScriptUnit cu= packageFragment.getCompilationUnit(DUMMY_CU_NAME);
  //		setCompletionContext(cu, "public class " + DUMMY_CLASS_NAME + " implements ", " {}"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
  //	}
  	
  	protected static class TypeCompletionRequestor extends CUPositionCompletionRequestor {
  		private static final String VOID= "void"; //$NON-NLS-1$
  		private static final List BASE_TYPES= Arrays.asList(
  			new String[] {"boolean", "byte", "char", "double", "float", "int", "long", "short"});  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
  		
  		private boolean fEnableBaseTypes;
  		private boolean fEnableVoid;
  		private final boolean fFullyQualify;
  		
  		public TypeCompletionRequestor(boolean enableBaseTypes, boolean enableVoid, boolean fullyQualify) {
  			fFullyQualify= fullyQualify;
  			fEnableBaseTypes= enableBaseTypes;
  			fEnableVoid= enableVoid;
  			setIgnored(CompletionProposal.ANONYMOUS_CLASS_DECLARATION, true);
  			setIgnored(CompletionProposal.FIELD_REF, true);
  			setIgnored(CompletionProposal.LABEL_REF, true);
  			setIgnored(CompletionProposal.LOCAL_VARIABLE_REF, true);
  			setIgnored(CompletionProposal.METHOD_DECLARATION, true);
  			setIgnored(CompletionProposal.METHOD_REF, true);
  			setIgnored(CompletionProposal.VARIABLE_DECLARATION, true);
  			setIgnored(CompletionProposal.POTENTIAL_METHOD_DECLARATION, true);
  			setIgnored(CompletionProposal.METHOD_NAME_REFERENCE, true);
  		}
  		
  		public void accept(CompletionProposal proposal) {
  			switch (proposal.getKind()) {
  				case CompletionProposal.PACKAGE_REF :
  					char[] packageName= proposal.getDeclarationSignature();
  					if (TypeFilter.isFiltered(packageName))
  						return;
  					addAdjustedCompletion(
  							new String(packageName),
  							new String(proposal.getCompletion()),
  							proposal.getReplaceStart(),
  							proposal.getReplaceEnd(),
  							proposal.getRelevance(),
  							JavaPluginImages.DESC_OBJS_PACKAGE);
  					return;
  					
  				case CompletionProposal.TYPE_REF :
  					char[] fullName= Signature.toCharArray(proposal.getSignature());
  					if (TypeFilter.isFiltered(fullName))
  						return;
  					StringBuffer buf= new StringBuffer();
  					buf.append(Signature.getSimpleName(fullName));
  					if (buf.length() == 0)
  						return; // this is the dummy class, whose $ have been converted to dots
  					char[] typeQualifier= Signature.getQualifier(fullName);
  					if (typeQualifier.length > 0) {
  						buf.append(" - "); //$NON-NLS-1$
  						buf.append(typeQualifier);
  					}
  					String name= buf.toString();
  					
  					addAdjustedTypeCompletion(
  							name,
  							new String(proposal.getCompletion()),
  							proposal.getReplaceStart(),
  							proposal.getReplaceEnd(),
  							proposal.getRelevance(),
  							JavaElementImageProvider.getTypeImageDescriptor(false, false, proposal.getFlags(), false),
  							fFullyQualify ? new String(fullName) : null);
  					return;
  					
  				case CompletionProposal.KEYWORD:
  					if (! fEnableBaseTypes)
  						return;
  					String keyword= new String(proposal.getName());
  					if ( (fEnableVoid && VOID.equals(keyword)) || (fEnableBaseTypes && BASE_TYPES.contains(keyword)) )
  						addAdjustedCompletion(
  								keyword,
  								new String(proposal.getCompletion()),
  								proposal.getReplaceStart(),
  								proposal.getReplaceEnd(),
  								proposal.getRelevance(),
  								null);
  					return;
  
  				default :
  					return;
  			}
  			
  		}
  	}
  }
  