content: package ru.yandex.qatools.allure.junit;
  
  import org.junit.Ignore;
  import org.junit.internal.AssumptionViolatedException;
  import org.junit.runner.Description;
  import org.junit.runner.Result;
  import org.junit.runner.notification.Failure;
  import org.junit.runner.notification.RunListener;
  import ru.yandex.qatools.allure.Allure;
  import ru.yandex.qatools.allure.config.AllureModelUtils;
  import ru.yandex.qatools.allure.events.ClearStepStorageEvent;
  import ru.yandex.qatools.allure.events.TestCaseCanceledEvent;
  import ru.yandex.qatools.allure.events.TestCaseFailureEvent;
  import ru.yandex.qatools.allure.events.TestCaseFinishedEvent;
  import ru.yandex.qatools.allure.events.TestCasePendingEvent;
  import ru.yandex.qatools.allure.events.TestCaseStartedEvent;
  import ru.yandex.qatools.allure.events.TestSuiteFinishedEvent;
  import ru.yandex.qatools.allure.events.TestSuiteStartedEvent;
  import ru.yandex.qatools.allure.utils.AnnotationManager;
  
  import java.util.HashMap;
  import java.util.Map;
  import java.util.UUID;
  
  /**
   * @author Dmitry Baev charlie@yandex-team.ru
   *         Date: 20.12.13
   */
  public class AllureRunListener extends RunListener {
  
      private Allure lifecycle = Allure.LIFECYCLE;
  
      private final Map<String, String> suites = new HashMap<>();
  
      public void testSuiteStarted(Description description) {
          String uid = generateSuiteUid(description.getClassName());
  
          TestSuiteStartedEvent event = new TestSuiteStartedEvent(uid, description.getClassName());
          AnnotationManager am = new AnnotationManager(description.getAnnotations());
  
          am.update(event);
  
          event.withLabels(AllureModelUtils.createTestFrameworkLabel("JUnit"));
  
          getLifecycle().fire(event);
      }
  
      @Override
      public void testStarted(Description description) {
          TestCaseStartedEvent event = new TestCaseStartedEvent(getSuiteUid(description), description.getMethodName());
          AnnotationManager am = new AnnotationManager(description.getAnnotations());
  
          am.update(event);
  
          fireClearStepStorage();
          getLifecycle().fire(event);
      }
  
      @Override
      public void testFailure(Failure failure) {
          if (failure.getDescription().isTest()) {
              fireTestCaseFailure(failure.getException());
          } else {
              startFakeTestCase(failure.getDescription());
              fireTestCaseFailure(failure.getException());
              finishFakeTestCase();
          }
      }
  
      @Override
      public void testAssumptionFailure(Failure failure) {
          testFailure(failure);
      }
  
      @Override
      public void testIgnored(Description description) {
          startFakeTestCase(description);
          getLifecycle().fire(new TestCasePendingEvent().withMessage(getIgnoredMessage(description)));
          finishFakeTestCase();
      }
  
      @Override
      public void testFinished(Description description) {
          getLifecycle().fire(new TestCaseFinishedEvent());
      }
  
  
      public void testSuiteFinished(String uid) {
          getLifecycle().fire(new TestSuiteFinishedEvent(uid));
      }
  
      @Override
      public void testRunFinished(Result result) {
          for (String uid : getSuites().values()) {
              testSuiteFinished(uid);
          }
      }
  
      public String generateSuiteUid(String suiteName) {
          String uid = UUID.randomUUID().toString();
          synchronized (getSuites()) {
              getSuites().put(suiteName, uid);
          }
          return uid;
      }
  
      public String getSuiteUid(Description description) {
          String suiteName = description.getClassName();
          if (!getSuites().containsKey(suiteName)) {
              Class testClass = description.getTestClass();
              Description suiteDescription;
              if (testClass != null) {
                  suiteDescription = Description.createSuiteDescription(testClass);
              } else {
                  suiteDescription = Description.createSuiteDescription(description.getClassName());
              }
              testSuiteStarted(suiteDescription);
          }
          return getSuites().get(suiteName);
      }
  
      public String getIgnoredMessage(Description description) {
          Ignore ignore = description.getAnnotation(Ignore.class);
          return ignore == null || ignore.value().isEmpty() ? "Test ignored (without reason)!" : ignore.value();
      }
  
      public void startFakeTestCase(Description description) {
          String uid = getSuiteUid(description);
  
          String name = description.isTest() ? description.getMethodName() : description.getClassName();
          TestCaseStartedEvent event = new TestCaseStartedEvent(uid, name);
          AnnotationManager am = new AnnotationManager(description.getAnnotations());
          am.update(event);
  
          fireClearStepStorage();
          getLifecycle().fire(event);
      }
  
      public void finishFakeTestCase() {
          getLifecycle().fire(new TestCaseFinishedEvent());
      }
  
      public void fireTestCaseFailure(Throwable throwable) {
          if (throwable instanceof AssumptionViolatedException) {
              getLifecycle().fire(new TestCaseCanceledEvent().withThrowable(throwable));
          } else {
              getLifecycle().fire(new TestCaseFailureEvent().withThrowable(throwable));
          }
      }
  
      public void fireClearStepStorage() {
          getLifecycle().fire(new ClearStepStorageEvent());
      }
  
      public Allure getLifecycle() {
          return lifecycle;
      }
  
      public void setLifecycle(Allure lifecycle) {
          this.lifecycle = lifecycle;
      }
  
      public Map<String, String> getSuites() {
          return suites;
      }
  }
  