blob: 81bc73559371fcc066015760859241e3a4e567bb [file] [log] [blame]
// 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.common.collect.Sets;
import com.google.gerrit.common.Container;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.server.git.meta.AbstractVersionedMetaData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/** Task Configuration file living in git */
public class TaskConfig extends AbstractVersionedMetaData {
public enum NamesFactoryType {
CHANGE,
STATIC;
public static NamesFactoryType getNamesFactoryType(String str) {
for (NamesFactoryType type : NamesFactoryType.values()) {
if (type.name().equalsIgnoreCase(str)) return type;
}
return null;
}
}
protected class SubSection extends Container {
public TaskConfig config;
public final SubSectionKey subSection;
public SubSection(SubSectionKey s) {
this.config = TaskConfig.this;
this.subSection = s;
}
}
public class TaskBase extends SubSection {
public String applicable;
public Map<String, String> exported;
public String fail;
public String failHint;
public String inProgress;
public String pass;
public String preloadTask;
public Map<String, String> properties;
public String readyHint;
public List<String> subTasks;
public List<String> subTasksExternals;
public List<String> subTasksFactories;
public List<String> subTasksFiles;
public boolean isVisible;
public boolean isTrusted;
public TaskBase(SubSectionKey s, boolean isVisible, boolean isTrusted) {
super(s);
this.isVisible = isVisible;
this.isTrusted = isTrusted;
applicable = getString(s, KEY_APPLICABLE, null);
exported = getProperties(s, KEY_EXPORT_PREFIX);
fail = getString(s, KEY_FAIL, null);
failHint = getString(s, KEY_FAIL_HINT, null);
inProgress = getString(s, KEY_IN_PROGRESS, null);
pass = getString(s, KEY_PASS, null);
preloadTask = getString(s, KEY_PRELOAD_TASK, null);
properties = getProperties(s, KEY_PROPERTIES_PREFIX);
readyHint = getString(s, KEY_READY_HINT, null);
subTasks = getStringList(s, KEY_SUBTASK);
subTasksExternals = getStringList(s, KEY_SUBTASKS_EXTERNAL);
subTasksFactories = getStringList(s, KEY_SUBTASKS_FACTORY);
subTasksFiles = getStringList(s, KEY_SUBTASKS_FILE);
}
protected TaskBase(TaskBase base) {
this(base.subSection);
Copier.deepCopyDeclaredFields(TaskBase.class, base, this, false, copyOnlyReferencesFor());
}
protected TaskBase(SubSectionKey s) {
super(s);
}
}
public class Task extends TaskBase {
public final TaskKey key;
public Task(SubSectionKey s, boolean isVisible, boolean isTrusted) {
super(s, isVisible, isTrusted);
key = TaskKey.create(s);
}
public Task(Task task) {
super(task);
// Despite being copied in Copier.deepCopyDeclaredFields this
// is needed to avoid the final variable initialization warning.
this.key = task.key;
Copier.deepCopyDeclaredFields(Task.class, task, this, false, copyOnlyReferencesFor());
}
public Task(TasksFactory tasks, String name) {
super(tasks);
key = TaskKey.create(tasks.subSection, name);
}
public Task(SubSectionKey s) {
super(s);
key = TaskKey.create(s);
}
protected Map<String, String> getAllProperties() {
Map<String, String> all = new HashMap<>(properties);
all.putAll(exported);
return all;
}
public String name() {
return key.task();
}
public FileKey file() {
return key.subSection().file();
}
public TaskKey key() {
return key;
}
}
public class TasksFactory extends TaskBase {
public String namesFactory;
public TasksFactory(SubSectionKey s, boolean isVisible, boolean isTrusted) {
super(s, isVisible, isTrusted);
namesFactory = getString(s, KEY_NAMES_FACTORY, null);
}
}
public class NamesFactory extends SubSection {
public String changes;
public List<String> names;
public String type;
public NamesFactory(SubSectionKey s) {
super(s);
changes = getString(s, KEY_CHANGES, null);
names = getStringList(s, KEY_NAME);
type = getString(s, KEY_TYPE, null);
}
public NamesFactory(NamesFactory n) {
super(n.subSection);
Copier.deepCopyDeclaredFields(NamesFactory.class, n, this, false, copyOnlyReferencesFor());
}
}
public class External extends SubSection {
public String name;
public String file;
public String user;
public External(SubSectionKey s) {
super(s);
name = s.subSection();
file = getString(s, KEY_FILE, null);
user = getString(s, KEY_USER, null);
}
}
public static final String SEP = "\0";
protected static final String SECTION_EXTERNAL = "external";
protected static final String SECTION_NAMES_FACTORY = "names-factory";
protected static final String SECTION_ROOT = "root";
protected static final String SECTION_TASK = "task";
protected static final String SECTION_TASKS_FACTORY = "tasks-factory";
protected static final String KEY_APPLICABLE = "applicable";
protected static final String KEY_CHANGES = "changes";
protected static final String KEY_EXPORT_PREFIX = "export-";
protected static final String KEY_FAIL = "fail";
protected static final String KEY_FAIL_HINT = "fail-hint";
protected static final String KEY_FILE = "file";
protected static final String KEY_IN_PROGRESS = "in-progress";
protected static final String KEY_NAME = "name";
protected static final String KEY_NAMES_FACTORY = "names-factory";
protected static final String KEY_PASS = "pass";
protected static final String KEY_PRELOAD_TASK = "preload-task";
protected static final String KEY_PROPERTIES_PREFIX = "set-";
protected static final String KEY_READY_HINT = "ready-hint";
protected static final String KEY_SUBTASK = "subtask";
protected static final String KEY_SUBTASKS_EXTERNAL = "subtasks-external";
protected static final String KEY_SUBTASKS_FACTORY = "subtasks-factory";
protected static final String KEY_SUBTASKS_FILE = "subtasks-file";
protected static final String KEY_TYPE = "type";
protected static final String KEY_USER = "user";
protected final FileKey file;
public boolean isVisible;
public boolean isTrusted;
public TaskConfig(FileKey file, boolean isVisible, boolean isTrusted) {
this(file.branch(), file, isVisible, isTrusted);
}
public TaskConfig(
BranchNameKey masqueraded, FileKey file, boolean isVisible, boolean isTrusted) {
super(masqueraded, file.file());
this.file = file;
this.isVisible = isVisible;
this.isTrusted = isTrusted;
}
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(subSectionKey(type, task), isVisible, isTrusted));
}
return tasks;
}
public List<External> getExternals() {
List<External> externals = new ArrayList<>();
// No need to get an external with no name (what would we call it?)
for (String external : cfg.getSubsections(SECTION_EXTERNAL)) {
externals.add(getExternal(external));
}
return externals;
}
protected Optional<Task> getOptionalTask(String name) {
SubSectionKey subSection = subSectionKey(SECTION_TASK, name);
return getNames(subSection).isEmpty()
? Optional.empty()
: Optional.of(new Task(subSection, isVisible, isTrusted));
}
public TasksFactory getTasksFactory(String name) {
return new TasksFactory(subSectionKey(SECTION_TASKS_FACTORY, name), isVisible, isTrusted);
}
public NamesFactory getNamesFactory(String name) {
return new NamesFactory(subSectionKey(SECTION_NAMES_FACTORY, name));
}
public External getExternal(String name) {
return getExternal(subSectionKey(SECTION_EXTERNAL, name));
}
protected External getExternal(SubSectionKey s) {
return new External(s);
}
protected Map<String, String> getProperties(SubSectionKey s, String prefix) {
Map<String, String> valueByName = new HashMap<>();
for (Map.Entry<String, String> e :
getStringByName(s, getMatchingNames(s, prefix + ".+")).entrySet()) {
String name = e.getKey();
valueByName.put(name.substring(prefix.length()), e.getValue());
}
return Collections.unmodifiableMap(valueByName);
}
protected Map<String, String> getStringByName(SubSectionKey s, Iterable<String> names) {
Map<String, String> valueByName = new HashMap<>();
for (String name : names) {
valueByName.put(name, getString(s, name));
}
return valueByName;
}
protected Set<String> getMatchingNames(SubSectionKey s, String match) {
Set<String> matched = new HashSet<>();
for (String name : getNames(s)) {
if (name.matches(match)) {
matched.add(name);
}
}
return matched;
}
protected Set<String> getNames(SubSectionKey s) {
return cfg.getNames(s.section(), s.subSection());
}
protected String getString(SubSectionKey s, String key, String def) {
String v = getString(s, key);
return v != null ? v : def;
}
protected String getString(SubSectionKey s, String key) {
return cfg.getString(s.section(), s.subSection(), key);
}
protected List<String> getStringList(SubSectionKey s, String key) {
return Collections.unmodifiableList(
Arrays.asList(cfg.getStringList(s.section(), s.subSection(), key)));
}
protected SubSectionKey subSectionKey(String section, String subSection) {
return SubSectionKey.create(file, section, subSection);
}
protected Collection<Class<?>> copyOnlyReferencesFor() {
return Sets.newHashSet(TaskKey.class, SubSectionKey.class);
}
}