@Override
  public void onApplicationEvent(ContextRefreshedEvent event) {
    // Run it as System
    // Remember the original context
    SecurityContext origCtx = SecurityContextHolder.getContext();
    try {
      // Set a SystemSecurityToken
      SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
      SecurityContextHolder.getContext().setAuthentication(new SystemSecurityToken());

      Query q =
          new QueryImpl()
              .eq(ObservableFeature.DATATYPE, FieldTypeEnum.CATEGORICAL.toString().toLowerCase());
      for (ObservableFeature categoricalFeature :
          dataService.findAll(ObservableFeature.ENTITY_NAME, q, ObservableFeature.class)) {
        OmxLookupTableRepository repo =
            new OmxLookupTableRepository(
                dataService, categoricalFeature.getIdentifier(), queryResolver);
        dataService.addRepository(repo);
      }
    } finally {
      // Set the original context back when method is finished
      SecurityContextHolder.setContext(origCtx);
    }
  }
  // RULE: Feature can only belong to one Protocol in a DataSet.(see issue #1136)
  private void checkFeatureCanOnlyBelongToOneProtocolForOneDataSet() {
    // RULE: Feature can only belong to one Protocol in a DataSet. Check it (see issue #1136)
    Iterable<DataSet> dataSets = dataService.findAll(DataSet.ENTITY_NAME, DataSet.class);
    for (DataSet dataSet : dataSets) {
      List<Protocol> dataSetProtocols =
          ProtocolUtils.getProtocolDescendants(dataSet.getProtocolUsed(), true);

      for (Protocol protocol : dataSetProtocols) {
        for (ObservableFeature feature : protocol.getFeatures()) {
          for (Protocol p : dataSetProtocols) {
            if (!p.equals(protocol) && p.getFeatures().contains(feature)) {
              String message =
                  String.format(
                      "An ObservableFeature can only belong to one Protocol but feature '%s' belongs to both '%s' and '%s'",
                      feature.getIdentifier(), p.getIdentifier(), protocol.getIdentifier());

              throw new MolgenisValidationException(
                  Sets.newHashSet(
                      new ConstraintViolation(
                          message, feature.getIdentifier(), feature, null, null, 0)));
            }
          }
        }
      }
    }
  }
  public static void setUp(DataService dataService) throws Exception {
    features0 = new ArrayList<ObservableFeature>();
    features1 = new ArrayList<ObservableFeature>();
    allEntities = new ArrayList<Entity>();
    subProtocols = new ArrayList<Protocol>();
    subProtocols1 = new ArrayList<Protocol>();
    categories = new ArrayList<Category>();

    feature0 = new ObservableFeature();
    feature0.setId(0);
    feature0.setName("featureName" + 0);
    feature0.setIdentifier("feature" + 0);

    feature1 = new ObservableFeature();
    feature1.setId(1);
    feature1.setName("featureName" + 1);
    feature1.setIdentifier("feature" + 1);

    features0.add(feature0);
    features1.add(feature1);

    protocol0 = new Protocol();
    protocol0.setDescription("description0");
    protocol0.setIdentifier("identifier0");
    protocol0.setId(0);
    protocol0.setFeatures(features0);
    protocol1 = new Protocol();
    protocol1.setDescription("description1");
    protocol1.setIdentifier("identifier1");
    protocol1.setId(1);
    protocol1.setFeatures(features1);
    subProtocols1.add(protocol1);
    protocol2 = new Protocol();
    protocol2.setDescription("description2");
    protocol2.setIdentifier("identifier2");
    protocol2.setSubprotocols(subProtocols1);
    protocol2.setId(2);
    protocol3 = new Protocol();
    protocol3.setDescription("description3");
    protocol3.setIdentifier("identifier3");
    protocol3.setSubprotocols(subProtocols1);
    protocol3.setId(3);

    allEntities.add(protocol0);
    allEntities.add(protocol1);
    allEntities.add(protocol2);
    allEntities.add(protocol3);

    subProtocols.add(protocol0);

    protocolUsed = new Protocol();
    protocolUsed.setDescription("protocolUsed_description");
    protocolUsed.setIdentifier("protocolUsed_identifier");
    protocolUsed.setId(100);
    protocolUsed.setSubprotocols(subProtocols);
    allEntities.add(protocolUsed);

    dataset = new DataSet();
    dataset.setId(0);
    dataset.setIdentifier("dataset" + 0);
    dataset.setName("datasetname" + 0);
    dataset.setProtocolUsed(protocolUsed);

    observationSet0 = new ObservationSet();
    observationSet0.setId(0);
    observationSet0.setPartOfDataSet(dataset);

    observationSets0 = new ArrayList<Entity>();
    observationSets0.add(observationSet0);

    observationSet1 = new ObservationSet();
    observationSet1.setId(1);

    ObservedValue observedValue0 = new ObservedValue();
    observedValue0.setId(0);
    observedValue0.setObservationSet(observationSet0);
    observedValue0.setValue(new Value());
    observedValue0.setFeature(feature0);
    observedValue0.setObservationSet(observationSet0);
    observedValues0 = new ArrayList<ObservedValue>();
    observedValues0.add(observedValue0);

    ObservedValue observedValue1 = new ObservedValue();
    observedValue1.setId(1);
    observedValue1.setObservationSet(observationSet1);
    Value v1 = new Value();
    v1.setId(1);
    observedValue1.setValue(v1);
    observedValue1.setFeature(feature1);
    observedValue1.setObservationSet(observationSet1);
    observedValues1 = new ArrayList<ObservedValue>();
    observedValues1.add(observedValue1);

    observationSets0 = new ArrayList<Entity>();
    observationSets0.add(observationSet0);

    category0 = new Category();
    category0.setId(0);
    category0.setIdentifier("category" + 0);
    categories.add(category0);

    List<DataSet> datasets = new ArrayList<DataSet>();
    datasets.add(dataset);

    when(dataService.findAllAsList(
            DataSet.ENTITY_NAME, new QueryImpl().eq(DataSet.IDENTIFIER, "dataset1")))
        .thenReturn(Arrays.<Entity>asList(dataset));
    when(dataService.findAllAsList(
            ObservedValue.ENTITY_NAME,
            new QueryImpl().eq(ObservedValue.OBSERVATIONSET, observationSet0)))
        .thenReturn(Arrays.<Entity>asList(observedValue0));

    when(dataService.findAllAsList(
            ObservationSet.ENTITY_NAME, new QueryImpl().eq(ObservationSet.PARTOFDATASET, 0)))
        .thenReturn(Arrays.<Entity>asList(observationSet0));
  }
  @Override
  @Transactional(rollbackFor = IOException.class)
  public EntityImportReport doImport(
      RepositoryCollection repositories, DatabaseAction databaseAction) throws IOException {
    // All new repository identifiers
    List<String> newRepoIdentifiers = new ArrayList<String>();

    // First import entities, the data sheets are ignored in the entitiesimporter
    EntityImportReport importReport = entitiesImporter.importEntities(repositories, databaseAction);

    // RULE: Feature can only belong to one Protocol in a DataSet. Check it (see issue #1136)
    checkFeatureCanOnlyBelongToOneProtocolForOneDataSet();

    // Import data sheets
    for (String name : repositories.getEntityNames()) {
      Repository repository = repositories.getRepositoryByEntityName(name);

      if (repository.getName().startsWith(DATASET_SHEET_PREFIX)) {
        // Import DataSet sheet, create new OmxRepository
        String identifier = repository.getName().substring(DATASET_SHEET_PREFIX.length());

        if (!dataService.hasRepository(identifier)) {

          dataService.addRepository(
              new AggregateableCrudRepositorySecurityDecorator(
                  new OmxRepository(dataService, searchService, identifier, entityValidator)));
          newRepoIdentifiers.add(identifier);

          DataSet dataSet =
              dataService.findOne(
                  DataSet.ENTITY_NAME,
                  new QueryImpl().eq(DataSet.IDENTIFIER, identifier),
                  DataSet.class);

          List<Protocol> protocols =
              ProtocolUtils.getProtocolDescendants(dataSet.getProtocolUsed());
          List<ObservableFeature> categoricalFeatures = new ArrayList<ObservableFeature>();
          for (Protocol protocol : protocols) {
            List<ObservableFeature> observableFeatures = protocol.getFeatures();
            if (observableFeatures != null) {
              for (ObservableFeature observableFeature : observableFeatures) {
                String dataType = observableFeature.getDataType();
                FieldType type = MolgenisFieldTypes.getType(dataType);
                if (type.getEnumType() == FieldTypeEnum.CATEGORICAL) {
                  categoricalFeatures.add(observableFeature);
                }
              }
            }
          }
          for (ObservableFeature categoricalFeature : categoricalFeatures) {
            if (!dataService.hasRepository(
                OmxLookupTableEntityMetaData.createOmxLookupTableEntityMetaDataName(
                    categoricalFeature.getIdentifier()))) {
              dataService.addRepository(
                  new OmxLookupTableRepository(
                      dataService, categoricalFeature.getIdentifier(), queryResolver));
              newRepoIdentifiers.add(
                  OmxLookupTableEntityMetaData.createOmxLookupTableEntityMetaDataName(
                      categoricalFeature.getIdentifier()));
            }
          }
        }

        // Check if all column names in the excel sheet exist as attributes of the entity
        Set<ConstraintViolation> violations = Sets.newLinkedHashSet();
        EntityMetaData meta = dataService.getEntityMetaData(identifier);
        for (AttributeMetaData attr : repository.getEntityMetaData().getAttributes()) {
          if (meta.getAttribute(attr.getName()) == null) {
            String message =
                String.format(
                    "Unknown attributename '%s' for entity '%s'. Sheet: '%s'",
                    attr.getName(), meta.getName(), repository.getName());
            violations.add(new ConstraintViolation(message, attr.getName(), null, null, meta, 0));
          }
        }

        if (!violations.isEmpty()) {
          throw new MolgenisValidationException(violations);
        }

        // Import data into new OmxRepository
        try {
          dataService.add(identifier, repository);
        } catch (MolgenisValidationException e) {
          // Add sheet info
          for (ConstraintViolation violation : e.getViolations()) {
            if (violation.getRownr() > 0) {

              // Rownr +1 for header
              violation.setImportInfo(
                  String.format(
                      "Sheet: '%s', row: %d", repository.getName(), violation.getRownr() + 1));
            } else {
              violation.setImportInfo(String.format("Sheet: '%s'", repository.getName()));
            }
          }

          for (String newRepoIdentifier : newRepoIdentifiers) {
            dataService.removeRepository(newRepoIdentifier);
          }

          throw e;
        }

        int count = (int) RepositoryUtils.count(repository);
        importReport.addEntityCount(identifier, count);
        importReport.addNrImported(count);
      }
    }

    return importReport;
  }