blob: a594f85541501beee55caee25c4a38365936406a [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.entity;
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.Text;
import com.google.appengine.api.users.User;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.reflect.TypeToken;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.Index;
import lombok.Data;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.googlecode.objectify.ObjectifyService.ofy;
@com.googlecode.objectify.annotation.Entity(name = "TestAcknowledgment")
@Cache
@Data
/** Entity describing a test failure acknowledgment. */
public class TestAcknowledgmentEntity implements DashboardEntity {
protected static final Logger logger =
Logger.getLogger(TestAcknowledgmentEntity.class.getName());
public static final String KIND = "TestAcknowledgment";
public static final String KEY = "key";
public static final String TEST_KEY = "testKey";
public static final String TEST_NAME = "testName";
public static final String USER_OBJ = "userObj";
public static final String CREATED = "created";
public static final String BRANCHES = "branches";
public static final String DEVICES = "devices";
public static final String TEST_CASE_NAMES = "testCaseNames";
public static final String NOTE = "note";
@Ignore private final Key key;
@Ignore public final Key test;
@Ignore public final User userObj;
@Id private Long id;
private com.googlecode.objectify.Key testKey;
private Set<String> branches;
private Set<String> devices;
private Set<String> testCaseNames;
private String note;
private String user;
@Index private final long created;
/**
* Create a AcknowledgmentEntity object.
*
* @param key The key of the AcknowledgmentEntity in the database.
* @param created The timestamp when the entity was created (in microseconds).
* @param test The key of the test.
* @param userObj The user who created or last modified the entity.
* @param branches The list of branch names for which the acknowledgment applies (or null if
* all).
* @param devices The list of device build flavors for which the acknowledgment applies (or null
* if all).
* @param testCaseNames The list of test case names known to fail (or null if all).
* @param note A text blob with details about the failure (or null if all).
*/
private TestAcknowledgmentEntity(
Key key,
long created,
Key test,
User userObj,
List<String> branches,
List<String> devices,
List<String> testCaseNames,
Text note) {
this.test = test;
this.userObj = userObj;
if (branches != null) this.branches = new HashSet(branches);
else this.branches = new HashSet<>();
if (devices != null) this.devices = new HashSet(devices);
else this.devices = new HashSet<>();
if (testCaseNames != null) this.testCaseNames = new HashSet(testCaseNames);
else this.testCaseNames = new HashSet<>();
if (note != null) this.note = note.getValue();
else this.note = null;
this.key = key;
this.created = created;
}
/**
* Create a AcknowledgmentEntity object.
*
* @param test The key of the test.
* @param userObj The user who created or last modified the entity.
* @param branches The list of branch names for which the acknowledgment applies (or null if
* all).
* @param devices The list of device build flavors for which the acknowledgment applies (or null
* if all).
* @param testCaseNames The list of test case names known to fail (or null if all).
* @param note A text blob with details about the failure (or null if all).
*/
public TestAcknowledgmentEntity(
Key test,
User userObj,
List<String> branches,
List<String> devices,
List<String> testCaseNames,
Text note) {
this(null, -1, test, userObj, branches, devices, testCaseNames, note);
}
/** Saving function for the instance of this class */
@Override
public com.googlecode.objectify.Key<TestAcknowledgmentEntity> save() {
return ofy().save().entity(this).now();
}
public Entity toEntity() {
Entity ackEntity;
if (this.key == null) ackEntity = new Entity(KIND);
else ackEntity = new Entity(key);
ackEntity.setProperty(TEST_KEY, this.test);
ackEntity.setProperty(USER_OBJ, this.userObj);
long created = this.created;
if (created < 0) created = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
ackEntity.setProperty(CREATED, created);
if (this.branches != null && this.branches.size() > 0)
ackEntity.setUnindexedProperty(BRANCHES, new ArrayList<>(this.branches));
if (this.devices != null && this.devices.size() > 0)
ackEntity.setUnindexedProperty(DEVICES, new ArrayList<>(this.devices));
if (this.testCaseNames != null && this.testCaseNames.size() > 0)
ackEntity.setUnindexedProperty(TEST_CASE_NAMES, new ArrayList<>(this.testCaseNames));
if (this.note != null) ackEntity.setUnindexedProperty(NOTE, new Text(this.note));
return ackEntity;
}
/**
* Convert an Entity object to a TestAcknowledgmentEntity.
*
* @param e The entity to process.
* @return TestEntity object with the properties from e processed, or null if incompatible.
*/
@SuppressWarnings("unchecked")
public static TestAcknowledgmentEntity fromEntity(Entity e) {
if (!e.getKind().equals(KIND)
|| !e.hasProperty(TEST_KEY)
|| !e.hasProperty(USER_OBJ)
|| !e.hasProperty(CREATED)) {
logger.log(
Level.WARNING, "Missing attributes in acknowledgment entity: " + e.toString());
return null;
}
try {
Key test = (Key) e.getProperty(TEST_KEY);
User user = (User) e.getProperty(USER_OBJ);
long created = (long) e.getProperty(CREATED);
List<String> branches;
if (e.hasProperty(BRANCHES)) branches = (List<String>) e.getProperty(BRANCHES);
else branches = null;
List<String> devices;
if (e.hasProperty(DEVICES)) devices = (List<String>) e.getProperty(DEVICES);
else devices = null;
List<String> testCaseNames;
if (e.hasProperty(TEST_CASE_NAMES))
testCaseNames = (List<String>) e.getProperty(TEST_CASE_NAMES);
else testCaseNames = null;
Text note = null;
if (e.hasProperty(NOTE)) note = (Text) e.getProperty(NOTE);
return new TestAcknowledgmentEntity(
e.getKey(), created, test, user, branches, devices, testCaseNames, note);
} catch (ClassCastException exception) {
logger.log(Level.WARNING, "Corrupted data in entity: " + e.getKey());
return null;
}
}
/**
* Convert a JSON object to a TestAcknowledgmentEntity.
*
* @param user The user requesting the conversion.
* @param json The json object to convert.
* @return TestAcknowledgmentEntity with the data from the json object.
*/
public static TestAcknowledgmentEntity fromJson(User user, JsonObject json) {
try {
if (!json.has(TEST_NAME)) return null;
String testName = json.get(TEST_NAME).getAsString();
Key testKey = KeyFactory.createKey(TestEntity.KIND, testName);
List<String> branches = null;
Type listType = new TypeToken<List<String>>() {}.getType();
if (json.has(BRANCHES)) {
branches = new Gson().fromJson(json.get(BRANCHES), listType);
}
List<String> devices = null;
if (json.has(DEVICES)) {
devices = new Gson().fromJson(json.get(DEVICES), listType);
}
List<String> testCaseNames = null;
if (json.has(TEST_CASE_NAMES)) {
testCaseNames = new Gson().fromJson(json.get(TEST_CASE_NAMES), listType);
}
Text note = null;
if (json.has(NOTE)) {
note = new Text(json.get(NOTE).getAsString());
}
Key key = null;
if (json.has(KEY)) {
key = KeyFactory.stringToKey(json.get(KEY).getAsString());
}
return new TestAcknowledgmentEntity(
key, -1l, testKey, user, branches, devices, testCaseNames, note);
} catch (ClassCastException | IllegalStateException e) {
return null;
}
}
/**
* Convert the entity to a json object.
*
* @return The entity serialized in JSON format.
*/
public JsonObject toJson() {
JsonObject json = new JsonObject();
json.add(KEY, new JsonPrimitive(KeyFactory.keyToString(this.key)));
json.add(TEST_NAME, new JsonPrimitive(this.test.getName()));
json.add(USER_OBJ, new JsonPrimitive(this.userObj.getEmail()));
json.add(CREATED, new JsonPrimitive(this.created));
List<JsonElement> branches = new ArrayList<>();
if (this.branches != null) {
for (String branch : this.branches) {
branches.add(new JsonPrimitive(branch));
}
}
json.add(BRANCHES, new Gson().toJsonTree(branches));
List<JsonElement> devices = new ArrayList<>();
if (this.devices != null) {
for (String device : this.devices) {
devices.add(new JsonPrimitive(device));
}
}
json.add(DEVICES, new Gson().toJsonTree(devices));
List<JsonElement> testCaseNames = new ArrayList<>();
if (this.testCaseNames != null) {
for (String testCaseName : this.testCaseNames) {
testCaseNames.add(new JsonPrimitive(testCaseName));
}
}
json.add(TEST_CASE_NAMES, new Gson().toJsonTree(testCaseNames));
String note = "";
if (this.note != null) note = this.note;
json.add(NOTE, new JsonPrimitive(note));
return json;
}
}