/* * Copyright 2013 Hewlett-Packard Development Company, L.P * * 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.hp.alm.ali.idea.tasks; import com.hp.alm.ali.idea.model.Entity; import com.hp.alm.ali.idea.entity.EntityQuery; import com.hp.alm.ali.idea.entity.EntityRef; import com.hp.alm.ali.idea.rest.RestService; import com.hp.alm.ali.idea.services.EntityService; import com.hp.alm.ali.idea.services.FavoritesService; import com.intellij.notification.Notification; import com.intellij.notification.NotificationListener; import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.tasks.CustomTaskState; import com.intellij.tasks.Task; import com.intellij.tasks.TaskRepository; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Tag; import org.jetbrains.annotations.Nullable; import javax.swing.event.HyperlinkEvent; import java.util.LinkedList; import java.util.List; @Tag("HP_ALM") final public class HpAlmRepository extends TaskRepository implements Comparable<HpAlmRepository> { private Project project; /** * Id has two uses. First of all it is forced by the following code from TaskRepositoriesConfigurable: * * TaskRepository clone = repository.clone(); * assert clone.equals(repository) : repository.getClass().getName(); * * This assertion prevents us from defining equals for identity only. On the other hand when equals is defined as * true for all other (HP ALM) repositories, removal operation is not working properly when multiple * (HP ALM) repositories are present - the first occurrence is removed instead of the one that was selected. * I wonder if this was worth the trouble, but auxiliary id fixes the problem.... * * More importantly id defines order and allows to ignore duplicated repositories when making queries to HP ALM system... */ private long id; private TaskConfig defect = new TaskConfig("defect"); private TaskConfig requirement = new TaskConfig("requirement"); public HpAlmRepository() { super(new HpAlmRepositoryType()); } public HpAlmRepository(String url, long id) { super(new HpAlmRepositoryType()); this.id = id; setUrl(url); } public void setId(long id) { this.id = id; } @Tag("defect") public TaskConfig getDefect() { return defect; } public void setDefect(TaskConfig defect) { this.defect = defect; } @Tag("requirement") public TaskConfig getRequirement() { return requirement; } public void setRequirement(TaskConfig requirement) { this.requirement = requirement; } @Attribute("id") public long getId() { return id; } public String getPresentableName() { return "HP ALM"; } public boolean isConfigured() { return true; } public Task[] getIssues(String query, int max, long since) throws Exception { if(!_assignProject()) { return new Task[0]; } List<HpAlmTask> list = new LinkedList<HpAlmTask>(); loadTasks(query, defect, "defect", list); loadTasks(query, requirement, "requirement", list); return list.toArray(new Task[list.size()]); } @Override public void setPreferredOpenTaskState(@Nullable CustomTaskState customTaskState) { } @Nullable @Override public CustomTaskState getPreferredOpenTaskState() { return null; } @Override public void setPreferredCloseTaskState(@Nullable CustomTaskState customTaskState) { } @Nullable @Override public CustomTaskState getPreferredCloseTaskState() { return null; } private void loadTasks(String query, TaskConfig config, String entityType, List<HpAlmTask> tasks) { if(config.isEnabled()) { EntityQuery filter = new EntityQuery(entityType); filter.addColumn(HpAlmTask.getDescriptionField(entityType), 1); filter.addColumn("name", 1); if(config.isCustomSelected()) { filter.copyFrom(config.getCustomFilter()); } else { EntityQuery stored = project.getComponent(FavoritesService.class).getStoredQuery(entityType, config.getStoredQuery()); if(stored != null) { filter.copyFrom(stored); } else { Notifications.Bus.notify(new Notification("HP ALM Integration", "Cannot retrieve task information from HP ALM:<br/> '"+config.getStoredQuery()+"' query not found", "<p><a href=\"\">Configure task integration ...</a></p>", NotificationType.ERROR, new NotificationListener() { public void hyperlinkUpdate(Notification notification, HyperlinkEvent event) { notification.expire(); ShowSettingsUtil.getInstance().showSettingsDialog(project, "Servers"); } } ), project); return; } } filter.setValue("name", "'*"+query+"*'"); // TODO: what if name is already specified in the filter? EntityService entityService = project.getComponent(EntityService.class); for(Entity entity: entityService.query(filter)) { tasks.add(new HpAlmTask(project, entity)); } try { int id = Integer.parseInt(query); Entity entity = project.getComponent(EntityService.class).getEntity(new EntityRef(entityType, id)); tasks.add(new HpAlmTask(project, entity)); } catch(Exception e) { // not a number or entity doesn't exist } } } public Task findTask(String taskName) throws Exception { if(!_assignProject()) { return null; } Entity entity = project.getComponent(EntityService.class).getEntity(new EntityRef(taskName)); return new HpAlmTask(project, entity); } public String extractId(String taskName) { return taskName; } public HpAlmRepository clone() { HpAlmRepository ret = new HpAlmRepository(getUrl(), id); ret.requirement = requirement; ret.defect = defect; return ret; } public boolean equals(Object o) { if(o == this) { return true; } else if(!(o instanceof HpAlmRepository)) { return false; } else if(((HpAlmRepository)o).id != id) { return false; } else if(getUrl() == null) { return ((HpAlmRepository) o).getUrl() == null; } else { return getUrl().equals(((HpAlmRepository) o).getUrl()); } } public int hashCode() { return getUrl() == null? 0: getUrl().hashCode() + 31 * new Long(id).hashCode(); } synchronized boolean _assignProject() throws InterruptedException { if(project == null) { for(Project project: ProjectManager.getInstance().getOpenProjects()) { if(project.getName().equals(getUrl())) { this.project = project; break; } } } return project != null && project.getComponent(RestService.class).getServerType().isConnected(); } public int compareTo(HpAlmRepository other) { if(id < other.id) { return -1; } else if(id > other.id) { return 1; } else { return 0; } } }