Package org.sylfra.idea.plugins.revu.business

Source Code of org.sylfra.idea.plugins.revu.business.ReviewManager$ReviewExtendedDepth

package org.sylfra.idea.plugins.revu.business;

import com.intellij.AppTopics;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.*;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.sylfra.idea.plugins.revu.RevuBundle;
import org.sylfra.idea.plugins.revu.RevuException;
import org.sylfra.idea.plugins.revu.RevuPlugin;
import org.sylfra.idea.plugins.revu.externalizing.IReviewExternalizer;
import org.sylfra.idea.plugins.revu.model.Review;
import org.sylfra.idea.plugins.revu.model.ReviewStatus;
import org.sylfra.idea.plugins.revu.settings.AbstractReviewFilesRevuSettingsComponent;
import org.sylfra.idea.plugins.revu.settings.IRevuSettingsListener;
import org.sylfra.idea.plugins.revu.settings.project.AbstractReviewFilesRevuSettings;
import org.sylfra.idea.plugins.revu.settings.project.RevuProjectSettings;
import org.sylfra.idea.plugins.revu.settings.project.RevuProjectSettingsComponent;
import org.sylfra.idea.plugins.revu.settings.project.workspace.RevuWorkspaceSettings;
import org.sylfra.idea.plugins.revu.settings.project.workspace.RevuWorkspaceSettingsComponent;
import org.sylfra.idea.plugins.revu.ui.statusbar.StatusBarComponent;
import org.sylfra.idea.plugins.revu.ui.statusbar.StatusBarMessage;
import org.sylfra.idea.plugins.revu.utils.RevuUtils;
import org.sylfra.idea.plugins.revu.utils.RevuVfsUtils;

import java.io.*;
import java.util.*;

/**
* @author <a href="mailto:syllant@gmail.com">Sylvain FRANCOIS</a>
* @version $Id$
*/
public class ReviewManager implements ProjectComponent
{
  private static final Logger LOGGER = Logger.getInstance(ReviewManager.class.getName());
  private static final Map<File, String> EMBEDDED_REVIEWS = new HashMap<File, String>(1);

  static
  {
    EMBEDDED_REVIEWS.put(new File("[default]"), "/org/sylfra/idea/plugins/revu/resources/defaultReviewTemplate.xml");
  }

  private final Project project;
  private final RevuFileListener fileListener;
  private Map<Review, MetaReview> metaReviews;
  private Map<File, Review> reviewsByFiles;
  private Map<String, Review> reviewsByNames;
  private final List<IReviewListener> reviewListeners;
  private final List<IReviewExternalizationListener> reviewExternalizationListeners;
  private IRevuSettingsListener<RevuProjectSettings> projectSettingsListener;
  private IRevuSettingsListener<RevuWorkspaceSettings> workspaceSettingsListener;

  public ReviewManager(Project project)
  {
    this.project = project;
    this.fileListener = new RevuFileListener(project, this);
    metaReviews = new IdentityHashMap<Review, MetaReview>();
    reviewsByFiles = new HashMap<File, Review>();
    reviewsByNames = new HashMap<String, Review>();
    reviewListeners = new ArrayList<IReviewListener>();
    reviewExternalizationListeners = new ArrayList<IReviewExternalizationListener>();
  }

  @Nullable
  public Review getReviewByFile(@NotNull File file)
  {
    return reviewsByFiles.get(file);
  }

  @Nullable
  public Review getReviewByName(@NotNull String name)
  {
    return reviewsByNames.get(name);
  }

  public boolean hasReview(@NotNull String name)
  {
    return reviewsByNames.containsKey(name);
  }

  @NotNull
  public SortedSet<Review> getReviews()
  {
    return new TreeSet<Review>(reviewsByNames.values());
  }

  @NotNull
  public Collection<Review> getReviews(@Nullable String userLogin, @Nullable ReviewStatus... statuses)
  {
    return getReviews(null, userLogin, statuses);
  }

  @NotNull
  public Collection<Review> getReviews(@Nullable String userLogin, boolean active)
  {
    return getReviews(userLogin, (active ? new ReviewStatus[]{ReviewStatus.REVIEWING, ReviewStatus.FIXING} : null));
  }

