blob: 73a7287edf4e520b2b5a98a7afcb24b04a5f8298 [file] [log] [blame]
/*
* Copyright (c) 2016 Google Inc. All Rights Reserved.
*
* 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.android.vts.servlet;
import com.android.vts.entity.TestEntity;
import com.android.vts.entity.TestStatusEntity;
import com.android.vts.entity.UserFavoriteEntity;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PropertyProjection;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.stream.Collectors;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import static com.googlecode.objectify.ObjectifyService.ofy;
/** Represents the servlet that is invoked on loading the first page of dashboard. */
public class DashboardMainServlet extends BaseServlet {
private static final String DASHBOARD_MAIN_JSP = "WEB-INF/jsp/dashboard_main.jsp";
private static final String NO_TESTS_ERROR = "No test results available.";
@Override
public PageType getNavParentType() {
return PageType.TOT;
}
@Override
public List<Page> getBreadcrumbLinks(HttpServletRequest request) {
return null;
}
/** Helper class for displaying test entries on the main dashboard. */
public class TestDisplay implements Comparable<TestDisplay> {
private final Key testKey;
private final int passCount;
private final int failCount;
private boolean muteNotifications;
private boolean isFavorite;
/**
* Test display constructor.
*
* @param testKey The key of the test.
* @param passCount The number of tests passing.
* @param failCount The number of tests failing.
* @param muteNotifications The flag for user notification in case of test failure.
* @param isFavorite The flag for showing favorite mark on All Tests Tab page.
*/
public TestDisplay(
Key testKey,
int passCount,
int failCount,
boolean muteNotifications,
boolean isFavorite) {
this.testKey = testKey;
this.passCount = passCount;
this.failCount = failCount;
this.muteNotifications = muteNotifications;
this.isFavorite = isFavorite;
}
/**
* Get the key of the test.
*
* @return The key of the test.
*/
public String getName() {
return this.testKey.getName();
}
/**
* Get the number of passing test cases.
*
* @return The number of passing test cases.
*/
public int getPassCount() {
return this.passCount;
}
/**
* Get the number of failing test cases.
*
* @return The number of failing test cases.
*/
public int getFailCount() {
return this.failCount;
}
/**
* Get the notification mute status.
*
* @return True if the subscriber has muted notifications, false otherwise.
*/
public boolean getMuteNotifications() {
return this.muteNotifications;
}
/** Set the notification mute status. */
public void setMuteNotifications(boolean muteNotifications) {
this.muteNotifications = muteNotifications;
}
/**
* Get the favorate status.
*
* @return True if an user set favorate for the test, false otherwise.
*/
public boolean getIsFavorite() {
return this.isFavorite;
}
/** Set the favorite status. */
public void setIsFavorite(boolean isFavorite) {
this.isFavorite = isFavorite;
}
@Override
public int compareTo(TestDisplay test) {
return this.testKey.getName().compareTo(test.getName());
}
}
@Override
public void doGetHandler(HttpServletRequest request, HttpServletResponse response)
throws IOException {
UserService userService = UserServiceFactory.getUserService();
User currentUser = userService.getCurrentUser();
RequestDispatcher dispatcher = null;
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
HttpSession session = request.getSession(true);
PageType referTo = PageType.TREE;
if (session.getAttribute("treeDefault") != null) {
boolean treeDefault = (boolean) session.getAttribute("treeDefault");
if (!treeDefault) {
referTo = PageType.TABLE;
}
}
List<TestDisplay> displayedTests = new ArrayList<>();
List<Key> unprocessedTestKeys = new ArrayList<>();
Map<Key, TestDisplay> testMap = new HashMap<>(); // map from table key to TestDisplay
Map<String, String> subscriptionMap = new HashMap<>();
boolean showAll = request.getParameter("showAll") != null;
String error = null;
List<String> allTestNames = TestEntity.getAllTestNames();
List<Key> favoriteKeyList = new ArrayList<Key>();
Filter userFilter =
new FilterPredicate(UserFavoriteEntity.USER, FilterOperator.EQUAL, currentUser);
Query filterQuery = new Query(UserFavoriteEntity.KIND).setFilter(userFilter);
Iterable<Entity> favoriteIter = datastore.prepare(filterQuery).asIterable();
favoriteIter.forEach(
fe -> {
Key testKey = UserFavoriteEntity.fromEntity(fe).testKey;
favoriteKeyList.add(testKey);
subscriptionMap.put(testKey.getName(), KeyFactory.keyToString(fe.getKey()));
});
Query query =
new Query(TestStatusEntity.KIND)
.addProjection(
new PropertyProjection(TestStatusEntity.PASS_COUNT, Long.class))
.addProjection(
new PropertyProjection(TestStatusEntity.FAIL_COUNT, Long.class));
for (Entity status : datastore.prepare(query).asIterable()) {
TestStatusEntity statusEntity = TestStatusEntity.fromEntity(status);
if (statusEntity == null) continue;
Key testKey = KeyFactory.createKey(TestEntity.KIND, statusEntity.getTestName());
boolean isFavorite = favoriteKeyList.contains(testKey);
TestDisplay display = new TestDisplay(testKey, -1, -1, false, isFavorite);
if (!unprocessedTestKeys.contains(testKey)) {
display =
new TestDisplay(
testKey,
statusEntity.getPassCount(),
statusEntity.getFailCount(),
false,
isFavorite);
}
testMap.put(testKey, display);
}
if (testMap.size() == 0) {
error = NO_TESTS_ERROR;
}
if (showAll) {
for (Key testKey : testMap.keySet()) {
displayedTests.add(testMap.get(testKey));
}
} else {
if (testMap.size() > 0) {
for (Entity favoriteEntity : favoriteIter) {
UserFavoriteEntity favorite = UserFavoriteEntity.fromEntity(favoriteEntity);
Key testKey = favorite.testKey;
if (!testMap.containsKey(testKey)) {
continue;
}
TestDisplay display = testMap.get(testKey);
display.setMuteNotifications(favorite.muteNotifications);
displayedTests.add(display);
}
}
}
displayedTests.sort(Comparator.naturalOrder());
response.setStatus(HttpServletResponse.SC_OK);
request.setAttribute("allTestsJson", new Gson().toJson(allTestNames));
request.setAttribute("subscriptionMapJson", new Gson().toJson(subscriptionMap));
request.setAttribute("testNames", displayedTests);
request.setAttribute("showAll", showAll);
request.setAttribute("error", error);
request.setAttribute("resultsUrl", referTo.defaultUrl);
dispatcher = request.getRequestDispatcher(DASHBOARD_MAIN_JSP);
try {
dispatcher.forward(request, response);
} catch (ServletException e) {
logger.log(Level.SEVERE, "Servlet Excpetion caught : ", e);
}
}
}