content: /*******************************************************************************
   * Copyright (c) 2005, 2011 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.text.java;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.eclipse.core.runtime.CoreException;
  import org.eclipse.core.runtime.NullProgressMonitor;
  import org.eclipse.wst.jsdt.core.CompletionProposal;
  import org.eclipse.wst.jsdt.core.IField;
  import org.eclipse.wst.jsdt.core.IJavaScriptElement;
  import org.eclipse.wst.jsdt.core.IJavaScriptProject;
  import org.eclipse.wst.jsdt.core.ILocalVariable;
  import org.eclipse.wst.jsdt.core.IMember;
  import org.eclipse.wst.jsdt.core.IType;
  import org.eclipse.wst.jsdt.core.JavaScriptModelException;
  import org.eclipse.wst.jsdt.core.search.IJavaScriptSearchScope;
  import org.eclipse.wst.jsdt.core.search.SearchEngine;
  import org.eclipse.wst.jsdt.core.search.SearchMatch;
  import org.eclipse.wst.jsdt.core.search.SearchParticipant;
  import org.eclipse.wst.jsdt.core.search.SearchPattern;
  import org.eclipse.wst.jsdt.core.search.SearchRequestor;
  import org.eclipse.wst.jsdt.internal.core.DefaultWorkingCopyOwner;
  import org.eclipse.wst.jsdt.internal.core.search.matching.FieldPattern;
  import org.eclipse.wst.jsdt.internal.core.util.QualificationHelpers;
  import org.eclipse.wst.jsdt.internal.corext.template.java.SignatureUtil;
  import org.eclipse.wst.jsdt.internal.ui.Logger;
  
  
  /**
   * Proposal info that computes the javadoc lazily when it is queried.
   *
   * 
   */
  public final class FieldProposalInfo extends MemberProposalInfo {	
  	/**
  	 * Creates a new proposal info.
  	 *
  	 * @param project the java project to reference when resolving types
  	 * @param proposal the proposal to generate information for
  	 */
  	public FieldProposalInfo(IJavaScriptProject project, CompletionProposal proposal) {
  		super(project, proposal);
  	}
  	
  	/**
  	 * <p>Returns the java element that this computer corresponds to, possibly <code>null</code>.</p>
  	 * 
  	 * <p><b>NOTE:</b> This overrides the parent implementation so that {@link #resolveMember()} is not called
  	 * because the field proposal can resolve to a none {@link IMember}.</p>
  	 * 
  	 * @return the java element that this computer corresponds to, possibly <code>null</code>
  	 * @throws JavaScriptModelException
  	 */
  	public IJavaScriptElement getJavaElement() throws JavaScriptModelException {
  		if (!fJavaElementResolved) {
  			fJavaElementResolved= true;
  			//call the internal resolve rather then #resolveMember
  			fElement = resolve();
  		}
  		return fElement;
  	}
  	
  	/**
  	 * @see org.eclipse.wst.jsdt.internal.ui.text.java.MemberProposalInfo#resolveMember()
  	 */
  	protected IMember resolveMember() throws JavaScriptModelException {
  		IMember member = null;
  		IJavaScriptElement element = this.resolve();
  		if(element instanceof IMember) {
  			member = (IMember)element;
  		}
  		return member;
  	}
  
  	/**
  	 * @return {@link IJavaScriptElement} that this field proposal resolves to
  	 * 
  	 * @throws JavaScriptModelException
  	 */
  	private IJavaScriptElement resolve() throws JavaScriptModelException {
  		//get the type name
  		char[] typeNameChars = fProposal.getDeclarationTypeName();
  		String declaringTypeName = null;
  		if(typeNameChars != null) {
  			declaringTypeName = String.valueOf(typeNameChars);
  		}
  		
  		/* try using the signature if type name not set
  		 * NOTE: old way of doing things, should be removed at some point
  		 */
  		if(declaringTypeName == null) {
  			char[] declarationSignature= fProposal.getDeclarationSignature();
  			if(declarationSignature != null) {
  				declaringTypeName = SignatureUtil.stripSignatureToFQN(String.valueOf(declarationSignature));
  			}
  		}
  		
  		//find the field
  		IJavaScriptElement resolvedField = null;
  		if(declaringTypeName != null) {
  			String fieldName = String.valueOf(fProposal.getName());
  			
  			IType[] types = this.fJavaProject.findTypes(declaringTypeName);
  			if(types != null && types.length > 0) {
  				for(int i = 0; i < types.length && resolvedField == null; ++i) {
  					IType type = types[i];
  					if (type != null) {
  						IField field = type.getField(fieldName);
  						if (field.exists()) {
  							resolvedField = field;
  						}
  					}
  				}
  			} else {
  				//create the search pattern
  				char[][] seperatedDeclaringTypename = QualificationHelpers.seperateFullyQualifedName(declaringTypeName.toCharArray());
  //				if(!CharOperation.equals(seperatedDeclaringTypename[QualificationHelpers.SIMPLE_NAMES_INDEX], IIndexConstants.GLOBAL_SYMBOL)) {
  					FieldPattern fieldPattern = new FieldPattern(true, false, false,
  								fieldName.toCharArray(),
  								seperatedDeclaringTypename[QualificationHelpers.QULIFIERS_INDEX],
  								seperatedDeclaringTypename[QualificationHelpers.SIMPLE_NAMES_INDEX],
  								SearchPattern.R_EXACT_MATCH);
  					
  					//search the index for a match
  					SearchEngine searchEngine = new SearchEngine(DefaultWorkingCopyOwner.PRIMARY);
  					IJavaScriptSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaScriptElement[] {this.fJavaProject});
  					final List matches = new ArrayList();
  					try {
  						searchEngine.search(fieldPattern,
  								new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()},
  								scope,
  								new SearchRequestor() {
  									public void acceptSearchMatch(SearchMatch match) throws CoreException {
  										Object element = match.getElement();
  										if(element instanceof IField || element instanceof ILocalVariable) {
  											matches.add(element);
  										}
  									}
  								},
  								new NullProgressMonitor());  //using a NPM here maybe a bad idea, but nothing better to do right now
  					}
  					catch (CoreException e) {
  						Logger.logException("Failed index search for field: " + fieldName, e); //$NON-NLS-1$
  					}
  					
  					// just use the first match found
  					if(!matches.isEmpty()) {
  						resolvedField = (IJavaScriptElement)matches.get(0);
  					}
  //				}
  			}
  		}
  		
  		return resolvedField;
  	}
  }
  