  @NotNull
  public Collection<Review> getReviews(@Nullable Collection<Review> customReviews, @Nullable String userLogin,
    @Nullable ReviewStatus... statuses)
  {
    if (customReviews == null)
    {
      customReviews = reviewsByNames.values();
    }

    List<ReviewStatus> statusList = Arrays.asList((statuses == null) ? ReviewStatus.values() : statuses);

    List<Review> result = new ArrayList<Review>();
    for (Review review : customReviews)
    {
      if ((statusList.contains(review.getStatus())
        && ((userLogin == null) || (review.getDataReferential().getUser(userLogin, true) != null))))
      {
        result.add(review);
      }
    }

    return Collections.unmodifiableList(result);
  }

  private void installSettingsListeners()
  {
    projectSettingsListener = new IRevuSettingsListener<RevuProjectSettings>()
    {
      public void settingsChanged(RevuProjectSettings oldSettings, RevuProjectSettings newSettings)
      {
        if (!newSettings.getReviewFiles().equals(oldSettings.getReviewFiles()))
        {
          loadAndAdd(newSettings.getReviewFiles(), true);
        }
      }
    };
    project.getComponent(RevuProjectSettingsComponent.class).addListener(projectSettingsListener);

    workspaceSettingsListener = new IRevuSettingsListener<RevuWorkspaceSettings>()
    {
      public void settingsChanged(RevuWorkspaceSettings oldSettings, RevuWorkspaceSettings newSettings)
      {
        if (!newSettings.getReviewFiles().equals(oldSettings.getReviewFiles()))
        {
          loadAndAdd(newSettings.getReviewFiles(), false);
        }
      }
    };
    project.getComponent(RevuWorkspaceSettingsComponent.class).addListener(workspaceSettingsListener);
  }

  public void projectOpened()
  {
    StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable()
    {
      public void run()
      {
        initEmbeddedReviews();

        RevuWorkspaceSettings workspaceSettings = RevuUtils.getWorkspaceSettings(project);
        List<String> workspaceReviewPaths = workspaceSettings.getReviewFiles();
        List<String> projectReviewPaths = RevuUtils.getProjectSettings(project).getReviewFiles();

        List<String> allPaths = new ArrayList<String>(projectReviewPaths);
        allPaths.addAll(workspaceReviewPaths);

        loadAndAdd(allPaths, null);

        // Check that reviewingReviewName matches an existing review
        String reviewingReviewName = workspaceSettings.getReviewingReviewName();
        if (reviewingReviewName != null)
        {
          Review review = getReviewByName(reviewingReviewName);
          if ((review == null) || (!ReviewStatus.REVIEWING.equals(review.getStatus())))
          {
            workspaceSettings.setReviewingReviewName(null);
            project.getComponent(RevuWorkspaceSettingsComponent.class).loadState(workspaceSettings);
          }
        }

      }
    });

