Refactor TaskDefinitions
Refactor how they are named, created, and looked up.
Change-Id: Ie83011dc61ddd46ec49191edd7cb0e5958454c5d
diff --git a/src/main/java/com/google/gerrit/common/Container.java b/src/main/java/com/google/gerrit/common/Container.java
new file mode 100644
index 0000000..62b672a
--- /dev/null
+++ b/src/main/java/com/google/gerrit/common/Container.java
@@ -0,0 +1,58 @@
+// Copyright (C) 2016 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.google.gerrit.common;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/* A data container, all fields considered in equals and hash */
+public class Container {
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ try {
+ for (Field field : getClass().getDeclaredFields()) {
+ field.setAccessible(true);
+ if (!Objects.deepEquals(field.get(this), field.get(o))) {
+ return false;
+ }
+ }
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ throw new RuntimeException();
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ List values = new ArrayList();
+ try {
+ for (Field field : getClass().getDeclaredFields()) {
+ field.setAccessible(true);
+ values.add(field.get(this));
+ }
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ }
+ return Objects.hash(values);
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
index ed6743f..298b1d7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
@@ -23,6 +23,7 @@
import com.google.gerrit.server.query.change.ChangeQueryProcessor.ChangeAttributeFactory;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
+import com.googlesource.gerrit.plugins.task.TaskConfig.Task;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -84,9 +85,9 @@
throws OrmException, QueryParseException {
TaskPluginAttribute a = new TaskPluginAttribute();
try {
- LinkedList<TaskDefinition> path = new LinkedList<>();
- for (TaskDefinition def : getRootTaskDefinitions()) {
- addApplicableTasks(a.roots, c, path, def);
+ LinkedList<Task> path = new LinkedList<>();
+ for (Task task : getRootTasks()) {
+ addApplicableTasks(a.roots, c, path, task);
}
} catch (ConfigInvalidException | IOException e) {
a.roots.add(invalid());
@@ -98,27 +99,8 @@
return a;
}
- protected List<TaskAttribute> getSubTasks(
- ChangeData c, LinkedList<TaskDefinition> path, TaskDefinition parent)
- throws OrmException, QueryParseException {
- List<TaskAttribute> subTasks = new ArrayList<>();
- for (String name : parent.subTasks) {
- try {
- TaskDefinition def = getTaskDefinition(parent, name);
- addApplicableTasks(subTasks, c, path, def);
- } catch (ConfigInvalidException | IOException e) {
- subTasks.add(invalid());
- }
- }
-
- if (subTasks.isEmpty()) {
- return null;
- }
- return subTasks;
- }
-
protected void addApplicableTasks(
- List<TaskAttribute> tasks, ChangeData c, LinkedList<TaskDefinition> path, TaskDefinition def)
+ List<TaskAttribute> tasks, ChangeData c, LinkedList<Task> path, Task def)
throws OrmException, QueryParseException {
if (path.contains(def)) { // looping definition
tasks.add(invalid());
@@ -130,7 +112,7 @@
}
protected void addApplicableTasksNoLoopCheck(
- List<TaskAttribute> tasks, ChangeData c, LinkedList<TaskDefinition> path, TaskDefinition def)
+ List<TaskAttribute> tasks, ChangeData c, LinkedList<Task> path, Task def)
throws OrmException {
try {
if (match(c, def.applicable)) {
@@ -150,6 +132,19 @@
}
}
+ protected List<TaskAttribute> getSubTasks(ChangeData c, LinkedList<Task> path, Task parent)
+ throws OrmException, QueryParseException {
+ List<TaskAttribute> subTasks = new ArrayList<>();
+ for (Task task : getSubTasks(parent)) {
+ addApplicableTasks(subTasks, c, path, task);
+ }
+
+ if (subTasks.isEmpty()) {
+ return null;
+ }
+ return subTasks;
+ }
+
protected static TaskAttribute invalid() {
// For security reasons, do not expose the task name without knowing
// the visibility which is derived from its applicability.
@@ -158,26 +153,28 @@
return a;
}
- protected List<TaskDefinition> getRootTaskDefinitions()
- throws ConfigInvalidException, IOException {
- return taskFactory.getRootConfig().getRootTaskDefinitions();
+ protected List<Task> getRootTasks() throws ConfigInvalidException, IOException {
+ return taskFactory.getRootConfig().getRootTasks();
}
- protected TaskDefinition getTaskDefinition(TaskDefinition parent, String name)
- throws ConfigInvalidException, IOException {
- return taskFactory.getTaskConfig(parent.branch, parent.fileName).getTaskDefinition(name);
+ protected List<Task> getSubTasks(Task parent) {
+ List<Task> tasks = new ArrayList<>();
+ for (String name : parent.subTasks) {
+ tasks.add(parent.config.getTask(name));
+ }
+ return tasks;
}
- protected Status getStatus(ChangeData c, TaskDefinition def, TaskAttribute a)
+ protected Status getStatus(ChangeData c, Task task, TaskAttribute a)
throws OrmException, QueryParseException {
- if (def.pass == null && a.subTasks == null) {
+ if (task.pass == null && a.subTasks == null) {
// A leaf without a PASS criteria is likely a missconfiguration.
// Either someone forgot to add subtasks, or they forgot to add
// the pass criteria.
return Status.INVALID;
}
- if (def.fail != null && match(c, def.fail)) {
+ if (task.fail != null && match(c, task.fail)) {
// A FAIL definition is meant to be a hard blocking criteria
// (like a CodeReview -2). Thus, if hard blocked, it is
// irrelevant what the subtask states, or the pass criteria are.
@@ -202,7 +199,7 @@
return Status.WAITING;
}
- if (def.pass != null && !match(c, def.pass)) {
+ if (task.pass != null && !match(c, task.pass)) {
// Non-leaf tasks with no PASS criteria are supported in order
// to support "grouping tasks" (tasks with no function aside from
// organizing tasks). A task without a PASS criteria, cannot ever
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
index 818b0fa..3334449 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
@@ -14,6 +14,7 @@
package com.googlesource.gerrit.plugins.task;
+import com.google.gerrit.common.Container;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.server.git.meta.AbstractVersionedMetaData;
import java.util.ArrayList;
@@ -22,6 +23,34 @@
/** Task Configuration file living in git */
public class TaskConfig extends AbstractVersionedMetaData {
+ protected class Section extends Container {
+ public TaskConfig config;
+
+ public Section() {
+ this.config = TaskConfig.this;
+ }
+ }
+
+ public class Task extends Section {
+ public String applicable;
+ public String fail;
+ public String inProgress;
+ public String name;
+ public String pass;
+ public String readyHint;
+ public List<String> subTasks;
+
+ public Task(SubSection s) {
+ applicable = getString(s, KEY_APPLICABLE, null);
+ fail = getString(s, KEY_FAIL, null);
+ inProgress = getString(s, KEY_IN_PROGRESS, null);
+ name = getString(s, KEY_NAME, s.subSection);
+ pass = getString(s, KEY_PASS, null);
+ readyHint = getString(s, KEY_READY_HINT, null);
+ subTasks = getStringList(s, KEY_SUBTASK);
+ }
+ }
+
protected static final String SECTION_ROOT = "root";
protected static final String SECTION_TASK = "task";
protected static final String KEY_APPLICABLE = "applicable";
@@ -36,49 +65,41 @@
super(branch, fileName);
}
- public List<TaskDefinition> getRootTaskDefinitions() {
- List<TaskDefinition> roots = new ArrayList<TaskDefinition>();
- // No need to get a root with no name (what would we call it?)
- for (String root : cfg.getSubsections(SECTION_ROOT)) {
- roots.add(getRootDefinition(root));
+ public List<Task> getRootTasks() {
+ return getTasks(SECTION_ROOT);
+ }
+
+ public List<Task> getTasks() {
+ return getTasks(SECTION_TASK);
+ }
+
+ protected List<Task> getTasks(String type) {
+ List<Task> tasks = new ArrayList<>();
+ // No need to get a task with no name (what would we call it?)
+ for (String task : cfg.getSubsections(type)) {
+ tasks.add(new Task(new SubSection(type, task)));
}
- return roots;
+ return tasks;
}
- protected TaskDefinition getRootDefinition(String name) {
- return getTaskDefinition(new Section(SECTION_ROOT, name));
+ public Task getTask(String name) {
+ return new Task(new SubSection(SECTION_TASK, name));
}
- public TaskDefinition getTaskDefinition(String name) {
- return getTaskDefinition(new Section(SECTION_TASK, name));
- }
-
- protected TaskDefinition getTaskDefinition(Section s) {
- TaskDefinition task = new TaskDefinition(branch, fileName);
- task.applicable = getString(s, KEY_APPLICABLE, null);
- task.fail = getString(s, KEY_FAIL, null);
- task.inProgress = getString(s, KEY_IN_PROGRESS, null);
- task.name = getString(s, KEY_NAME, s.subSection);
- task.pass = getString(s, KEY_PASS, null);
- task.readyHint = getString(s, KEY_READY_HINT, null);
- task.subTasks = getStringList(s, KEY_SUBTASK);
- return task;
- }
-
- protected String getString(Section s, String key, String def) {
+ protected String getString(SubSection s, String key, String def) {
String v = cfg.getString(s.section, s.subSection, key);
return v != null ? v : def;
}
- protected List<String> getStringList(Section s, String key) {
+ protected List<String> getStringList(SubSection s, String key) {
return Arrays.asList(cfg.getStringList(s.section, s.subSection, key));
}
- protected static class Section {
+ protected static class SubSection {
public final String section;
public final String subSection;
- protected Section(String section, String subSection) {
+ protected SubSection(String section, String subSection) {
this.section = section;
this.subSection = subSection;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskDefinition.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskDefinition.java
deleted file mode 100644
index 491d88b..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskDefinition.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2016 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.googlesource.gerrit.plugins.task;
-
-import com.google.gerrit.reviewdb.client.Branch;
-import java.util.List;
-import java.util.Objects;
-
-public class TaskDefinition {
- public Branch.NameKey branch;
- public String fileName;
-
- public String applicable;
- public String fail;
- public String inProgress;
- public String name;
- public String readyHint;
- public String pass;
- public List<String> subTasks;
-
- public TaskDefinition(Branch.NameKey branch, String fileName) {
- this.branch = branch;
- this.fileName = fileName;
- }
-
- @Override
- public boolean equals(Object o) {
- if (o == this) {
- return true;
- }
- if (o == null || !(o instanceof TaskDefinition)) {
- return false;
- }
- TaskDefinition t = (TaskDefinition) o;
- return Objects.equals(branch, t.branch)
- && Objects.equals(fileName, t.fileName)
- && Objects.equals(applicable, t.applicable)
- && Objects.equals(fail, t.fail)
- && Objects.equals(inProgress, t.inProgress)
- && Objects.equals(name, t.name)
- && Objects.equals(readyHint, t.readyHint)
- && Objects.equals(pass, t.pass)
- && Objects.equals(subTasks, t.subTasks);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(
- branch, fileName, applicable, fail, inProgress, name, pass, readyHint, subTasks);
- }
-}