Package com.google.testing.testify.risk.frontend.server.service.impl

Source Code of com.google.testing.testify.risk.frontend.server.service.impl.DataServiceImpl

// Copyright 2010 Google Inc. All Rights Reseved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


package com.google.testing.testify.risk.frontend.server.service.impl;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.testing.testify.risk.frontend.model.AccElementType;
import com.google.testing.testify.risk.frontend.model.Bug;
import com.google.testing.testify.risk.frontend.model.Checkin;
import com.google.testing.testify.risk.frontend.model.DataRequest;
import com.google.testing.testify.risk.frontend.model.DataSource;
import com.google.testing.testify.risk.frontend.model.DatumType;
import com.google.testing.testify.risk.frontend.model.Filter;
import com.google.testing.testify.risk.frontend.model.Signoff;
import com.google.testing.testify.risk.frontend.model.TestCase;
import com.google.testing.testify.risk.frontend.model.UploadedDatum;
import com.google.testing.testify.risk.frontend.server.service.DataService;
import com.google.testing.testify.risk.frontend.server.service.UserService;
import com.google.testing.testify.risk.frontend.server.util.ServletUtils;
import com.google.testing.testify.risk.frontend.shared.util.StringUtil;

import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;

/**
* Implementation of the DataRequestService, for tracking project requests for external
* data. This data is also exposed via the DataRequest servlet.
*
* @author chrsmith@google.com (Chris Smith)
* @author jimr@google.com (Jim Reardon)
*/
@Singleton
public class DataServiceImpl implements DataService {
  private static final Logger log = Logger.getLogger(DataServiceImpl.class.getName());
  private final PersistenceManagerFactory pmf;
  private final UserService userService;

  /**
   * Creates a new DataServiceImpl instance.
   */
  @Inject
  public DataServiceImpl(PersistenceManagerFactory pmf, UserService userService) {
    this.pmf = pmf;
    this.userService = userService;
  }

  @Override
  public boolean isSignedOff(AccElementType type, Long elementId) {
    Signoff signoff = getSignoff(type, elementId);
    return signoff == null ? false : signoff.getSignedOff();
  }

