// Path: cloud-vmware-server/src/main/java/jetbrains/buildServer/clouds/base/connector/AbstractInstance.java
// public abstract class AbstractInstance {
//   @NotNull
//   public abstract String getName();
// 
//   public abstract boolean isInitialized();
// 
//   public abstract Date getStartDate();
// 
//   public abstract String getIpAddress();
// 
//   public abstract InstanceStatus getInstanceStatus();
// 
//   @Nullable
//   public abstract String getProperty(String name);
// }
// 
// Path: cloud-vmware-server/src/main/java/jetbrains/buildServer/clouds/base/connector/CloudApiConnector.java
// public interface CloudApiConnector<T extends AbstractCloudImage, G extends AbstractCloudInstance> {
// 
//   void test() throws CheckedCloudException;
// 
//   /**
//    * A special key of the cloud connector. Used to determine whether this cloud connector can be used in several cloud profiles.
//    * <br/>
//    *
//    * It is supposed to represent the same username and server url/region/instance
//    * @return see above.
//    */
//   @NotNull
//   String getKey();
// 
//   @NotNull
//   <R extends AbstractInstance> Map<String, R> fetchInstances(@NotNull final T image) throws CheckedCloudException;
// 
//   @NotNull
//   <R extends AbstractInstance> Map<T, Map<String, R>> fetchInstances(@NotNull final Collection<T> images) throws CheckedCloudException;
// 
//   @NotNull
//   @Deprecated
//   TypedCloudErrorInfo[] checkImage(@NotNull final T image);
// 
//   @NotNull
//   Map<T, TypedCloudErrorInfo[]> checkImages(@NotNull final Collection<T> images);
// 
//   @NotNull
//   TypedCloudErrorInfo[] checkInstance(@NotNull final G instance);
// }
// 
// Path: cloud-vmware-server/src/main/java/jetbrains/buildServer/clouds/base/errors/CheckedCloudException.java
// public class CheckedCloudException extends Exception {
// 
//   public CheckedCloudException(final Throwable cause) {
//     super(cause);
//   }
// 
//   public CheckedCloudException(final String message) {
//     super(message);
//   }
// 
//   public CheckedCloudException(final String message, final Throwable cause) {
//     super(message, cause);
//   }
// }
// 
// Path: cloud-vmware-server/src/main/java/jetbrains/buildServer/clouds/base/errors/TypedCloudErrorInfo.java
// public class TypedCloudErrorInfo{
//   @NotNull private final String myType;
//   @NotNull private final String myMessage;
//   @NotNull private final String myDetails;
//   @Nullable private final Throwable myThrowable;
// 
//   public static TypedCloudErrorInfo fromException(@NotNull Throwable th){
//     return new TypedCloudErrorInfo(th.getMessage(), th.getMessage(), th.toString(), th);
//   }
// 
//   public TypedCloudErrorInfo(@NotNull final String message) {
//     this(message, message, null, null);
//   }
// 
//   public TypedCloudErrorInfo(@NotNull final String type, @NotNull final String message) {
//     this(type, message, null, null);
//   }
// 
//   public TypedCloudErrorInfo(@NotNull final String type, @NotNull final String message, @Nullable final String details) {
//     this(type, message, details, null);
//   }
// 
//   public TypedCloudErrorInfo(@Nullable final String type,
//                              @Nullable final String message,
//                              @Nullable final String details,
//                              @Nullable final Throwable throwable) {
//     myType = String.valueOf(type);
//     myMessage = String.valueOf(message);
//     myDetails = String.valueOf(details);
//     myThrowable = throwable;
//   }
// 
//   @NotNull
//   public String getType() {
//     return myType;
//   }
// 
//   @NotNull
//   public String getMessage() {
//     return myMessage;
//   }
// 
//   @NotNull
//   public String getDetails() {
//     return myDetails;
//   }
// 
//   @Nullable
//   public Throwable getThrowable() {
//     return myThrowable;
//   }
// 
// 
// }


import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import jetbrains.buildServer.clouds.base.connector.AbstractInstance;
import jetbrains.buildServer.clouds.base.connector.CloudApiConnector;
import jetbrains.buildServer.clouds.base.errors.CheckedCloudException;
import jetbrains.buildServer.clouds.base.errors.TypedCloudErrorInfo;
import org.jetbrains.annotations.NotNull;
   * @return see above.
   */
  @NotNull
  @Override
  public String getKey() {
    return "dummy_connector";
  }

  @NotNull
  @Override
  public <R extends AbstractInstance> Map<DummyCloudImage, Map<String, R>> fetchInstances(@NotNull final Collection<DummyCloudImage> images) throws CheckedCloudException {
    Map<DummyCloudImage, Map<String, R>> result = new HashMap<>();
    for (DummyCloudImage image: images) {
      if (fetchInstances(image).size() > 0)
      result.put(image, fetchInstances(image));
    }
    return result;
  }

  @NotNull
  @Override
  public <R extends AbstractInstance> Map<String, R> fetchInstances(@NotNull final DummyCloudImage image) throws CheckedCloudException {
    checkLatch("listImageInstances");
    return myRealInstanceMap.entrySet().stream()
                            .filter(e->e.getValue().getDummyImageName().equals(image.getId()))
                            .collect(Collectors.toMap(e->e.getKey(), e->(R)e.getValue()));
  }

  @NotNull
  @Override
