// Path: src/com/jetbrains/crucible/connection/CrucibleManager.java
// public class CrucibleManager {
//   private final Project myProject;
//   private final Map<String, CrucibleSession> mySessions = new HashMap<String, CrucibleSession>();
// 
//   private static final Logger LOG = Logger.getInstance(CrucibleManager.class.getName());
// 
//   // implicitly constructed by pico container
//   @SuppressWarnings("UnusedDeclaration")
//   private CrucibleManager(@NotNull final Project project) {
//     myProject = project;
//   }
// 
//   public static CrucibleManager getInstance(@NotNull final Project project) {
//     return ServiceManager.getService(project, CrucibleManager.class);
//   }
// 
//   @Nullable
//   public List<BasicReview> getReviewsForFilter(@NotNull final CrucibleFilter filter) {
//     try {
//       final CrucibleSession session = getSession();
//       if (session != null) {
//         return session.getReviewsForFilter(filter);
//       }
//     }
//     catch (IOException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
//     }
//     catch (CrucibleApiException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
//     }
//     return null;
//   }
// 
//   @Nullable
//   public Review getDetailsForReview(@NotNull final String permId) {
//     try {
//       final CrucibleSession session = getSession();
//       if (session != null) {
//         return session.getDetailsForReview(permId);
//       }
//     }
//     catch (CrucibleApiException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
// 
//     }
//     catch (IOException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
//     }
//     return null;
//   }
// 
//   @Nullable
//   public Comment postComment(@NotNull final Comment comment, boolean isGeneral, String reviewId) {
//     try {
//       final CrucibleSession session = getSession();
//       if (session != null) {
//         return session.postComment(comment, isGeneral, reviewId);
//       }
//     }
//     catch (CrucibleApiException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
//     }
//     return null;
//   }
// 
//   public void completeReview(String reviewId) {
//     try {
//       final CrucibleSession session = getSession();
//       if (session != null) {
//         session.completeReview(reviewId);
//       }
//     }
//     catch (CrucibleApiException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
//     }
//   }
// 
//   @Nullable
//   public CrucibleSession getSession() throws CrucibleApiException {
//     final CrucibleSettings crucibleSettings = CrucibleSettings.getInstance();
//     final String serverUrl = crucibleSettings.SERVER_URL;
//     final String username = crucibleSettings.USERNAME;
//     if (StringUtil.isEmptyOrSpaces(serverUrl) || StringUtil.isEmptyOrSpaces(username)) {
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.define.host.username"), MessageType.ERROR);
//       return null;
//     }
//     try {
//       new URL(serverUrl);
//     }
//     catch (MalformedURLException e) {
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.wrong.host"), MessageType.ERROR);
//       return null;
//     }
//     String key = serverUrl + username + crucibleSettings.getPassword();
//     CrucibleSession session = mySessions.get(key);
//     if (session == null) {
//       session = new CrucibleSessionImpl(myProject);
//       session.login();
//       mySessions.put(key, session);
//       try {
//         session.fillRepoHash();
//       }
//       catch (IOException e) {
//         LOG.warn(e.getMessage());
//       }
//     }
//     return session;
//   }
// 
//   public Map<String,VirtualFile> getRepoHash() {
//     try {
//       final CrucibleSession session = getSession();
//       if (session != null) {
//         return session.getRepoHash();
//       }
//     }
//     catch (CrucibleApiException e) {
//       LOG.warn(e.getMessage());
//     }
//     return Collections.emptyMap();
//   }
// 
//   public void publishComment(@NotNull Review review, @NotNull Comment comment) throws IOException, CrucibleApiException {
//     CrucibleSession session = getSession();
//     if (session != null) {
//       session.publishComment(review, comment);
//     }
//   }
// }


