<commit_before>package com.google.sampling.experiential.server;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.datastore.TransactionOptions;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.sampling.experiential.datastore.ExperimentJsonEntityManager;
import com.google.sampling.experiential.datastore.PublicExperimentList;
import com.google.sampling.experiential.datastore.PublicExperimentList.CursorExerimentIdListPair;
import com.google.sampling.experiential.model.Event;
import com.pacoapp.paco.shared.model.SignalTimeDAO;
import com.pacoapp.paco.shared.model2.ActionTrigger;
import com.pacoapp.paco.shared.model2.ExperimentDAO;
import com.pacoapp.paco.shared.model2.ExperimentGroup;
import com.pacoapp.paco.shared.model2.ExperimentQueryResult;
import com.pacoapp.paco.shared.model2.ExperimentValidator;
import com.pacoapp.paco.shared.model2.InterruptTrigger;
import com.pacoapp.paco.shared.model2.JsonConverter;
import com.pacoapp.paco.shared.model2.PacoAction;
import com.pacoapp.paco.shared.model2.Schedule;
import com.pacoapp.paco.shared.model2.ScheduleTrigger;
import com.pacoapp.paco.shared.model2.SignalTime;
import com.pacoapp.paco.shared.model2.ValidationMessage;
import com.pacoapp.paco.shared.scheduling.ActionScheduleGenerator;
import com.pacoapp.paco.shared.util.ExperimentHelper;

class DefaultExperimentService implements ExperimentService {

  private static final Logger log = Logger.getLogger(DefaultExperimentService.class.getName());

  private String getExperimentAsJson(Long id) {
    return ExperimentJsonEntityManager.getExperiment(id);
  }


  @Override
  /**
   * This is to be used server side only because it does not scrub out participant id information.
   */
  public ExperimentDAO getExperiment(Long id) {
    String experimentJson = getExperimentAsJson(id);
    if (experimentJson != null) {
      return  JsonConverter.fromSingleEntityJson(experimentJson);
    }
    return null;
  }

  @Override
  public List<ExperimentDAO> getExperimentsById(List<Long> experimentIds, String email, DateTimeZone timezone) {
    List<Long> allowedExperimentIds = Lists.newArrayList();
    for (Long experimentId : experimentIds) {
      if (ExperimentAccessManager.isUserAllowedToGetExperiments(experimentId, email)) {
        allowedExperimentIds.add(experimentId);
      }
    }

    List<String> experimentJsons = getExperimentsByIdAsJson(allowedExperimentIds, email, timezone);
    List<ExperimentDAO> experiments = Lists.newArrayList();
    for (String experimentJson : experimentJsons) {
      if (experimentJson != null) {
        experiments .add(JsonConverter.fromSingleEntityJson(experimentJson));
      }
    }
    removeNonAdminData(email, experiments);
    return experiments;
  }

  protected List<ExperimentDAO> getExperimentsByIdInternal(List<Long> experimentIds, String email, DateTimeZone timezone) {
    List<String> experimentJsons = getExperimentsByIdAsJson(experimentIds, email, timezone);
    log.info("Got back " + experimentJsons.size() +" jsons for " + experimentIds.size() + " ids ( " + Joiner.on(",").join(experimentIds) + ")");
    List<ExperimentDAO> experiments = Lists.newArrayList();
    for (String experimentJson : experimentJsons) {
      if (experimentJson != null) {
        final ExperimentDAO fromSingleEntityJson = JsonConverter.fromSingleEntityJson(experimentJson);
        if (fromSingleEntityJson != null) {
          experiments.add(fromSingleEntityJson);
          log.info("Retrieved experimentDAO from json for experiment: " + fromSingleEntityJson.getTitle());
        } else {
          log.severe("could not recreate experiment for experiment data: " + experimentJson);
        }
      }
    }
    return experiments;
  }


  protected List<String> getExperimentsByIdAsJson(List<Long> experimentIds, String email, DateTimeZone timezone) {
 //   TODO who can access this call and in what role?
    // is email a participant or an admin?
    return ExperimentJsonEntityManager.getExperimentsById(experimentIds);
  }