  @Override
  public void setSignedOff(long projectId, AccElementType type, long elementId,
      boolean isSignedOff) {
    ServletUtils.requireAccess(userService.hasEditAccess(projectId));
    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      Signoff signoff = getSignoff(type, elementId);
      if (signoff == null) {
        signoff = new Signoff();
        signoff.setParentProjectId(projectId);
        signoff.setElementType(type);
        signoff.setElementId(elementId);
      } else {
        if (signoff.getParentProjectId() != projectId) {
          ServletUtils.requireAccess(false);
        }
      }
      signoff.setSignedOff(isSignedOff);
      pm.makePersistent(signoff);
    } finally {
      pm.close();
    }
  }

  @Override
  @SuppressWarnings("unchecked")
  public List<Signoff> getSignoffsByType(long projectId, AccElementType type) {
    ServletUtils.requireAccess(userService.hasViewAccess(projectId));
    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      Query query = pm.newQuery(Signoff.class);
      query.declareParameters("AccElementType elementTypeParam, Long projectIdParam");
      query.setFilter("elementType == elementTypeParam && parentProjectId == projectIdParam");
      List<Signoff> results = (List<Signoff>) query.execute(type, projectId);
      return ServletUtils.makeGwtSafe(results, pm);
    } finally {
      pm.close();
    }
  }

  @SuppressWarnings("unchecked")
  private Signoff getSignoff(AccElementType type, Long elementId) {
    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      Query query = pm.newQuery(Signoff.class);
      query.declareParameters("AccElementType elementTypeParam, Long elementIdParam");
      query.setFilter("elementType == elementTypeParam && elementId == elementIdParam");
      List<Signoff> results = (List<Signoff>) query.execute(type, elementId);
      if (results.size() > 0) {
        Signoff signoff = results.get(0);
        ServletUtils.requireAccess(userService.hasViewAccess(signoff.getParentProjectId()));
        return ServletUtils.makeGwtSafe(signoff, pm);
      } else {
        return null;
      }
    } finally {
      pm.close();
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<DataSource> getDataSources() {
    boolean isInternal = userService.isInternalUser();
    PersistenceManager pm = pmf.getPersistenceManager();
    List<DataSource> results = null;
    log.info("Retrieving data sources.");
    try {
      Query query = pm.newQuery(DataSource.class);
      if (isInternal == false) {
        query.setFilter("internalOnly == false");
        log.info("Only retrieving external friendly sources, not an internal user.");
      }
      results = (List<DataSource>) query.execute();
      results = ServletUtils.makeGwtSafe(results, pm);
    } finally {
      pm.close();
    }
    log.info("Returning results: " + results.size());
    return results;
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<DataRequest> getProjectRequests(long projectId) {
    ServletUtils.requireAccess(userService.hasViewAccess(projectId));

    log.info("Getting Data Requests for project: " + Long.toString(projectId));
    PersistenceManager pm = pmf.getPersistenceManager();

    Query jdoQuery = pm.newQuery(DataRequest.class);
    jdoQuery.declareParameters("Long parentProjectParam");
    jdoQuery.setFilter("parentProjectId == parentProjectParam");

    List<DataRequest> results = null;
    try {
      List<DataRequest> returnedRequests = (List<DataRequest>) jdoQuery.execute(projectId);
      results = ServletUtils.makeGwtSafe(returnedRequests, pm);
    } finally {
      pm.close();
    }

    return results;
  }

  @Override
  public long addDataRequest(DataRequest request) {
    ServletUtils.requireAccess(userService.hasEditAccess(request.getParentProjectId()));

    log.info("Creating new Data Request for source: " + request.getDataSourceName());
    request.setDataSourceName(request.getDataSourceName().trim());

    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      pm.makePersistent(request);
    } finally {
      pm.close();
    }

    return request.getRequestId();
  }

  @Override
  public void updateDataRequest(DataRequest request) {
    if (request.getRequestId() == null) {
        throw new IllegalArgumentException(
            "Request has not been saved. Please call addDataRequest first.");
    }
    ServletUtils.requireAccess(userService.hasEditAccess(request.getParentProjectId()));

    log.info("Updating DataRequest: " + request.getRequestId().toString());
    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      pm.makePersistent(request);
    } finally {
      pm.close();
    }
  }

  @Override
  public void removeDataRequest(DataRequest request) {
    if (request.getRequestId() == null) {
      log.info("Attempting to delete unsaved DataRequest. Ignoring.");
      return;
    }

    ServletUtils.requireAccess(userService.hasEditAccess(request.getParentProjectId()));

    log.info("Removing DataRequest: " + request.getRequestId().toString());
    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      DataRequest requestToDelete = pm.getObjectById(DataRequest.class, request.getRequestId());
      pm.deletePersistent(requestToDelete);
    } finally {
      pm.close();
    }
  }

  @Override
  public List<Filter> getFilters(long projectId) {
    return getFiltersByType(projectId, null);
  }

  @SuppressWarnings("unchecked")
  private List<Filter> getFiltersByType(long projectId, DatumType filterType) {
    ServletUtils.requireAccess(userService.hasViewAccess(projectId));

    log.info("Getting Filters for project: " + Long.toString(projectId));
    PersistenceManager pm = pmf.getPersistenceManager();

    Query jdoQuery = pm.newQuery(Filter.class);
    List<Filter> jdoResults;
    try {
      if (filterType == null) {
        jdoQuery.declareParameters("Long parentProjectParam");
        jdoQuery.setFilter("parentProjectId == parentProjectParam");
        jdoResults = (List<Filter>) jdoQuery.execute(projectId);
      } else {
        jdoQuery.declareParameters("Long parentProjectParam, DatumType filterTypeParam");
        jdoQuery.setFilter(
            "parentProjectId == parentProjectParam && filterType == filterTypeParam");
        jdoResults = (List<Filter>) jdoQuery.execute(projectId, filterType);
      }
      return ServletUtils.makeGwtSafe(jdoResults, pm);
    } finally {
      pm.close();
    }
  }

  @Override
  public long addFilter(Filter filter) {
    ServletUtils.requireAccess(userService.hasEditAccess(filter.getParentProjectId()));

    log.info("Adding filter for project: " + filter.getParentProjectId());
    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      pm.makePersistent(filter);
    } finally {
      pm.close();
    }

    return filter.getId();
  }

  @Override
  public void updateFilter(Filter filter) {
    if (filter.getId() == null) {
        throw new IllegalArgumentException(
            "Filter has not been saved. Please call addFilter first.");
    }
    ServletUtils.requireAccess(userService.hasEditAccess(filter.getParentProjectId()));

    log.info("Updating filter: " + filter.getId().toString());
    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      pm.makePersistent(filter);
    } finally {
      pm.close();
    }
  }

  @Override
  public void removeFilter(Filter filter) {
    if (filter.getId() == null) {
      log.info("Attempting to delete unsaved Filter. Ignoring.");
      return;
    }

    ServletUtils.requireAccess(userService.hasEditAccess(filter.getParentProjectId()));

    log.info("Deleting filter: " + filter.getId().toString());
    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      Filter filterToDelete = pm.getObjectById(Filter.class, filter.getId());
      pm.deletePersistent(filterToDelete);
    } finally {
      pm.close();
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<Bug> getProjectBugsById(long projectId) {
    return getProjectData(Bug.class, projectId);
  }

  @SuppressWarnings("unchecked")
  @Override
  public void updateBugAssociations(long bugId, long attributeId, long componentId,
      long capabilityId) {
    updateAssociations(Bug.class, bugId, attributeId, componentId, capabilityId);
  }

  /**
   * Try to upload a new bug into the GAE datastore.  If a bug with the same Bug ID already exists,
   * it will be updated.  This is a friendly function; it will not throw if there's an error
   * adding the bug.
   */
  @Override
  public void addBug(Bug bug) {
    addBug(bug, userService.getEmail());
  }

  @SuppressWarnings("unchecked")
  @Override
  public void addBug(Bug bug, String asEmail) {
    log.info("Trying to add Bug: " + bug.getTitle() + " for project " + bug.getParentProjectId());
    ServletUtils.requireAccess(userService.hasEditAccess(bug.getParentProjectId(), asEmail));

    // Trim long fields.
    bug.setTitle(StringUtil.trimString(bug.getTitle()));
    saveOrUpdateDatum(bug);
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<Checkin> getProjectCheckinsById(long projectId) {
    return getProjectData(Checkin.class, projectId);
  }

  @Override
  public void addCheckin(Checkin checkin) {
    addCheckin(checkin, userService.getEmail());
  }

  /**
   * Try to upload a new Checkin into the GAE datastore.  If a Checkin with the same Checkin ID
   * already exists, it will be updated.
   */
  @SuppressWarnings("unchecked")
  @Override
  public void addCheckin(Checkin checkin, String asEmail) {
    log.info("Trying to add Checkin: " + checkin.getSummary());
    ServletUtils.requireAccess(userService.hasEditAccess(checkin.getParentProjectId(), asEmail));

    checkin.setSummary(StringUtil.trimString(checkin.getSummary()));
    saveOrUpdateDatum(checkin);
  }

  @SuppressWarnings("unchecked")
  @Override
  public void updateCheckinAssociations(long checkinId, long attributeId, long componentId,
      long capabilityId) {
    updateAssociations(Checkin.class, checkinId, attributeId, componentId, capabilityId);
  }

  @SuppressWarnings("unchecked")
  @Override
  public List<TestCase> getProjectTestCasesById(long projectId) {
    return getProjectData(TestCase.class, projectId);
  }

  @SuppressWarnings("unchecked")
  @Override
  public void updateTestAssociations(long testCaseId, long attributeId, long componentId,
      long capabilityId) {
    updateAssociations(TestCase.class, testCaseId, attributeId, componentId, capabilityId);
  }

  @Override
  public void addTestCase(TestCase test) {
    addTestCase(test, userService.getEmail());
  }

  /**
   * Try to upload a new bug into the GAE datastore.  If a test case with the same ID already
   * exists, it will be updated.
   */
  @SuppressWarnings("unchecked")
  @Override
  public void addTestCase(TestCase test, String asEmail) {
    log.info("Trying to add Test: " + test.getTitle());
    ServletUtils.requireAccess(userService.hasEditAccess(test.getParentProjectId(), asEmail));

    // Trim long fields.
    test.setTitle(StringUtil.trimString(test.getTitle()));
    saveOrUpdateDatum(test);
  }

  @SuppressWarnings("unchecked")
  private <T extends UploadedDatum> List<T> getProjectData(Class<T> clazz, long projectId) {
    ServletUtils.requireAccess(userService.hasViewAccess(projectId));
    log.info("Getting data for project: " + Long.toString(projectId));
    PersistenceManager pm = pmf.getPersistenceManager();

    Query jdoQuery = pm.newQuery(clazz);
    jdoQuery.declareParameters("Long parentProjectParam");
    jdoQuery.setFilter("parentProjectId == parentProjectParam");
    jdoQuery.setOrdering("externalId asc");

    List<T> projectData = null;
    try {
      List<T> results = (List<T>) jdoQuery.execute(projectId);
      projectData = ServletUtils.makeGwtSafe(results, pm);
    } finally {
      pm.close();
    }
    return projectData;
  }

  /**
   * Saves a new datum, or updates an existing datum in the database if it already exists.
   *
   * @param datum
   */
  @SuppressWarnings("unchecked")
  private <T extends UploadedDatum> void saveOrUpdateDatum(T datum) {
    PersistenceManager pm = pmf.getPersistenceManager();

    Query jdoQuery = pm.newQuery(datum.getClass());
    jdoQuery.declareParameters("Long parentProjectParam, Long externalIdParam");
    jdoQuery.setFilter("parentProjectId == parentProjectParam && externalId == externalIdParam");

    try {
      // There are two ways an existing item may exist: the same primary key, or the same
      // parent project ID and bug ID.
      T oldDatum = null;
      if (datum.getInternalId() != null) {
        // If it's the same primary key, make sure it makes sense to overwrite it.  The existing
        // bug should be non-null (we shouldn't have a pkey if it's unsaved already) and match
        // projects.
        oldDatum = (T) pm.getObjectById(datum.getClass(), datum.getInternalId());
        ServletUtils.requireAccess(oldDatum != null);
        ServletUtils.requireAccess(oldDatum.getParentProjectId() == datum.getParentProjectId());
      } else {
        // Try to load by a combination of project and external IDs.
        List<T> results = (List<T>)
            jdoQuery.execute(datum.getParentProjectId(), datum.getExternalId());
        if (results.size() > 0) {
          oldDatum = results.get(0);
        }
      }
      if (oldDatum != null) {
        datum.setInternalId(oldDatum.getInternalId());
        transferAssignments(oldDatum, datum);
      } else {
        applyFilters(datum);
      }
      pm.makePersistent(datum);
    } finally {
      pm.close();
    }
  }

  private <T extends UploadedDatum> void updateAssociations(Class<T> clazz, long internalId,
      long attributeId, long componentId,
      long capabilityId) {
    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      T datum = pm.getObjectById(clazz, internalId);
      if (datum == null) {
        log.info("No results when querying for datum ID: " + internalId);
        return;
      }
      ServletUtils.requireAccess(userService.hasEditAccess(datum.getParentProjectId()));

      boolean updated = false;
      if (attributeId >= 0) {
        datum.setTargetAttributeId(attributeId == 0 ? null : attributeId);
        updated = true;
      }
      if (componentId >= 0) {
        datum.setTargetComponentId(componentId == 0 ? null : componentId);
        updated = true;
      }
      if (capabilityId >= 0) {
        datum.setTargetCapabilityId(capabilityId == 0 ? null : capabilityId);
        updated = true;
      }

      if (updated) {
        pm.makePersistent(datum);
      }
    } finally {
      pm.close();
    }
  }

  /**
   * Iff the old datum (from the database) has an assigned attribute, component, or capability
   * AND the new datum doesn't have an assignment, we copy the old assignment over.
   *
   * @param oldDatum the old item.
   * @param newDatum the new item; it will have the a/c/c set from the old item.
   */
  private void transferAssignments(UploadedDatum oldDatum, UploadedDatum newDatum) {
    if (positive(oldDatum.getTargetAttributeId()) && !positive(newDatum.getTargetAttributeId())) {
      newDatum.setTargetAttributeId(oldDatum.getTargetAttributeId());
    }

    if (positive(oldDatum.getTargetComponentId()) && !positive(newDatum.getTargetComponentId())) {
      newDatum.setTargetComponentId(oldDatum.getTargetComponentId());
    }

    if (positive(oldDatum.getTargetCapabilityId()) && !positive(newDatum.getTargetCapabilityId())) {
      newDatum.setTargetCapabilityId(oldDatum.getTargetCapabilityId());
    }
  }

  private void applyFilters(UploadedDatum item) {
    // TODO(jimr): This is a poor way to filter items... it's a stop-gap solution until the recently
    // announced Full Text Search is available for the AppEngine datastore.
    List<Filter> filters = getFiltersByType(item.getParentProjectId(), item.getDatumType());
    for (Filter filter : filters) {
      filter.apply(item);
    }
  }

  private boolean positive(Long value) {
    return value != null && value > 0;
  }
}
TOP

Related Classes of com.google.testing.testify.risk.frontend.server.service.impl.DataServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.