org.eclipse.che.jdt.search.SearchManager.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.che.jdt.search.SearchManager.java

Source

/*******************************************************************************
 * Copyright (c) 2012-2015 Codenvy, S.A.
 * 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:
 * Codenvy, S.A. - initial API and implementation
 *******************************************************************************/

package org.eclipse.che.jdt.search;

import com.google.inject.Singleton;

import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.che.ide.ext.java.shared.dto.Region;
import org.eclipse.che.ide.ext.java.shared.dto.model.JavaProject;
import org.eclipse.che.ide.ext.java.shared.dto.search.FindUsagesResponse;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageDeclaration;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
import org.eclipse.jdt.internal.core.DocumentAdapter;
import org.eclipse.jdt.internal.ui.search.JavaSearchQuery;
import org.eclipse.jdt.internal.ui.search.JavaSearchResult;
import org.eclipse.jdt.internal.ui.search.JavaSearchScopeFactory;
import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.ui.search.ElementQuerySpecification;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.search.NewSearchUI;
import org.eclipse.search.ui.ISearchResult;
import org.eclipse.search.ui.text.Match;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Performs all Java related search.
 *
 * @author Evgen Vidolob
 */
@Singleton
public class SearchManager {
    private static final Logger LOG = LoggerFactory.getLogger(SearchManager.class);

    private static final Class<?>[] TYPES_FOR_FIND_USAGE = new Class[] { ICompilationUnit.class, IType.class,
            IMethod.class, IField.class, IPackageDeclaration.class, IImportDeclaration.class,
            IPackageFragment.class, ILocalVariable.class, ITypeParameter.class };

    public FindUsagesResponse findUsage(IJavaProject javaProject, String fqn, int offset) throws SearchException {
        try {
            ICompilationUnit compilationUnit;
            IType type = javaProject.findType(fqn);
            if (type == null) {
                throw new SearchException("Can't find type: " + fqn);
            }
            if (type.isBinary()) {
                compilationUnit = type.getClassFile().getWorkingCopy(DefaultWorkingCopyOwner.PRIMARY, null);
                if (compilationUnit == null) {
                    throw new SearchException("Can't find sources for: " + fqn + " type");
                }
            } else {
                compilationUnit = type.getCompilationUnit();
            }
            IJavaElement[] elements = compilationUnit.codeSelect(offset, 0);
            if (elements != null && elements.length == 1) {
                IJavaElement element = elements[0];
                if (isTypeValid(element, TYPES_FOR_FIND_USAGE)) {
                    return performFindUsageSearch(element);
                } else {
                    throw new SearchException("Find usage can't search for element: " + element.getElementName());
                }

            } else {
                throw new SearchException(
                        "Can't find element to search, try to move cursor to another place and invoke search again");
            }

        } catch (JavaModelException e) {
            LOG.error(e.getMessage(), e);
            throw new SearchException(String.format("Can't find project: %s or file for FQN: %s",
                    javaProject.getPath().toOSString(), fqn), e);
        } catch (BadLocationException e) {
            LOG.error(e.getMessage(), e);
            throw new SearchException("Some error happened when formatting search result", e);
        }
    }

    private FindUsagesResponse performFindUsageSearch(IJavaElement element)
            throws JavaModelException, BadLocationException {
        JavaSearchScopeFactory factory = JavaSearchScopeFactory.getInstance();
        boolean isInsideJRE = factory.isInsideJRE(element);
        JavaSearchQuery query = new JavaSearchQuery(new ElementQuerySpecification(element,
                IJavaSearchConstants.REFERENCES, factory.createWorkspaceScope(isInsideJRE), "workspace scope"));
        NewSearchUI.runQueryInForeground(null, query);
        ISearchResult result = query.getSearchResult();
        JavaSearchResult javaResult = ((JavaSearchResult) result);
        FindUsagesResponse response = DtoFactory.newDto(FindUsagesResponse.class);
        Map<String, List<org.eclipse.che.ide.ext.java.shared.dto.search.Match>> mapMaches = new HashMap<>();
        JavaElementToDtoConverter converter = new JavaElementToDtoConverter(javaResult);
        for (Object o : javaResult.getElements()) {
            IJavaElement javaElement = (IJavaElement) o;
            IDocument document = null;
            if (javaElement instanceof IMember) {
                IMember member = ((IMember) javaElement);
                if (member.isBinary()) {
                    if (member.getClassFile().getSource() != null) {
                        document = new Document(member.getClassFile().getSource());
                    }
                } else {
                    document = getDocument(member.getCompilationUnit());
                }
            } else if (javaElement instanceof IPackageDeclaration) {
                ICompilationUnit ancestor = (ICompilationUnit) (javaElement)
                        .getAncestor(IJavaElement.COMPILATION_UNIT);
                document = getDocument(ancestor);

            }
            converter.addElementToProjectHierarchy(javaElement);

            Match[] matches = javaResult.getMatches(o);

            List<org.eclipse.che.ide.ext.java.shared.dto.search.Match> matchList = new ArrayList<>();
            for (Match match : matches) {
                org.eclipse.che.ide.ext.java.shared.dto.search.Match dtoMatch = DtoFactory
                        .newDto(org.eclipse.che.ide.ext.java.shared.dto.search.Match.class);
                if (document != null) {
                    IRegion lineInformation = document.getLineInformationOfOffset(match.getOffset());

                    int offsetInLine = match.getOffset() - lineInformation.getOffset();
                    Region matchInLine = DtoFactory.newDto(Region.class).withOffset(offsetInLine)
                            .withLength(match.getLength());
                    dtoMatch.setMatchInLine(matchInLine);
                    dtoMatch.setMatchLineNumber(document.getLineOfOffset(match.getOffset()));
                    dtoMatch.setMatchedLine(document.get(lineInformation.getOffset(), lineInformation.getLength()));
                }
                dtoMatch.setFileMatchRegion(DtoFactory.newDto(Region.class).withOffset(match.getOffset())
                        .withLength(match.getLength()));
                matchList.add(dtoMatch);

            }
            mapMaches.put(javaElement.getHandleIdentifier(), matchList);
        }
        List<JavaProject> projects = converter.getProjects();
        response.setProjects(projects);
        response.setMatches(mapMaches);
        response.setSearchElementLabel(JavaElementLabels.getElementLabel(element, JavaElementLabels.ALL_DEFAULT));
        return response;
    }

    private IDocument getDocument(ICompilationUnit ancestor) throws JavaModelException {
        IDocument document;
        IBuffer buffer = ancestor.getBuffer();
        if (buffer instanceof org.eclipse.jdt.internal.ui.javaeditor.DocumentAdapter) {
            document = ((org.eclipse.jdt.internal.ui.javaeditor.DocumentAdapter) buffer).getDocument();
        } else {
            document = new DocumentAdapter(buffer);
        }
        return document;
    }

    private boolean isTypeValid(IJavaElement element, Class<?>[] classes) {
        if (element == null) {
            return false;
        }

        for (Class<?> clazz : classes) {
            if (clazz.isInstance(element)) {
                if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
                    return hasChildren((IPackageFragment) element);
                } else {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean hasChildren(IPackageFragment packageFragment) {
        try {
            return packageFragment.hasChildren();
        } catch (JavaModelException ex) {
            return false;
        }
    }
}