/*************************GO-LICENSE-START*********************************
* Copyright 2014 ThoughtWorks, Inc.
*
* 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.
*************************GO-LICENSE-END***********************************/
package com.thoughtworks.go.presentation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.thoughtworks.go.config.AdminsConfig;
import com.thoughtworks.go.config.AgentConfig;
import com.thoughtworks.go.config.Agents;
import com.thoughtworks.go.config.CaseInsensitiveString;
import com.thoughtworks.go.config.EnvironmentConfig;
import com.thoughtworks.go.config.Resource;
import com.thoughtworks.go.config.Role;
import com.thoughtworks.go.config.UserRoleMatcher;
import com.thoughtworks.go.domain.config.Admin;
import com.thoughtworks.go.util.comparator.AlphaAsciiComparator;
/**
* @understands What values are selected on multiple agents
*/
public class TriStateSelection implements Comparable<TriStateSelection> {
private String value;
private Action action;
private boolean enabled;
private AlphaAsciiComparator comparator = new AlphaAsciiComparator();
public TriStateSelection(String value, Action action) {
this(value, action, true);
}
public TriStateSelection(String value, String action) {
this(value, Action.valueOf(action));
}
public TriStateSelection(String value, Action action, boolean enabled) {
this.value = value;
this.action = action;
this.enabled = enabled;
}
public String getValue() {
return value;
}
public Action getAction() {
return action;
}
public boolean isEnabled() {
return enabled;
}
public static List<TriStateSelection> forAgentsResources(Set<Resource> resources, Agents agents) {
return convert(resources, agents, new Assigner<Resource, AgentConfig>() {
public boolean shouldAssociate(AgentConfig agent, Resource resource) {
return agent.getResources().contains(resource);
}
public String identifier(Resource resource) {
return resource.getName();
}
public boolean shouldEnable(AgentConfig agent, Resource resource) {
return true;
}
});
}
public static List<TriStateSelection> forRoles(Set<Role> allRoles, List<String> users) {
return convert(allRoles, users, new Assigner<Role, String>() {
public boolean shouldAssociate(String user, Role role) {
return role.hasMember(new CaseInsensitiveString(user));
}
public String identifier(Role role) {
return CaseInsensitiveString.str(role.getName());
}
public boolean shouldEnable(String user, Role role) {
return true;
}
});
}
public static TriStateSelection forSystemAdmin(final AdminsConfig adminsConfig, final Set<Role> allRoles, final UserRoleMatcher userRoleMatcher, List<String> users) {
return convert(new HashSet<>(Arrays.asList(Admin.GO_SYSTEM_ADMIN)), users, new Assigner<String, String>() {
public boolean shouldAssociate(String userName, String ignore) {
return adminsConfig.hasUser(new CaseInsensitiveString(userName), userRoleMatcher);
}
public String identifier(String ignore) {
return Admin.GO_SYSTEM_ADMIN;
}
public boolean shouldEnable(String userName, String ignore) {
List<Role> roles = new ArrayList<>();
for (Role role : allRoles) {
if (role.hasMember(new CaseInsensitiveString(userName))) {
roles.add(role);
}
}
return ! adminsConfig.isAdminRole(roles);
}
}).get(0);
}
public static List<TriStateSelection> forAgentsEnvironmens(Set<EnvironmentConfig> environments, Agents agents) {
return convert(environments, agents, new Assigner<EnvironmentConfig, AgentConfig>() {
public boolean shouldAssociate(AgentConfig agent, EnvironmentConfig environment) {
return environment.hasAgent(agent.getUuid());
}
public String identifier(EnvironmentConfig environment) {
return CaseInsensitiveString.str(environment.name());
}
public boolean shouldEnable(AgentConfig agent, EnvironmentConfig environment) {
return true;
}
});
}
static <T,V> List<TriStateSelection> convert(Set<T> assignables, List<V> assignees, Assigner<T,V> associator) {
ArrayList<TriStateSelection> selections = new ArrayList<>();
for (T t : assignables) {
int count = 0;
boolean enabled = true;
for (V assignee : assignees) {
if (associator.shouldAssociate(assignee, t)) {
count++;
}
enabled = enabled && associator.shouldEnable(assignee, t);
}
Action action = Action.remove;
if (count > 0) {
if (count == assignees.size()) {
action = Action.add;
} else {
action = Action.nochange;
}
}
selections.add(new TriStateSelection(associator.identifier(t), action, enabled));
}
Collections.sort(selections);
return selections;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TriStateSelection that = (TriStateSelection) o;
if (action != null ? !action.equals(that.action) : that.action != null) {
return false;
}
if (value != null ? !value.equals(that.value) : that.value != null) {
return false;
}
return enabled == that.enabled;
}
@Override
public int hashCode() {
int result = value != null ? value.hashCode() : 0;
result = 31 * result + (action != null ? action.hashCode() : 0);
return result;
}
@Override public String toString() {
return "TriStateSelection{" +
"value='" + value + '\'' +
", action='" + action + '\'' +
", enabled='" + enabled + '\'' +
'}';
}
public int compareTo(TriStateSelection other) {
return comparator.compare(this.value,other.value);
}
static interface Assigner<T,V> {
boolean shouldAssociate(V v, T t);
String identifier(T t);
boolean shouldEnable(V v, T t);
}
public static enum Action {
add, remove, nochange
}
}