| /* |
| * Copyright 2000-2012 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.ide.favoritesTreeView; |
| |
| import com.intellij.ide.projectView.ViewSettings; |
| import com.intellij.ide.util.treeView.AbstractTreeNode; |
| import com.intellij.openapi.actionSystem.CommonDataKeys; |
| import com.intellij.openapi.actionSystem.DataContext; |
| import com.intellij.openapi.actionSystem.PlatformDataKeys; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.module.ModuleUtil; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.util.Comparing; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiFile; |
| import com.intellij.usageView.UsageInfo; |
| import com.intellij.usages.Usage; |
| import com.intellij.usages.UsageInfo2UsageAdapter; |
| import com.intellij.usages.UsageView; |
| import com.intellij.usages.impl.NullUsage; |
| import com.intellij.usages.rules.UsageInFile; |
| import com.intellij.usages.rules.UsageInFiles; |
| import com.intellij.util.ProxyComparator; |
| import com.intellij.util.SmartList; |
| import com.intellij.util.containers.Convertor; |
| import com.intellij.util.containers.MultiMap; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.*; |
| |
| /** |
| * Created with IntelliJ IDEA. |
| * User: Irina.Chernushina |
| * Date: 6/6/12 |
| * Time: 6:51 PM |
| */ |
| public class UsageFavoriteNodeProvider extends FavoriteNodeProvider { |
| private final static Map<String, TreeSet<WorkingSetSerializable>> ourSerializables = |
| new HashMap<String, TreeSet<WorkingSetSerializable>>(); |
| private final static Comparator<VirtualFile> VIRTUAL_FILE_COMPARATOR = |
| new ProxyComparator<String, VirtualFile>(new Convertor<VirtualFile, String>() { |
| @Override |
| public String convert(VirtualFile o) { |
| return o.getPath(); |
| } |
| }); |
| private static final Logger LOG = Logger.getInstance("#com.intellij.ide.favoritesTreeView.UsageFavoriteNodeProvider"); |
| |
| static { |
| final TreeSet<WorkingSetSerializable> usageSet = createSet(); |
| final UsageSerializable serializable = new UsageSerializable(); |
| ourSerializables.put(serializable.getId(), usageSet); |
| usageSet.add(serializable); |
| |
| final TreeSet<WorkingSetSerializable> fileSet = createSet(); |
| final FileSerializable fileSerializable = new FileSerializable(); |
| ourSerializables.put(fileSerializable.getId(), fileSet); |
| fileSet.add(fileSerializable); |
| |
| final TreeSet<WorkingSetSerializable> noteSet = createSet(); |
| final NoteSerializable noteSerializable = new NoteSerializable(); |
| ourSerializables.put(noteSerializable.getId(), noteSet); |
| noteSet.add(noteSerializable); |
| } |
| |
| private static TreeSet<WorkingSetSerializable> createSet() { |
| return new TreeSet<WorkingSetSerializable>(new Comparator<WorkingSetSerializable>() { |
| @Override |
| public int compare(WorkingSetSerializable o1, WorkingSetSerializable o2) { |
| assert o1.getId().equals(o1.getId()); |
| return Comparing.compare(o1.getVersion(), o2.getVersion()); |
| } |
| }); |
| } |
| |
| @Override |
| public Collection<AbstractTreeNode> getFavoriteNodes(DataContext context, ViewSettings viewSettings) { |
| final Project project = CommonDataKeys.PROJECT.getData(context); |
| if (project == null) { |
| return null; |
| } |
| final Usage[] usages = UsageView.USAGES_KEY.getData(context); |
| if (usages != null) { |
| |
| final List<AbstractTreeNode> result = new SmartList<AbstractTreeNode>(); |
| final MultiMap<VirtualFile, Usage> map = new MultiMap<VirtualFile, Usage>(); |
| final List<Usage> nonMapped = new ArrayList<Usage>(); |
| for (Usage usage : usages) { |
| if (usage instanceof UsageInFile) { |
| map.putValue(((UsageInFile)usage).getFile(), usage); |
| } |
| else if (usage instanceof UsageInFiles) { |
| final VirtualFile[] files = ((UsageInFiles)usage).getFiles(); |
| for (VirtualFile file : files) { |
| map.putValue(file, usage); |
| } |
| } |
| else { |
| nonMapped.add(usage); |
| } |
| } |
| |
| final TreeSet<VirtualFile> keys = new TreeSet<VirtualFile>(VIRTUAL_FILE_COMPARATOR); |
| keys.addAll(map.keySet()); |
| for (VirtualFile key : keys) { |
| final FileGroupingProjectNode grouping = new FileGroupingProjectNode(project, new File(key.getPath()), viewSettings); |
| result.add(grouping); |
| final Collection<Usage> subUsages = map.get(key); |
| for (Usage usage : subUsages) { |
| if (usage instanceof UsageInfo2UsageAdapter) { |
| final UsageProjectTreeNode node = |
| new UsageProjectTreeNode(project, ((UsageInfo2UsageAdapter)usage).getUsageInfo(), viewSettings); |
| grouping.addChild(node); |
| } |
| else if (NullUsage.INSTANCE.equals(usage)) { |
| continue; |
| } |
| else { |
| grouping.addChild(new NoteProjectNode(project, new NoteNode(usage.getPresentation().getPlainText(), true), viewSettings)); |
| } |
| } |
| } |
| for (Usage usage : nonMapped) { |
| if (usage instanceof UsageInfo2UsageAdapter) { |
| final UsageProjectTreeNode node = |
| new UsageProjectTreeNode(project, ((UsageInfo2UsageAdapter)usage).getUsageInfo(), viewSettings); |
| result.add(node); |
| } |
| else if (NullUsage.INSTANCE.equals(usage)) { |
| continue; |
| } |
| else { |
| result.add(new NoteProjectNode(project, new NoteNode(usage.getPresentation().getPlainText(), true), viewSettings)); |
| } |
| } |
| |
| return result; |
| } |
| return null; |
| } |
| |
| @Override |
| public AbstractTreeNode createNode(Project project, Object element, ViewSettings viewSettings) { |
| if (element instanceof UsageInfo) { |
| return new UsageProjectTreeNode(project, (UsageInfo)element, viewSettings); |
| } |
| else if (element instanceof InvalidUsageNoteNode) { |
| return new InvalidUsageNoteProjectNode(project, (InvalidUsageNoteNode)element, viewSettings); |
| } |
| else if (element instanceof NoteNode) { |
| return new NoteProjectNode(project, (NoteNode)element, viewSettings); |
| } |
| else if (element instanceof File) { |
| return new FileGroupingProjectNode(project, (File)element, viewSettings); |
| } |
| return super.createNode(project, element, viewSettings); |
| } |
| |
| @Override |
| public PsiElement getPsiElement(Object element) { |
| if (element instanceof UsageInfo) { |
| return ((UsageInfo)element).getElement(); |
| } |
| return super.getPsiElement(element); |
| } |
| |
| @Override |
| public boolean elementContainsFile(Object element, VirtualFile vFile) { |
| return false; |
| } |
| |
| @Override |
| public int getElementWeight(Object element, boolean isSortByType) { |
| return 0; |
| } |
| |
| @Override |
| public String getElementLocation(Object element) { |
| if (element instanceof UsageInfo) { |
| final PsiElement psiElement = ((UsageInfo)element).getElement(); |
| final PsiFile file = psiElement.getContainingFile(); |
| /*if (parent != null) { |
| return ClassPresentationUtil.getNameForClass(parent, true); |
| }*/ |
| return file.getPresentation().getPresentableText();//+- // todo do smthg for invalid usage |
| } |
| else if (element instanceof File) { |
| return ((File)element).getParent(); |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean isInvalidElement(Object element) { |
| /*if (element instanceof UsageInfo) { |
| return ((UsageInfo)element).getElement().isValid(); |
| } else if (element instanceof InvalidUsageNoteNode) { |
| return true; |
| } */ |
| return false; |
| } |
| |
| @NotNull |
| @Override |
| public String getFavoriteTypeId() { |
| return "usage"; |
| } |
| |
| @Override |
| public String getElementUrl(Object element) { |
| //if (element instanceof UsageInfo) { |
| final TreeSet<WorkingSetSerializable> serializables = ourSerializables.get(element.getClass().getName()); |
| if (serializables != null && !serializables.isEmpty()) { |
| final WorkingSetSerializable last = serializables.last(); |
| //final ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| try { |
| //final ObjectOutputStream os = new ObjectOutputStream(baos); |
| final StringBuilder sb = new StringBuilder(); |
| sb.append(last.getId()); |
| sb.append(' '); |
| sb.append("" + last.getVersion()); |
| sb.append(' '); |
| |
| //os.writeUTF(last.getId()); |
| //os.writeInt(last.getVersion()); |
| last.serializeMe(element, sb); |
| //os.close(); |
| //final byte[] bytes = baos.toByteArray(); |
| return sb.toString(); |
| //return new String(bytes, 4, bytes.length - 4); |
| } |
| catch (IOException e) { |
| LOG.info(e); |
| return null; |
| } |
| } |
| //} |
| return null; |
| } |
| |
| @Override |
| public String getElementModuleName(Object element) { |
| if (element instanceof UsageInfo) { |
| Module module = ModuleUtil.findModuleForPsiElement(((UsageInfo)element).getElement()); |
| return module != null ? module.getName() : null; |
| } |
| return null; |
| } |
| |
| @Override |
| public Object[] createPathFromUrl(Project project, String url, String moduleName) { |
| try { |
| //final byte[] bytes = url.getBytes(CharsetToolkit.UTF8_CHARSET); |
| /*final byte[] wrapped = new byte[bytes.length + 4]; |
| final ByteArrayOutputStream bas = new ByteArrayOutputStream(); |
| final ObjectOutputStream oos = new ObjectOutputStream(bas); |
| oos.close(); |
| final byte[] header = bas.toByteArray(); |
| System.arraycopy(header, 0, wrapped, 0, 4); |
| System.arraycopy(bytes, 0, wrapped, 0, bytes.length);*/ |
| |
| //ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(bytes)); |
| final List<String> parts = StringUtil.split(url, " ", true); |
| if (parts.size() < 3) return null; |
| |
| final String id = parts.get(0); |
| final TreeSet<WorkingSetSerializable> set = ourSerializables.get(id); |
| if (set != null && !set.isEmpty()) { |
| final int version = Integer.parseInt(parts.get(1)); |
| final String cut = StringUtil.join(parts.subList(2, parts.size()), " "); |
| for (Iterator<WorkingSetSerializable> iterator = set.descendingIterator(); iterator.hasNext(); ) { |
| WorkingSetSerializable serializable = iterator.next(); |
| if (serializable.getVersion() == version) { |
| return readWithSerializable(project, url, cut, serializable); |
| } |
| } |
| readWithSerializable(project, url, cut, set.last()); |
| } |
| } |
| catch (IOException e) { |
| LOG.info(e); |
| } |
| return null; |
| } |
| |
| private Object[] readWithSerializable(Project project, String url, String is, WorkingSetSerializable serializable) |
| throws IOException { |
| Object obj = serializable.deserializeMe(project, is); |
| if (obj == null) { |
| obj = serializable.deserializeMeInvalid(project, is); |
| } |
| return obj == null ? null : new Object[]{obj}; |
| /*Object obj = serializable.deserializeMe(project, is); |
| if (obj == null) { |
| is.close(); |
| is = new ObjectInputStream(new ByteArrayInputStream(url.getBytes(CharsetToolkit.UTF8_CHARSET))); |
| is.readUTF(); |
| is.readInt(); |
| obj = serializable.deserializeMeInvalid(project, is); |
| } |
| if (obj != null) { |
| return new Object[]{obj}; |
| } else { |
| return null; |
| }*/ |
| } |
| } |