/src/main/java/com/atlassian/labs/jira/workflow/HipChatPostFunctionFactory.java
Java | 358 lines | 294 code | 58 blank | 6 comment | 9 complexity | 28d9cbc6eb3a13ec9fda698f7503e177 MD5 | raw file
- package com.atlassian.labs.jira.workflow;
- import com.atlassian.fugue.Either;
- import com.atlassian.hipchat.plugins.api.client.ClientError;
- import com.atlassian.hipchat.plugins.api.client.HipChatClient;
- import com.atlassian.hipchat.plugins.api.client.Room;
- import com.atlassian.hipchat.plugins.api.config.HipChatConfigurationManager;
- import com.atlassian.jira.bc.issue.search.SearchService;
- import com.atlassian.jira.plugin.workflow.AbstractWorkflowPluginFactory;
- import com.atlassian.jira.plugin.workflow.WorkflowPluginFunctionFactory;
- import com.atlassian.jira.security.JiraAuthenticationContext;
- import com.google.common.base.Function;
- import com.google.common.base.Joiner;
- import com.google.common.base.Splitter;
- import com.google.common.base.Strings;
- import com.google.common.collect.ImmutableMap;
- import com.google.common.collect.Iterables;
- import com.google.common.collect.Lists;
- import com.google.common.collect.Maps;
- import com.opensymphony.workflow.loader.AbstractDescriptor;
- import com.opensymphony.workflow.loader.FunctionDescriptor;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.List;
- import java.util.Map;
- import static com.google.common.collect.Lists.newArrayList;
- /*
- This is the factory class responsible for dealing with the UI for the post-function.
- This is typically where you put default values into the velocity context and where you store user input.
- */
- public class HipChatPostFunctionFactory extends AbstractWorkflowPluginFactory implements WorkflowPluginFunctionFactory {
- public static final String ROOMS_TO_NOTIFY_CSV_IDS_PARAM = "roomsToNotifyCsvIds";
- public static final String JQL_FILTER_PARAM = "jql";
- public static final String NOTIFY_CLIENTS_PARAM = "notifyClients";
- public static final String MESSAGE_FILTER_PARAM = "message";
- private final HipChatClient hipChatClient;
- private final HipChatConfigurationManager configurationManager;
- private final SearchService searchService;
- private final JiraAuthenticationContext authenticationContext;
- public HipChatPostFunctionFactory(HipChatClient hipChatClient, HipChatConfigurationManager configurationManager,
- SearchService searchService, JiraAuthenticationContext authenticationContext) {
- this.hipChatClient = hipChatClient;
- this.configurationManager = configurationManager;
- this.searchService = searchService;
- this.authenticationContext = authenticationContext;
- }
- @Override
- protected void getVelocityParamsForInput(Map<String, Object> velocityParams) {
- EditDto editDto;
- if (configurationManager.getApiToken().isDefined())
- {
- editDto = getRooms().fold(
- new Function<ClientError, EditDto>()
- {
- @Override
- public EditDto apply(ClientError error)
- {
- return new EditDto(true, true);
- }
- },
- new Function<List<Room>, EditDto>()
- {
- @Override
- public EditDto apply(List<Room> rooms)
- {
- return new EditDto(toRoomDtos(rooms));
- }
- }
- );
- }
- else
- {
- editDto = new EditDto(false, false);
- }
- velocityParams.put("dto", editDto);
- }
- private List<RoomDto> toRoomDtos(List<Room> rooms)
- {
- return Lists.transform(rooms, new Function<Room, RoomDto>()
- {
- @Override
- public RoomDto apply(Room from)
- {
- return new RoomDto(String.valueOf(from.getId()), from.getName());
- }
- });
- }
- @Override
- protected void getVelocityParamsForEdit(Map<String, Object> velocityParams, AbstractDescriptor descriptor) {
- final EditDto editDto;
- if (configurationManager.getApiToken().isDefined())
- {
- FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
- final String jql = Strings.nullToEmpty((String) functionDescriptor.getArgs().get(JQL_FILTER_PARAM));
- final boolean notifyClients = Boolean.parseBoolean((String) functionDescriptor.getArgs().get(NOTIFY_CLIENTS_PARAM));
- final Iterable<String> roomsToNotifyIds = Splitter.on(",").split(Strings.nullToEmpty((String) functionDescriptor.getArgs().get(ROOMS_TO_NOTIFY_CSV_IDS_PARAM)));
- final String message = Strings.nullToEmpty((String) functionDescriptor.getArgs().get(MESSAGE_FILTER_PARAM));
- editDto = getRooms().fold(
- new Function<ClientError, EditDto>()
- {
- @Override
- public EditDto apply(ClientError error)
- {
- return new EditDto(true, true);
- }
- },
- new Function<List<Room>, EditDto>()
- {
- @Override
- public EditDto apply(List<Room> rooms)
- {
- return new EditDto(newArrayList(roomsToNotifyIds), jql, notifyClients, toRoomDtos(rooms), isValidQuery(jql), message);
- }
- }
- );
- }
- else
- {
- editDto = new EditDto(false, false);
- }
- velocityParams.put("dto", editDto);
- }
- private Either<ClientError, List<Room>> getRooms()
- {
- return hipChatClient.rooms().list().claim();
- }
- @Override
- protected void getVelocityParamsForView(Map<String, Object> velocityParams, AbstractDescriptor descriptor) {
- final ViewDto viewDto;
- if (configurationManager.getApiToken().isDefined()) {
- FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
- String jql = Strings.nullToEmpty((String) functionDescriptor.getArgs().get(JQL_FILTER_PARAM));
- boolean notifyClients = Boolean.parseBoolean((String) functionDescriptor.getArgs().get(NOTIFY_CLIENTS_PARAM));
- final Either<ClientError,List<Room>> rooms = getRooms();
- if (rooms.isRight())
- {
- // seems to be counterintuitive to load the full list, but its actually more efficient than a request per room starting from 2 rooms
- final ImmutableMap<Long, Room> roomsById = Maps.uniqueIndex(rooms.right().get(), new Function<Room, Long>()
- {
- @Override
- public Long apply(Room from)
- {
- return from.getId();
- }
- });
- Iterable<String> roomsToNotifyIds = Splitter.on(",").omitEmptyStrings().split(Strings.nullToEmpty((String) functionDescriptor.getArgs().get(ROOMS_TO_NOTIFY_CSV_IDS_PARAM)));
- viewDto = new ViewDto(newArrayList(Iterables.transform(roomsToNotifyIds, new Function<String, RoomDto>()
- {
- @Override
- public RoomDto apply(String from)
- {
- Long roomId = Long.valueOf(from);
- return new RoomDto(from, roomsById.containsKey(roomId) ? roomsById.get(roomId).getName() : null);
- }
- })), jql, notifyClients, isValidQuery(jql));
- }
- else
- {
- viewDto = new ViewDto(true, true);
- }
- } else {
- viewDto = new ViewDto(false, false);
- }
- velocityParams.put("dto", viewDto);
- }
- public ImmutableMap<String, String> getDescriptorParams(Map<String, Object> formParams) {
- String[] roomsIds = (String[]) formParams.get("roomsToNotify");
- String roomsToNotifyCsvIds = roomsIds != null ? Joiner.on(",").join(roomsIds) : "";
- String jql = extractSingleParam(formParams, "jql");
- String message = extractSingleParam(formParams, "message");
- final String notifyClients;
- if ( formParams.containsKey(NOTIFY_CLIENTS_PARAM) ) {
- notifyClients = extractSingleParam(formParams, NOTIFY_CLIENTS_PARAM);
- } else {
- notifyClients = "false";
- }
- return ImmutableMap.of(ROOMS_TO_NOTIFY_CSV_IDS_PARAM, roomsToNotifyCsvIds, JQL_FILTER_PARAM, jql, NOTIFY_CLIENTS_PARAM, notifyClients, MESSAGE_FILTER_PARAM, message);
- }
- private boolean isValidQuery(String jql) {
- if (Strings.isNullOrEmpty(jql)) {
- return true;
- }
- // the current user (admin) probably won't be the user who will run the query, but it's sufficient to just test if query is valid
- SearchService.ParseResult parseResult = searchService.parseQuery(authenticationContext.getLoggedInUser(), jql);
- return parseResult.isValid();
- }
- public static class ViewDto {
- private final String jql;
- private final Collection<RoomDto> roomsToNotify;
- private final boolean notifyClients;
- private final boolean apiTokenConfigured;
- private final boolean responseError;
- private final boolean jqlValid;
- public ViewDto(Collection<RoomDto> roomsToNotify, String jql, boolean notifyClients, boolean jqlValid) {
- this.roomsToNotify = roomsToNotify;
- this.jql = jql;
- this.notifyClients = notifyClients;
- this.apiTokenConfigured = true;
- this.responseError = false;
- this.jqlValid = jqlValid;
- }
- public ViewDto(boolean apiTokenConfigured, boolean responseError) {
- this.roomsToNotify = Collections.emptyList();
- this.jql = null;
- this.notifyClients = false;
- this.apiTokenConfigured = apiTokenConfigured;
- this.responseError = responseError;
- this.jqlValid = false;
- }
- public Collection<RoomDto> getRoomsToNotify() {
- return roomsToNotify;
- }
- public String getJql() {
- return jql;
- }
- public boolean isNotifyClients() {
- return notifyClients;
- }
- public boolean isApiTokenConfigured() {
- return apiTokenConfigured;
- }
- public boolean isResponseError() {
- return responseError;
- }
- public boolean isJqlValid() {
- return jqlValid;
- }
- }
- public static class EditDto {
- private final Collection<String> roomsToNotifyIds;
- private final String jql;
- private final boolean notifyClients;
- private final Collection<RoomDto> rooms;
- private final boolean apiTokenConfigured;
- private final boolean responseError;
- private final boolean jqlValid;
- private final String message;
- public EditDto(Collection<String> roomsToNotifyIds, String jql, boolean notifyClients, Collection<RoomDto> rooms, boolean jqlValid, String message) {
- this.roomsToNotifyIds = roomsToNotifyIds;
- this.jql = jql;
- this.notifyClients = notifyClients;
- this.rooms = rooms;
- this.apiTokenConfigured = true;
- this.responseError = false;
- this.jqlValid = jqlValid;
- this.message = message;
- }
- public EditDto(boolean apiTokenConfigured, boolean responseError) {
- this.roomsToNotifyIds = Collections.emptyList();
- this.rooms = Collections.emptyList();
- this.jql = null;
- this.notifyClients = false;
- this.apiTokenConfigured = apiTokenConfigured;
- this.responseError = responseError;
- this.jqlValid = false;
- this.message = null;
- }
- public EditDto(Collection<RoomDto> rooms) {
- this(Collections.<String>emptyList(), null, false, rooms, true, null);
- }
- public Collection<String> getRoomsToNotifyIds() {
- return roomsToNotifyIds;
- }
- public String getJql() {
- return jql;
- }
- public boolean isNotifyClients() {
- return notifyClients;
- }
- public Collection<RoomDto> getRooms() {
- return rooms;
- }
- public boolean isApiTokenConfigured() {
- return apiTokenConfigured;
- }
- public boolean isResponseError() {
- return responseError;
- }
- public boolean isJqlValid() {
- return jqlValid;
- }
- public String getMessage()
- {
- return message;
- }
- }
- public static class RoomDto {
- private final String id;
- private final String name;
- public RoomDto(String id, String name) {
- this.id = id;
- this.name = name;
- }
- public String getId() {
- return id;
- }
- public String getName() {
- return name;
- }
- }
- }