    installSettingsListeners();
  }

  public void projectClosed()
  {
    project.getComponent(RevuProjectSettingsComponent.class).removeListener(projectSettingsListener);
    project.getComponent(RevuWorkspaceSettingsComponent.class).removeListener(workspaceSettingsListener);
  }

  @NotNull
  public String getComponentName()
  {
    return RevuPlugin.PLUGIN_NAME + "." + getClass().getSimpleName();
  }

  public void initComponent()
  {
  }

  public void disposeComponent()
  {
    fileListener.dispose();
  }

  public void addReviewListener(@NotNull IReviewListener listener)
  {
    reviewListeners.add(listener);
  }

  public void removeReviewListener(@NotNull IReviewListener listener)
  {
    reviewListeners.remove(listener);
  }

  public void addReviewExternalizationListener(@NotNull IReviewExternalizationListener listener)
  {
    reviewExternalizationListeners.add(listener);
  }

  public void removeReviewExternalizationListener(@NotNull IReviewExternalizationListener listener)
  {
    reviewExternalizationListeners.remove(listener);
  }

  public void addReview(@NotNull Review review)
  {
    reviewsByFiles.put(review.getFile(), review);
    reviewsByNames.put(review.getName(), review);
    metaReviews.put(review, new MetaReview(review, -1, false));
  }

  public void removeReview(@NotNull Review review)
  {
    Review oldReview = reviewsByFiles.remove(review.getFile());
    reviewsByNames.remove(review.getName());
    metaReviews.remove(oldReview);

    fireReviewDeleted(review);
  }

  public void reviewFileChanged(@NotNull Review review, @NotNull VirtualFile newVFile)
  {
    File oldFile = review.getFile();
    File newFile = new File(newVFile.getPath());

    reviewsByFiles.remove(oldFile);

    review.setFile(newFile);
    reviewsByFiles.put(newFile, review);

    fireReviewChanged(review);

    Class<? extends AbstractReviewFilesRevuSettingsComponent> settingsComponentClass =
      review.isShared() ? RevuProjectSettingsComponent.class : RevuWorkspaceSettingsComponent.class;
    AbstractReviewFilesRevuSettingsComponent settingsComponent = project.getComponent(settingsComponentClass);

    AbstractReviewFilesRevuSettings state = (AbstractReviewFilesRevuSettings) settingsComponent.getState();
    List<String> reviewFiles = state.getReviewFiles();
    int index = reviewFiles.indexOf(RevuVfsUtils.buildRelativePath(project, oldFile));
    if (index != -1)
    {
      reviewFiles.set(index, RevuVfsUtils.buildRelativePath(project, newFile));
      settingsComponent.loadState(state);
    }
  }

  public boolean isContentModified(@NotNull Review review)
  {
    MetaReview meta = metaReviews.get(review);
    return ((meta == null) || (review.hashCode() != meta.reviewHashCode));
  }

  public long getLastSavedTStamp(@NotNull Review review)
  {
    MetaReview meta = metaReviews.get(review);
    return (meta == null) ? -1 : meta.lastSaved;
  }

  private boolean isSaving(Review review)
  {
    MetaReview meta = metaReviews.get(review);
    return (meta != null) && meta.isSaving;
  }

  @Nullable
  private InputStream getInputStream(@NotNull Review review) throws IOException
  {
    if (!review.isExternalizable())
    {
      return null;
    }

    // Embedded review
    if (review.isEmbedded())
    {
      return getClass().getClassLoader().getResourceAsStream(EMBEDDED_REVIEWS.get(review.getFile()));
    }

    return new FileInputStream(review.getFile());
  }

  private void initEmbeddedReviews()
  {
    reviewsByNames.clear();
    reviewsByFiles.clear();
    metaReviews.clear();

    for (Map.Entry<File, String> entry : EMBEDDED_REVIEWS.entrySet())
    {
      Review review = new Review();
      review.setFile(entry.getKey());
      review.setEmbedded(true);
      load(review, false);
      addReview(review);
    }
  }

  private void loadAndAdd(@NotNull List<String> filePaths, @Nullable Boolean sharedFilter)
  {
    List<Review> reviewsToLoad = prepareReviewsToLoad(filePaths);

    Map<String, Review> changedReviews = new HashMap<String, Review>();

    if (sharedFilter != null)
    {
      // Delete obsolete reviews
      Collection<Review> reviews = new HashSet<Review>(getReviews());
      for (Iterator<Review> it = reviews.iterator(); it.hasNext();)
      {
        Review review = it.next();
        if ((review.isEmbedded()) || (review.isShared() != sharedFilter))
        {
          continue;
        }
        if (review.isExternalizable()) {
          String filePath = RevuVfsUtils.buildRelativePath(project, review.getFile());
          if (filePaths.contains(filePath)) {
            changedReviews.put(filePath, review);
          } else {
            fireReviewDeleted(review);
          }
        }
        Review oldReview = reviewsByFiles.remove(review.getFile());
        reviewsByNames.remove(review.getName());
        metaReviews.remove(oldReview);
        it.remove();
      }
    }

    // Load remaining reviews and added review
    for (Review review : reviewsToLoad)
    {
      if (!load(review, false))
      {
        continue;
      }

      if ((sharedFilter == null) || (review.isShared() == sharedFilter))
      {
        addReview(review);
      }
    }

    for (Review review : getReviews())
    {
      if ((!review.isEmbedded()) && (((sharedFilter == null) || review.isShared() == sharedFilter)))
      {
        metaReviews.put(review, new MetaReview(review, System.currentTimeMillis(), false));

        if (changedReviews.containsValue(review))
        {
          fireReviewChanged(review);
        }
        else
        {
          fireReviewAdded(review);
        }
      }
    }
  }

  private List<Review> prepareReviewsToLoad(List<String> relativePaths)
  {
    Map<String, ReviewExtendedDepth> reviewByNames = new HashMap<String, ReviewExtendedDepth>(relativePaths.size());
    for (String relativePath : relativePaths)
    {
      File file = RevuVfsUtils.findFileFromRelativePath(project, relativePath);
      Review review = reviewsByFiles.get(file);
      if (review == null)
      {
        review = new Review();
        review.setFile(file);
      }

      if (load(review, true))
      {
        ReviewExtendedDepth reviewExtendedDepth = new ReviewExtendedDepth(review, 0);
        reviewByNames.put(review.getName(), reviewExtendedDepth);
      }
    }

    List<ReviewExtendedDepth> reviewExtendedDepths = new ArrayList<ReviewExtendedDepth>(reviewByNames.values());
    for (ReviewExtendedDepth reviewExtendedDepth : reviewExtendedDepths)
    {
      Review review = reviewExtendedDepth.review;
      if (review.getExtendedReview() != null)
      {
        try
        {
          checkCyclicLink(review, review.getExtendedReview());
        }
        catch (RevuException e)
        {
          LOGGER.warn("Cyclic link: " + review.getFile(), e);
          fireReviewLoadFailed(e, review.getFile());
        }

        while ((review != null) && (review.getExtendedReview() != null))
        {
          reviewExtendedDepth.depth++;
          review = reviewsByNames.get(review.getExtendedReview().getName());
        }
      }
    }

    Collections.sort(reviewExtendedDepths, new Comparator<ReviewExtendedDepth>()
    {
      public int compare(ReviewExtendedDepth o1, ReviewExtendedDepth o2)
      {
        return o1.depth - o2.depth;
      }
    });

    List<Review> result = new ArrayList<Review>(reviewExtendedDepths.size());
    for (ReviewExtendedDepth reviewExtendedDepth : reviewExtendedDepths)
    {
      result.add(reviewExtendedDepth.review);
    }

    return result;
  }

  public boolean load(@NotNull final Review review, boolean prepare)
  {
    IReviewExternalizer reviewExternalizer = project.getComponent(IReviewExternalizer.class);

    InputStream inputStream = null;
    Exception exception = null;
    if (!review.isExternalizable()) {
      return true;
    }
    File file = review.getFile();
    try
    {
      inputStream = getInputStream(review);
      if (inputStream == null)
      {
        LOGGER.warn("Can't retrieve stream for review: " + review.getFile());
        //noinspection ThrowableInstanceNeverThrown
        exception = new FileNotFoundException(file.getPath());
      }
      else
      {
        reviewExternalizer.load(review, inputStream, prepare);

        if (!prepare)
        {
          fireReviewLoadSucceeded(review);
        }
      }
    }
    catch (IOException e)
    {
      exception = e;
      LOGGER.warn("IO error while loading review file: " + file, e);
    }
    catch (RevuException e)
    {
      exception = e;
      LOGGER.warn("Failed to load review file: " + file, e);
    }
    finally
    {
      try
      {
        if (inputStream != null)
        {
          inputStream.close();
        }
      }
      catch (IOException e)
      {
        LOGGER.warn("Failed to close release review file: " + file, e);
      }
    }

    if (exception != null)
    {
      fireReviewLoadFailed(exception, file);

      return false;
    }

    return true;
  }

  public void save(@NotNull Review review) throws RevuException, IOException
  {
    assert (!review.isEmbedded()) : "Embedded review cannot be saved : " + review;

    IReviewExternalizer reviewExternalizer = project.getComponent(IReviewExternalizer.class);

    boolean newReview;
    MetaReview metaReview = metaReviews.get(review);
    if (metaReview == null)
    {
      reviewsByFiles.put(review.getFile(), review);
      reviewsByNames.put(review.getName(), review);

      metaReview = new MetaReview(review, -1, true);
      metaReviews.put(review, metaReview);

      newReview = true;
    }
    else
    {
      metaReview.isSaving = true;
      metaReview.updateReviewHashcode();

      newReview = false;
    }

    try
    {
      if (review.isExternalizable())
      {
        reviewExternalizer.save(review, review.getFile());
      }
    }
    finally
    {
      metaReview.isSaving = false;
    }

    metaReview.lastSaved = System.currentTimeMillis();
    fireReviewSaveSucceeded(review);

    if (newReview)
    {
      fireReviewAdded(review);
    }
    else
    {
      fireReviewChanged(review);
    }
  }

  public void saveChanges(@NotNull Review review)
  {
    try
    {
      save(review);
    }
    catch (Exception exception)
    {
      LOGGER.warn(exception);

      final String details = ((exception.getLocalizedMessage() == null)
        ? exception.toString() : exception.getLocalizedMessage());
      project.getComponent(StatusBarComponent.class).addMessage(new StatusBarMessage(StatusBarMessage.Type.ERROR,
        RevuBundle.message("friendlyError.externalizing.save.error.title.text"),
        RevuBundle.message("friendlyError.externalizing.load.error.details.text", review.getFile(), details)), true);

      return;
    }

    fireReviewChanged(review);
  }

  public void saveSilently(@NotNull Review review)
  {
    Exception exception = null;
    try
    {
      save(review);
    }
    catch (IOException e)
    {
      LOGGER.warn("IO error while writing review file: " + review.getFile(), e);
      exception = e;
    }
    catch (RevuException e)
    {
      LOGGER.warn("Failed to save review file : " + review.getFile(), e);
      exception = e;
    }

    if (exception != null)
    {
      fireReviewSavedFailed(review, exception);
    }
  }

  public void saveChangedReviews()
  {
    for (Review review : getReviews())
    {
      if (!review.isEmbedded())
      {
        MetaReview metaReview = metaReviews.get(review);
        if (review.hashCode() != metaReview.reviewHashCode)
        {
          saveSilently(review);
        }
      }
    }
  }

  public void checkCyclicLink(@NotNull Review main, @NotNull Review extendedRoot)
    throws RevuException
  {
    checkCyclicLink(main, extendedRoot, extendedRoot);
  }

  private void checkCyclicLink(@NotNull Review main, @NotNull Review extendedRoot, @NotNull Review extendedChild)
    throws RevuException
  {
    if (main.getName().equals(extendedChild.getName()))
    {
      throw new RevuException(
        RevuBundle.message("friendlyError.externalizing.cyclicReview.details.text",
          main.getFile(), main.getName(),
          extendedRoot.getFile(), extendedRoot.getName()));
    }

    Review extendedChild2;
    while ((extendedChild2 = extendedChild.getExtendedReview()) != null)
    {
      checkCyclicLink(main, extendedRoot, extendedChild2);
    }
  }

  private void fireReviewAdded(Review review)
  {
    // Defensive copy against concurrent modifications
    List<IReviewListener> copy = new ArrayList<IReviewListener>(reviewListeners);
    for (IReviewListener listener : copy)
    {
      listener.reviewAdded(review);
    }
  }

  private void fireReviewChanged(Review review)
  {
    // Defensive copy against concurrent modifications
    List<IReviewListener> copy = new ArrayList<IReviewListener>(reviewListeners);
    for (IReviewListener listener : copy)
    {
      listener.reviewChanged(review);
    }
  }

  private void fireReviewDeleted(Review review)
  {
    // Defensive copy against concurrent modifications
    List<IReviewListener> copy = new ArrayList<IReviewListener>(reviewListeners);
    for (IReviewListener listener : copy)
    {
      listener.reviewDeleted(review);
    }
  }

  private void fireReviewLoadFailed(Exception exception, File file)
  {
    List<IReviewExternalizationListener> copy =
      new ArrayList<IReviewExternalizationListener>(reviewExternalizationListeners);
    for (IReviewExternalizationListener listener : copy)
    {
      listener.loadFailed(file, exception);
    }
  }

  private void fireReviewLoadSucceeded(Review review)
  {
    List<IReviewExternalizationListener> copy =
      new ArrayList<IReviewExternalizationListener>(reviewExternalizationListeners);
    for (IReviewExternalizationListener listener : copy)
    {
      listener.loadSucceeded(review);
    }
  }

  private void fireReviewSaveSucceeded(Review review)
  {
    List<IReviewExternalizationListener> copy =
      new ArrayList<IReviewExternalizationListener>(reviewExternalizationListeners);
    for (IReviewExternalizationListener listener : copy)
    {
      listener.saveSucceeded(review);
    }
  }

  private void fireReviewSavedFailed(Review review, Exception exception)
  {
    List<IReviewExternalizationListener> copy =
      new ArrayList<IReviewExternalizationListener>(reviewExternalizationListeners);
    for (IReviewExternalizationListener listener : copy)
    {
      listener.saveFailed(review, exception);
    }
  }

  private static final class ReviewExtendedDepth
  {
    Review review;
    int depth;

    private ReviewExtendedDepth(@NotNull Review review, int depth)
    {
      this.review = review;
      this.depth = depth;
    }
  }

  private static final class MetaReview
  {
    Review review;
    int reviewHashCode;
    long lastSaved;
    boolean isSaving;

    public MetaReview(Review review, long lastSaved, boolean isSaving)
    {
      this.review = review;
      this.lastSaved = lastSaved;
      this.isSaving = isSaving;
      updateReviewHashcode();
    }

    void updateReviewHashcode()
    {
      reviewHashCode = review.hashCode();
    }
  }

  /**
   * @author <a href="mailto:syllant@gmail.com">Sylvain FRANCOIS</a>
   * @version $Id$
   */
  public static class RevuFileListener implements Disposable
  {
    private final Project project;
    private final ReviewManager reviewManager;
    private final VirtualFileListener virtualFileListener;
    private final FileDocumentManagerAdapter fileDocumentManagerListener;
    private MessageBusConnection messageBusConnection;

    public RevuFileListener(final Project project, final ReviewManager reviewManager)
    {
      this.reviewManager = reviewManager;
      this.project = project;

      virtualFileListener = new VirtualFileAdapter()
      {
        @Override
        public void contentsChanged(VirtualFileEvent event)
        {
          VirtualFile vFile = event.getFile();

          Review review = reviewManager.getReviewByFile(new File(vFile.getPath()));
          if ((review != null)
            && (vFile.getTimeStamp() > reviewManager.getLastSavedTStamp(review))
            && (!reviewManager.isSaving(review)))
          {
            if (Messages.showOkCancelDialog(project,
              RevuBundle.message("general.reviewFileChanged.text", review.getName()),
              RevuBundle.message("general.reviewFileChanged.title"),
              Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE)
            {
              reviewManager.load(review, false);
              reviewManager.fireReviewChanged(review);
            }
          }
        }

        @Override
        public void fileDeleted(VirtualFileEvent event)
        {
          VirtualFile vFile = event.getFile();
          Review review = reviewManager.getReviewByFile(new File(vFile.getPath()));
          if (review != null)
          {
            reviewManager.removeReview(review);
          }
        }

        @Override
        public void propertyChanged(VirtualFilePropertyEvent event)
        {
          if (VirtualFile.PROP_NAME.equals(event.getPropertyName()))
          {
            String oldPath = event.getFile().getParent().getPath() + "/" + event.getOldValue();
            pathChanged(event.getFile(), oldPath);
          }
        }

        @Override
        public void fileMoved(VirtualFileMoveEvent event)
        {
          String oldPath = event.getOldParent().getPath() + "/" + event.getFileName();
          pathChanged(event.getFile(), oldPath);
        }
      };

      fileDocumentManagerListener = new FileDocumentManagerAdapter()
      {
        @Override
        public void beforeAllDocumentsSaving()
        {
          // File with issues
          reviewManager.saveChangedReviews();
        }
      };
      messageBusConnection = this.project.getMessageBus().connect();

      LocalFileSystem.getInstance().addVirtualFileListener(virtualFileListener);
      messageBusConnection.subscribe(AppTopics.FILE_DOCUMENT_SYNC, fileDocumentManagerListener);
    }

    private void pathChanged(VirtualFile vFile, String oldPath)
    {
      Review review = reviewManager.getReviewByFile(new File(oldPath));
      if (review != null)
      {
        reviewManager.reviewFileChanged(review, vFile);
      }
    }

    public void dispose()
    {
      LocalFileSystem.getInstance().removeVirtualFileListener(virtualFileListener);
      messageBusConnection.disconnect();
    }
  }
}
TOP

Related Classes of org.sylfra.idea.plugins.revu.business.ReviewManager$ReviewExtendedDepth

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.