Package org.springframework.ide.eclipse.quickfix.jdt.computers

Source Code of org.springframework.ide.eclipse.quickfix.jdt.computers.RequestMappingParamTypeProposalComputer

/*******************************************************************************
*  Copyright (c) 2012 VMware, Inc.
*  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:
*      VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.quickfix.jdt.computers;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.CompletionProposal;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.internal.ui.text.correction.AssistContext;
import org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposalComputer;
import org.eclipse.jdt.internal.ui.text.java.LazyJavaTypeCompletionProposal;
import org.eclipse.jdt.ui.SharedASTProvider;
import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext;
import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.source.SourceViewer;
import org.springframework.ide.eclipse.quickfix.Activator;
import org.springframework.ide.eclipse.quickfix.jdt.util.ProposalCalculatorUtil;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springsource.ide.eclipse.commons.core.SpringCoreUtils;
import org.springsource.ide.eclipse.commons.core.StatusHandler;

/**
* Content assist proposal computer for showing user a list of allowable type
* for a
* @RequestMapping method parameter. See {@link RequestMapping}
*
* @author Terry Denney
* @author Martin Lippert
* @since 2.6
*/
public class RequestMappingParamTypeProposalComputer extends JavaCompletionProposalComputer {

  // TODO: add javax.portlet.PortletRequest
  // TODO: add javax.portlet.ActionRequest
  // TODO: add javax.portlet.RenderRequest
  // TODO: add javax.portlet.PortletSession
  // TODO: add @RequestParam

  private static Class<?>[] PARAM_TYPE_CLASSES = new Class<?>[] { ServletRequest.class, HttpServletRequest.class,
      HttpSession.class, WebRequest.class, NativeWebRequest.class, Locale.class, InputStream.class, Reader.class,
      OutputStream.class, Writer.class, Map.class, Model.class, ModelMap.class, Errors.class,
      BindingResult.class, SessionStatus.class };