import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.crucible.connection.CrucibleManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;
  @NotNull
  public List<Comment> getGeneralComments() {
    return myGeneralComments;
  }

  @NotNull
  public List<Comment> getComments() {
    return myComments;
  }

  @NotNull
  public Set<ReviewItem> getReviewItems() {
    return myItems;
  }

  public void addReviewItem(@NotNull final ReviewItem item) {
    myItems.add(item);
  }

  @Nullable
  public String getPathById(@NotNull final String id) {
    for (ReviewItem item : myItems) {
      if (item.getId().equals(id))
        return item.getPath();
    }
    return null;
  }

  @Nullable
  public String getIdByPath(@NotNull final String path, Project project) {
// Path: src/com/jetbrains/crucible/connection/CrucibleManager.java
// public class CrucibleManager {
//   private final Project myProject;
//   private final Map<String, CrucibleSession> mySessions = new HashMap<String, CrucibleSession>();
// 
//   private static final Logger LOG = Logger.getInstance(CrucibleManager.class.getName());
// 
//   // implicitly constructed by pico container
//   @SuppressWarnings("UnusedDeclaration")
//   private CrucibleManager(@NotNull final Project project) {
//     myProject = project;
//   }
// 
//   public static CrucibleManager getInstance(@NotNull final Project project) {
//     return ServiceManager.getService(project, CrucibleManager.class);
//   }
// 
//   @Nullable
//   public List<BasicReview> getReviewsForFilter(@NotNull final CrucibleFilter filter) {
//     try {
//       final CrucibleSession session = getSession();
//       if (session != null) {
//         return session.getReviewsForFilter(filter);
//       }
//     }
//     catch (IOException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
//     }
//     catch (CrucibleApiException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
//     }
//     return null;
//   }
// 
//   @Nullable
//   public Review getDetailsForReview(@NotNull final String permId) {
//     try {
//       final CrucibleSession session = getSession();
//       if (session != null) {
//         return session.getDetailsForReview(permId);
//       }
//     }
//     catch (CrucibleApiException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
// 
//     }
//     catch (IOException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
//     }
//     return null;
//   }
// 
//   @Nullable
//   public Comment postComment(@NotNull final Comment comment, boolean isGeneral, String reviewId) {
//     try {
//       final CrucibleSession session = getSession();
//       if (session != null) {
//         return session.postComment(comment, isGeneral, reviewId);
//       }
//     }
//     catch (CrucibleApiException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
//     }
//     return null;
//   }
// 
//   public void completeReview(String reviewId) {
//     try {
//       final CrucibleSession session = getSession();
//       if (session != null) {
//         session.completeReview(reviewId);
//       }
//     }
//     catch (CrucibleApiException e) {
//       LOG.warn(e.getMessage());
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.connection.error.message.$0", e.getMessage()), MessageType.ERROR);
//     }
//   }
// 
//   @Nullable
//   public CrucibleSession getSession() throws CrucibleApiException {
//     final CrucibleSettings crucibleSettings = CrucibleSettings.getInstance();
//     final String serverUrl = crucibleSettings.SERVER_URL;
//     final String username = crucibleSettings.USERNAME;
//     if (StringUtil.isEmptyOrSpaces(serverUrl) || StringUtil.isEmptyOrSpaces(username)) {
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.define.host.username"), MessageType.ERROR);
//       return null;
//     }
//     try {
//       new URL(serverUrl);
//     }
//     catch (MalformedURLException e) {
//       UiUtils.showBalloon(myProject, CrucibleBundle.message("crucible.wrong.host"), MessageType.ERROR);
//       return null;
//     }
//     String key = serverUrl + username + crucibleSettings.getPassword();
//     CrucibleSession session = mySessions.get(key);
//     if (session == null) {
//       session = new CrucibleSessionImpl(myProject);
//       session.login();
//       mySessions.put(key, session);
//       try {
//         session.fillRepoHash();
//       }
//       catch (IOException e) {
//         LOG.warn(e.getMessage());
//       }
//     }
//     return session;
//   }
// 
//   public Map<String,VirtualFile> getRepoHash() {
//     try {
//       final CrucibleSession session = getSession();
//       if (session != null) {
//         return session.getRepoHash();
//       }
//     }
//     catch (CrucibleApiException e) {
//       LOG.warn(e.getMessage());
//     }
//     return Collections.emptyMap();
//   }
// 
//   public void publishComment(@NotNull Review review, @NotNull Comment comment) throws IOException, CrucibleApiException {
//     CrucibleSession session = getSession();
//     if (session != null) {
//       session.publishComment(review, comment);
//     }
//   }
// }


// Path: src/com/jetbrains/crucible/model/Review.java
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.crucible.connection.CrucibleManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;

  @NotNull
  public List<Comment> getGeneralComments() {
    return myGeneralComments;
  }

  @NotNull
  public List<Comment> getComments() {
    return myComments;
  }

  @NotNull
  public Set<ReviewItem> getReviewItems() {
    return myItems;
  }

  public void addReviewItem(@NotNull final ReviewItem item) {
    myItems.add(item);
  }

  @Nullable
  public String getPathById(@NotNull final String id) {
    for (ReviewItem item : myItems) {
      if (item.getId().equals(id))
        return item.getPath();
    }
    return null;
  }

  @Nullable
  public String getIdByPath(@NotNull final String path, Project project) {
    final Map<String,VirtualFile> hash = CrucibleManager.getInstance(project).getRepoHash();