// Path: cloud-vmware-server/src/main/java/jetbrains/buildServer/clouds/base/connector/AbstractInstance.java
// public abstract class AbstractInstance {
//   @NotNull
//   public abstract String getName();
// 
//   public abstract boolean isInitialized();
// 
//   public abstract Date getStartDate();
// 
//   public abstract String getIpAddress();
// 
//   public abstract InstanceStatus getInstanceStatus();
// 
//   @Nullable
//   public abstract String getProperty(String name);
// }
// 
// Path: cloud-vmware-server/src/main/java/jetbrains/buildServer/clouds/base/connector/CloudApiConnector.java
// public interface CloudApiConnector<T extends AbstractCloudImage, G extends AbstractCloudInstance> {
// 
//   void test() throws CheckedCloudException;
// 
//   /**
//    * A special key of the cloud connector. Used to determine whether this cloud connector can be used in several cloud profiles.
//    * <br/>
//    *
//    * It is supposed to represent the same username and server url/region/instance
//    * @return see above.
//    */
//   @NotNull
//   String getKey();
// 
//   @NotNull
//   <R extends AbstractInstance> Map<String, R> fetchInstances(@NotNull final T image) throws CheckedCloudException;
// 
//   @NotNull
//   <R extends AbstractInstance> Map<T, Map<String, R>> fetchInstances(@NotNull final Collection<T> images) throws CheckedCloudException;
// 
//   @NotNull
//   @Deprecated
//   TypedCloudErrorInfo[] checkImage(@NotNull final T image);
// 
//   @NotNull
//   Map<T, TypedCloudErrorInfo[]> checkImages(@NotNull final Collection<T> images);
// 
//   @NotNull
//   TypedCloudErrorInfo[] checkInstance(@NotNull final G instance);
// }
// 
// Path: cloud-vmware-server/src/main/java/jetbrains/buildServer/clouds/base/errors/CheckedCloudException.java
// public class CheckedCloudException extends Exception {
// 
//   public CheckedCloudException(final Throwable cause) {
//     super(cause);
//   }
// 
//   public CheckedCloudException(final String message) {
//     super(message);
//   }
// 
//   public CheckedCloudException(final String message, final Throwable cause) {
//     super(message, cause);
//   }
// }
// 
// Path: cloud-vmware-server/src/main/java/jetbrains/buildServer/clouds/base/errors/TypedCloudErrorInfo.java
// public class TypedCloudErrorInfo{
//   @NotNull private final String myType;
//   @NotNull private final String myMessage;
//   @NotNull private final String myDetails;
//   @Nullable private final Throwable myThrowable;
// 
//   public static TypedCloudErrorInfo fromException(@NotNull Throwable th){
//     return new TypedCloudErrorInfo(th.getMessage(), th.getMessage(), th.toString(), th);
//   }
// 
//   public TypedCloudErrorInfo(@NotNull final String message) {
//     this(message, message, null, null);
//   }
// 
//   public TypedCloudErrorInfo(@NotNull final String type, @NotNull final String message) {
//     this(type, message, null, null);
//   }
// 
//   public TypedCloudErrorInfo(@NotNull final String type, @NotNull final String message, @Nullable final String details) {
//     this(type, message, details, null);
//   }
// 
//   public TypedCloudErrorInfo(@Nullable final String type,
//                              @Nullable final String message,
//                              @Nullable final String details,
//                              @Nullable final Throwable throwable) {
//     myType = String.valueOf(type);
//     myMessage = String.valueOf(message);
//     myDetails = String.valueOf(details);
//     myThrowable = throwable;
//   }
// 
//   @NotNull
//   public String getType() {
//     return myType;
//   }
// 
//   @NotNull
//   public String getMessage() {
//     return myMessage;
//   }
// 
//   @NotNull
//   public String getDetails() {
//     return myDetails;
//   }
// 
//   @Nullable
//   public Throwable getThrowable() {
//     return myThrowable;
//   }
// 
// 
// }


// Path: cloud-vmware-server/src/test/java/jetbrains/buildServer/clouds/base/stubs/DummyApiConnector.java
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import jetbrains.buildServer.clouds.base.connector.AbstractInstance;
import jetbrains.buildServer.clouds.base.connector.CloudApiConnector;
import jetbrains.buildServer.clouds.base.errors.CheckedCloudException;
import jetbrains.buildServer.clouds.base.errors.TypedCloudErrorInfo;
import org.jetbrains.annotations.NotNull;

   * @return see above.
   */
  @NotNull
  @Override
  public String getKey() {
    return "dummy_connector";
  }

  @NotNull
  @Override
  public <R extends AbstractInstance> Map<DummyCloudImage, Map<String, R>> fetchInstances(@NotNull final Collection<DummyCloudImage> images) throws CheckedCloudException {
    Map<DummyCloudImage, Map<String, R>> result = new HashMap<>();
    for (DummyCloudImage image: images) {
      if (fetchInstances(image).size() > 0)
      result.put(image, fetchInstances(image));
    }
    return result;
  }

  @NotNull
  @Override
  public <R extends AbstractInstance> Map<String, R> fetchInstances(@NotNull final DummyCloudImage image) throws CheckedCloudException {
    checkLatch("listImageInstances");
    return myRealInstanceMap.entrySet().stream()
                            .filter(e->e.getValue().getDummyImageName().equals(image.getId()))
                            .collect(Collectors.toMap(e->e.getKey(), e->(R)e.getValue()));
  }

  @NotNull
  @Override
  public TypedCloudErrorInfo[] checkImage(@NotNull final DummyCloudImage image) {