  @Override
  public List<ICompletionProposal> computeCompletionProposals(ContentAssistInvocationContext context,
      IProgressMonitor monitor) {
    if (context instanceof JavaContentAssistInvocationContext) {
      JavaContentAssistInvocationContext javaContext = (JavaContentAssistInvocationContext) context;

      // check if project is a spring project
      if (SpringCoreUtils.isSpringProject(javaContext.getProject().getProject())) {
        ICompilationUnit cu = javaContext.getCompilationUnit();
        if (ProposalCalculatorUtil.hasAnnotationOnType(cu, "Controller")) {
          ITextViewer viewer = javaContext.getViewer();

          if (viewer instanceof SourceViewer) {
            SourceViewer sourceViewer = (SourceViewer) viewer;
            int invocationOffset = context.getInvocationOffset();
            AssistContext assistContext = new AssistContext(cu, sourceViewer, invocationOffset, 0, SharedASTProvider.WAIT_NO);
            ASTNode node = assistContext.getCoveringNode();
            // cursor is at the beginning of an empty param list
            // [method(^)}
            if (node instanceof MethodDeclaration) {
              MethodDeclaration methodDecl = (MethodDeclaration) node;
              if (ProposalCalculatorUtil.hasAnnotation("RequestMapping", methodDecl)) {
                try {
                  // We need to discover if we're actually
                  // inside the parameter declaration -- node
                  // is reported as MethodDeclaration when
                  // we're inside annotation
                  IDocument document = sourceViewer.getDocument();
                  int relativeOffset = invocationOffset - methodDecl.getStartPosition();
                  String methodText = document.get(methodDecl.getStartPosition(),
                      methodDecl.getLength());
                  String methodName = methodDecl.getName().getFullyQualifiedName();
                  int getterLocation = methodText.indexOf(methodName) + methodName.length();
                  if (getterLocation < relativeOffset) {
                    return getProposals(methodDecl, "", invocationOffset, null, javaContext);
                  }
                }
                catch (BadLocationException e) {
                  StatusHandler
                      .log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
                }
              }
            }

            else if (node instanceof SimpleName) {
              SimpleName name = (SimpleName) node;
              ASTNode parentNode = name.getParent();
              // cursor is at the start of a param at the end of
              // the
              // param
              // list [metohd(param, ^)]
              if (parentNode instanceof VariableDeclarationFragment) {
                parentNode = parentNode.getParent();
                if (parentNode instanceof VariableDeclarationStatement) {
                  VariableDeclarationStatement varDeclStmt = (VariableDeclarationStatement) parentNode;
                  Type varDeclType = varDeclStmt.getType();
                  if (varDeclType instanceof SimpleType) {
                    SimpleType sType = (SimpleType) varDeclType;
                    parentNode = parentNode.getParent();
                    if (parentNode instanceof Block) {
                      Block block = (Block) parentNode;

                      try {
                        if (viewer.getDocument().getChar(block.getStartPosition()) != '{') {
                          parentNode = parentNode.getParent();
                          if (parentNode instanceof MethodDeclaration) {
                            MethodDeclaration methodDecl = (MethodDeclaration) parentNode;
                            return getProposals(methodDecl, sType.getName()
                                .getFullyQualifiedName(), invocationOffset,
                                varDeclStmt, javaContext);
                          }
                        }
                      }
                      catch (BadLocationException e) {
                        StatusHandler.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e
                            .getMessage(), e));
                      }
                    }
                  }
                }
              }

              // cursor is at the start of a param type
              else if (parentNode instanceof SimpleType) {
                SimpleType sType = (SimpleType) parentNode;
                parentNode = sType.getParent();
                if (parentNode instanceof SingleVariableDeclaration) {
                  SingleVariableDeclaration varDecl = (SingleVariableDeclaration) parentNode;
                  parentNode = varDecl.getParent();
                  if (parentNode instanceof MethodDeclaration) {
                    MethodDeclaration methodDecl = (MethodDeclaration) parentNode;
                    return getProposals(methodDecl, sType.getName().getFullyQualifiedName(),
                        invocationOffset, sType, javaContext);
                  }
                }
              }
            }

            // param at the end of a method param list
            // [method(param,
            // w^)]
            else if (node instanceof Block) {
              Block block = (Block) node;
              ASTNode parentNode = block.getParent();
              if (parentNode instanceof MethodDeclaration) {
                MethodDeclaration methodDecl = (MethodDeclaration) parentNode;
                try {
                  String blockContent = viewer.getDocument().get(block.getStartPosition(),
                      block.getLength());
                  if (blockContent.startsWith(",")) {
                    blockContent = blockContent.substring(1);

                    boolean isAnnotation = false;
                    while (blockContent.length() > 0) {
                      char currChar = blockContent.charAt(0);
                      if (Character.isWhitespace(currChar)) {
                        blockContent = blockContent.substring(1);
                        isAnnotation = false;
                      }
                      else if (currChar == '@') {
                        blockContent = blockContent.substring(1);
                        isAnnotation = true;
                      }
                      else if (Character.isLetter(currChar)) {
                        if (!isAnnotation) {
                          break;
                        }
                        else {
                          blockContent = blockContent.substring(1);
                        }
                      }
                      else {
                        break;
                      }
                    }

                    // skip annotations
                    if (blockContent.length() > 0) {
                      if (blockContent.charAt(0) == '@') {
                        blockContent = blockContent.substring(1);
                      }
                    }

                    StringBuilder filter = new StringBuilder();
                    while (blockContent.length() > 0) {
                      char currChar = blockContent.charAt(0);
                      if (Character.isLetter(currChar)) {
                        filter.append(currChar);
                        blockContent = blockContent.substring(1);
                      }
                      else {
                        break;
                      }
                    }

                    return getProposals(methodDecl, filter.toString(), invocationOffset, block,
                        javaContext);
                  }
                }
                catch (BadLocationException e) {
                  StatusHandler
                      .log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e));
                }
              }
            }

          }
        }
      }
    }

    return Collections.emptyList();
  }

  private List<ICompletionProposal> getProposals(MethodDeclaration methodDecl, String filter, int offset,
      ASTNode toBeRemoved, JavaContentAssistInvocationContext context) {
    List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>();

    for (Class<?> paramType : PARAM_TYPE_CLASSES) {
      if (paramType.getSimpleName().toLowerCase().startsWith(filter.toLowerCase())) {
        // proposals
        // .add(new
        // RequestMappingParamTypeCompletionProposal(methodDecl,
        // paramType, toBeRemoved, context));
        CompletionProposal proposal = CompletionProposal.create(CompletionProposal.TYPE_REF,
            context.getInvocationOffset());
        proposal.setCompletion(paramType.getCanonicalName().toCharArray());
        proposal.setDeclarationSignature(paramType.getPackage().getName().toCharArray());
        proposal.setFlags(paramType.getModifiers());
        proposal.setRelevance(Integer.MAX_VALUE);
        proposal.setReplaceRange(context.getInvocationOffset() - filter.length(), context.getInvocationOffset());
        proposal.setSignature(Signature.createTypeSignature(paramType.getCanonicalName(), true).toCharArray());
        LazyJavaTypeCompletionProposal typeProposal = new LazyJavaTypeCompletionProposal(proposal, context);
        typeProposal.setRelevance(Integer.MAX_VALUE);
        proposals.add(typeProposal);
      }
    }

    return proposals;
  }

}
TOP

Related Classes of org.springframework.ide.eclipse.quickfix.jdt.computers.RequestMappingParamTypeProposalComputer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.