  // save experiments
  @Override
  public List<ValidationMessage> saveExperiment(ExperimentDAO experiment,
                                                String loggedInUserEmail,
                                                DateTimeZone timezone) {
    if (ExperimentAccessManager.isUserAllowedToSaveExperiment(experiment.getId(), loggedInUserEmail)) {
      ensureIdsOnActionTriggerObjects(experiment);

      ExperimentValidator validator = new ExperimentValidator();
      experiment.validateWith(validator);
      List<ValidationMessage> results = validator.getResults();
      if (!results.isEmpty()) {
        return results;
      }

      DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
      TransactionOptions options = TransactionOptions.Builder.withXG(true);
      Transaction tx = ds.beginTransaction(options);
      try {
        if (experiment.getId() == null) {
          experiment.setCreator(loggedInUserEmail);
        }
        if (!experiment.getAdmins().contains(loggedInUserEmail)) {
          experiment.getAdmins().add(loggedInUserEmail);
        }
        if (Strings.isNullOrEmpty(experiment.getContactEmail())) {
          experiment.setContactEmail(experiment.getCreator());
        }
        Integer version = experiment.getVersion();
        if (version == null || version == 0) {
          version = 1;
        } else {
          version++;
        }
        experiment.setVersion(version);
        Key experimentKey = ExperimentJsonEntityManager.saveExperiment(ds, tx, JsonConverter.jsonify(experiment),
                                                                       experiment.getId(),
                                                                       experiment.getTitle(),
                                                                       experiment.getVersion());

        experiment.setId(experimentKey.getId());
        ExperimentAccessManager.updateAccessControlEntities(ds, tx, experiment, experimentKey, timezone);
        tx.commit();
        return null;
      } catch (Exception e) {
        e.printStackTrace();
        throw new IllegalStateException(e);
      } finally {
        if (tx.isActive()) {
          tx.rollback();<commit_msg>update modifyDate when saving an experiment<commit_after>package com.google.sampling.experiential.server;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.datastore.TransactionOptions;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.sampling.experiential.datastore.ExperimentJsonEntityManager;
import com.google.sampling.experiential.datastore.PublicExperimentList;
import com.google.sampling.experiential.datastore.PublicExperimentList.CursorExerimentIdListPair;
import com.google.sampling.experiential.model.Event;
import com.pacoapp.paco.shared.model.SignalTimeDAO;
import com.pacoapp.paco.shared.model2.ActionTrigger;
import com.pacoapp.paco.shared.model2.ExperimentDAO;
import com.pacoapp.paco.shared.model2.ExperimentGroup;
import com.pacoapp.paco.shared.model2.ExperimentQueryResult;
import com.pacoapp.paco.shared.model2.ExperimentValidator;
import com.pacoapp.paco.shared.model2.InterruptTrigger;
import com.pacoapp.paco.shared.model2.JsonConverter;
import com.pacoapp.paco.shared.model2.PacoAction;
import com.pacoapp.paco.shared.model2.Schedule;
import com.pacoapp.paco.shared.model2.ScheduleTrigger;
import com.pacoapp.paco.shared.model2.SignalTime;
import com.pacoapp.paco.shared.model2.ValidationMessage;
import com.pacoapp.paco.shared.scheduling.ActionScheduleGenerator;
import com.pacoapp.paco.shared.util.ExperimentHelper;

class DefaultExperimentService implements ExperimentService {

  private static final Logger log = Logger.getLogger(DefaultExperimentService.class.getName());

  private String getExperimentAsJson(Long id) {
    return ExperimentJsonEntityManager.getExperiment(id);
  }


  @Override
  /**
   * This is to be used server side only because it does not scrub out participant id information.
   */
  public ExperimentDAO getExperiment(Long id) {
    String experimentJson = getExperimentAsJson(id);
    if (experimentJson != null) {
      return  JsonConverter.fromSingleEntityJson(experimentJson);
    }
    return null;
  }

  @Override
  public List<ExperimentDAO> getExperimentsById(List<Long> experimentIds, String email, DateTimeZone timezone) {
    List<Long> allowedExperimentIds = Lists.newArrayList();
    for (Long experimentId : experimentIds) {
      if (ExperimentAccessManager.isUserAllowedToGetExperiments(experimentId, email)) {
        allowedExperimentIds.add(experimentId);
      }
    }

    List<String> experimentJsons = getExperimentsByIdAsJson(allowedExperimentIds, email, timezone);
    List<ExperimentDAO> experiments = Lists.newArrayList();
    for (String experimentJson : experimentJsons) {
      if (experimentJson != null) {
        experiments .add(JsonConverter.fromSingleEntityJson(experimentJson));
      }
    }
    removeNonAdminData(email, experiments);
    return experiments;
  }

  protected List<ExperimentDAO> getExperimentsByIdInternal(List<Long> experimentIds, String email, DateTimeZone timezone) {
    List<String> experimentJsons = getExperimentsByIdAsJson(experimentIds, email, timezone);
    log.info("Got back " + experimentJsons.size() +" jsons for " + experimentIds.size() + " ids ( " + Joiner.on(",").join(experimentIds) + ")");
    List<ExperimentDAO> experiments = Lists.newArrayList();
    for (String experimentJson : experimentJsons) {
      if (experimentJson != null) {
        final ExperimentDAO fromSingleEntityJson = JsonConverter.fromSingleEntityJson(experimentJson);
        if (fromSingleEntityJson != null) {
          experiments.add(fromSingleEntityJson);
          log.info("Retrieved experimentDAO from json for experiment: " + fromSingleEntityJson.getTitle());
        } else {
          log.severe("could not recreate experiment for experiment data: " + experimentJson);
        }
      }
    }
    return experiments;
  }


  protected List<String> getExperimentsByIdAsJson(List<Long> experimentIds, String email, DateTimeZone timezone) {
 //   TODO who can access this call and in what role?
    // is email a participant or an admin?
    return ExperimentJsonEntityManager.getExperimentsById(experimentIds);
  }


  // save experiments
  @Override
  public List<ValidationMessage> saveExperiment(ExperimentDAO experiment,
                                                String loggedInUserEmail,
                                                DateTimeZone timezone) {
    if (ExperimentAccessManager.isUserAllowedToSaveExperiment(experiment.getId(), loggedInUserEmail)) {
      ensureIdsOnActionTriggerObjects(experiment);

      ExperimentValidator validator = new ExperimentValidator();
      experiment.validateWith(validator);
      List<ValidationMessage> results = validator.getResults();
      if (!results.isEmpty()) {
        return results;
      }

      DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
      TransactionOptions options = TransactionOptions.Builder.withXG(true);
      Transaction tx = ds.beginTransaction(options);
      try {
        if (experiment.getId() == null) {
          experiment.setCreator(loggedInUserEmail);
        }
        if (!experiment.getAdmins().contains(loggedInUserEmail)) {
          experiment.getAdmins().add(loggedInUserEmail);
        }
        if (Strings.isNullOrEmpty(experiment.getContactEmail())) {
          experiment.setContactEmail(experiment.getCreator());
        }
        Integer version = experiment.getVersion();
        if (version == null || version == 0) {
          version = 1;
        } else {
          version++;
        }
        experiment.setVersion(version);
        experiment.setModifyDate(com.pacoapp.paco.shared.util.TimeUtil.formatDate(new Date().getTime()));
        Key experimentKey = ExperimentJsonEntityManager.saveExperiment(ds, tx, JsonConverter.jsonify(experiment),
                                                                       experiment.getId(),
                                                                       experiment.getTitle(),
                                                                       experiment.getVersion());

        experiment.setId(experimentKey.getId());
        ExperimentAccessManager.updateAccessControlEntities(ds, tx, experiment, experimentKey, timezone);
        tx.commit();
        return null;
      } catch (Exception e) {
        e.printStackTrace();
        throw new IllegalStateException(e);
      } finally {
        if (tx.isActive()) {
          tx.rollback();
{'fraction_non_alphanumeric': 0.09628500943259324, 'fraction_numerical': 0.0020316354665505733, 'mean_word_length': 3.4432624113475176, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6893225', 'n_tokens_mistral': 3789, 'n_tokens_neox': 3755, 'n_words': 680}