diff --git a/.gitignore b/.gitignore index b2032c4..1c9ed72 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ # Eclipse and Maven Files # -.classpath -.settings -.project -.checkstyle -target -bin +/.classpath +/.settings +/.project +/.checkstyle +/target +/bin +/.pmd +/.fbExcludeFilterFile +/.pmdruleset.xml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e009e1e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: java +jdk: + - oraclejdk8 +script: mvn verify +install: true +sudo: false +cache: + directories: + - $HOME/.m2 diff --git a/README.md b/README.md index fdb76e5..7460abd 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,19 @@ jira-worklog-query-plugin ========================= -Worklog Query Plugin is a JIRA plugin enabling its users to run worklog queries and apply parameters on these queries through RESTful services. The plugin handles queries according to user roles, therefore, these queries can only be run on worklogs the user has appropriate permissions to access. Various filtering parameters can also be set up to narrow down the search results to a certain interval of time, user, user group and/or project. The result of the worklog query is served in JSON format. +Worklog Query Plugin is a JIRA plugin enabling its users to run worklog +queries and apply parameters on these queries through RESTful services. The +plugin handles queries according to user roles, therefore, these queries can +only be run on worklogs the user has appropriate permissions to access. +Various filtering parameters can also be set up to narrow down the search +results to a certain interval of time, user, user group and/or project. The +result of the worklog query is served in JSON format. -The documentation of the plugin can be found [here](https://github.com/everit-org/jira-worklog-query-plugin/wiki). +The documentation of the plugin can be found [here][1]. + +The version history can be found on the [Atlassian Marketplace][2]. [![Analytics](https://ga-beacon.appspot.com/UA-15041869-4/everit-org/jira-worklog-query-plugin)](https://github.com/igrigorik/ga-beacon) + +[1]: http://www.everit.org/jira-worklog-query-plugin +[2]: https://marketplace.atlassian.com/plugins/org.everit.jira.worklog.query.plugin.core/versions diff --git a/core/pom.xml b/core/pom.xml index 4e83fc1..aaf9589 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -1,26 +1,23 @@ + @@ -28,7 +25,7 @@ org.everit.jira.worklog.query.plugin - 1.2.1-SNAPSHOT + 1.3.4 org.everit.jira.worklog.query.plugin.parent @@ -57,7 +54,39 @@ + + com.atlassian.maven.plugins + maven-jira-plugin + ${maven.jira.plugin.version} + false + + + generate-obr-artifact + package + + generate-obr-artifact + + + + + + + org.everit.jira + jira-querydsl-support + + + + <_manifest>${project.build.outputdirectory}/META-INF/MANIFEST.MF + + + + + + src/main/resources + true + + @@ -73,30 +102,16 @@ 1.5.8 provided - - com.atlassian.usercompatibility - usercompatibility-jira - 0.18 - provided - - - com.atlassian.crowd - embedded-crowd-api - 2.2.8 - provided - - - com.atlassian.ofbiz - entityengine - 1.0.3 - provided - com.atlassian.jira - atlassian-jira + jira-core ${jira.version} provided + + jta + jta + jndi jndi @@ -109,6 +124,12 @@ 1.0 provided + + org.everit.jira + jira-querydsl-support + 1.0.1 + provided + diff --git a/core/src/main/java/org/everit/jira/worklog/query/plugin/core/DateTimeConverterUtil.java b/core/src/main/java/org/everit/jira/worklog/query/plugin/core/DateTimeConverterUtil.java index 3462e0e..9f7f8a3 100644 --- a/core/src/main/java/org/everit/jira/worklog/query/plugin/core/DateTimeConverterUtil.java +++ b/core/src/main/java/org/everit/jira/worklog/query/plugin/core/DateTimeConverterUtil.java @@ -1,26 +1,22 @@ -package org.everit.jira.worklog.query.plugin.core; - -/* - * Copyright (c) 2013, Everit Kft. - * - * All rights reserved. +/** + * This file is part of org.everit.jira.worklog.query.plugin.core. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * org.everit.jira.worklog.query.plugin.core is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * org.everit.jira.worklog.query.plugin.core is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * You should have received a copy of the GNU Lesser General Public License + * along with org.everit.jira.worklog.query.plugin.core. If not, see . */ +package org.everit.jira.worklog.query.plugin.core; +import java.sql.Timestamp; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -93,6 +89,7 @@ public static Calendar setCalendarHourMinSec(final Calendar originalCalendar, final int hourOfDay, final int minute, final int second) { Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.MILLISECOND, 0); calendar.set( originalCalendar.get(Calendar.YEAR), originalCalendar.get(Calendar.MONTH), @@ -119,6 +116,20 @@ public static String stringDateToISO8601FormatString(final String dateString) return DateTimeConverterUtil.dateToString(date); } + /** + * Format a timestamp to valid ISO-8601 format String date. + * + * @param timestamp + * The timestamp. + * @return The formated String date. + * @throws ParseException + * If cannot parse the String to Date. + */ + public static String stringDateToISO8601FormatString(final Timestamp timestamp) { + Date date = new Date(timestamp.getTime()); + return DateTimeConverterUtil.dateToString(date); + } + /** * Private constructor. */ diff --git a/core/src/main/java/org/everit/jira/worklog/query/plugin/core/IssueBeanWithTimespent.java b/core/src/main/java/org/everit/jira/worklog/query/plugin/core/IssueBeanWithTimespent.java new file mode 100644 index 0000000..cdb6615 --- /dev/null +++ b/core/src/main/java/org/everit/jira/worklog/query/plugin/core/IssueBeanWithTimespent.java @@ -0,0 +1,42 @@ +/** + * This file is part of org.everit.jira.worklog.query.plugin.core. + * + * org.everit.jira.worklog.query.plugin.core is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * org.everit.jira.worklog.query.plugin.core is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with org.everit.jira.worklog.query.plugin.core. If not, see . + */ +package org.everit.jira.worklog.query.plugin.core; + +import java.net.URI; +import java.net.URISyntaxException; + +import javax.xml.bind.annotation.XmlElement; + +import com.atlassian.jira.rest.v2.issue.IssueBean; + +/** + * IssueBeanWithTimespent extends the original IssueBean class with spent time value. + */ +public class IssueBeanWithTimespent extends IssueBean { + @XmlElement + private Long timespent = 0L; + + public IssueBeanWithTimespent(final Long id, final String key, final String selfUri, + final Long timespent) throws URISyntaxException { + super(id, key, new URI(selfUri)); + this.timespent = timespent; + } + + public Long getTimeSpent() { + return timespent; + } +} diff --git a/core/src/main/java/org/everit/jira/worklog/query/plugin/core/SearchResultsBeanWithTimespent.java b/core/src/main/java/org/everit/jira/worklog/query/plugin/core/SearchResultsBeanWithTimespent.java new file mode 100644 index 0000000..429bcb4 --- /dev/null +++ b/core/src/main/java/org/everit/jira/worklog/query/plugin/core/SearchResultsBeanWithTimespent.java @@ -0,0 +1,68 @@ +/** + * This file is part of org.everit.jira.worklog.query.plugin.core. + * + * org.everit.jira.worklog.query.plugin.core is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * org.everit.jira.worklog.query.plugin.core is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with org.everit.jira.worklog.query.plugin.core. If not, see . + */ +package org.everit.jira.worklog.query.plugin.core; + +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import com.atlassian.jira.rest.v2.search.SearchResultsBean; + +/** + * SearchResultsBeanWithTimespent extends the original SearchResultsBean class with issues + * timespent. + */ +@XmlRootElement +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +public class SearchResultsBeanWithTimespent extends SearchResultsBean { + + @XmlElement + private List issues; + + /** + * SearchResultsBeanWithTimespent constructor with fields. + * + * @param startAt + * Start the result list from. + * @param maxResults + * Max number of results. + * @param total + * Total number of found result. + * @param issues + * List of the found issues. + */ + public SearchResultsBeanWithTimespent(final Integer startAt, final Integer maxResults, + final Integer total, final List issues) { + this.startAt = startAt; + this.maxResults = maxResults; + this.total = total; + setIssues(issues); + } + + @SuppressWarnings("unused") + public List getIssues() { + return issues; + } + + public void setIssues(final List issues) { + this.issues = issues; + } + +} diff --git a/core/src/main/java/org/everit/jira/worklog/query/plugin/core/WorklogQueryResource.java b/core/src/main/java/org/everit/jira/worklog/query/plugin/core/WorklogQueryResource.java index 6382727..48b0a40 100644 --- a/core/src/main/java/org/everit/jira/worklog/query/plugin/core/WorklogQueryResource.java +++ b/core/src/main/java/org/everit/jira/worklog/query/plugin/core/WorklogQueryResource.java @@ -1,45 +1,32 @@ -package org.everit.jira.worklog.query.plugin.core; - -/* - * Copyright (c) 2013, Everit Kft. - * - * All rights reserved. +/** + * This file is part of org.everit.jira.worklog.query.plugin.core. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * org.everit.jira.worklog.query.plugin.core is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * org.everit.jira.worklog.query.plugin.core is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * You should have received a copy of the GNU Lesser General Public License + * along with org.everit.jira.worklog.query.plugin.core. If not, see . */ +package org.everit.jira.worklog.query.plugin.core; -import java.net.URI; import java.net.URISyntaxException; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Timestamp; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.TreeSet; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; @@ -48,10 +35,12 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.everit.jira.querydsl.support.QuerydslSupport; +import org.everit.jira.querydsl.support.ri.QuerydslSupportImpl; +import org.everit.jira.worklog.query.plugin.query.FindWorklogsByIssuesQuery; +import org.everit.jira.worklog.query.plugin.query.FindWorklogsQuery; +import org.everit.jira.worklog.query.plugin.query.JsonWorklog; import org.ofbiz.core.entity.GenericEntityException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,7 +52,6 @@ import com.atlassian.jira.config.properties.APKeys; import com.atlassian.jira.exception.DataAccessException; import com.atlassian.jira.issue.Issue; -import com.atlassian.jira.issue.IssueManager; import com.atlassian.jira.issue.fields.Field; import com.atlassian.jira.issue.fields.FieldException; import com.atlassian.jira.issue.fields.NavigableField; @@ -76,20 +64,18 @@ import com.atlassian.jira.issue.search.SearchException; import com.atlassian.jira.issue.search.SearchResults; import com.atlassian.jira.jql.parser.JqlParseException; -import com.atlassian.jira.ofbiz.DefaultOfBizConnectionFactory; import com.atlassian.jira.project.Project; import com.atlassian.jira.rest.api.util.StringList; import com.atlassian.jira.rest.v2.issue.IncludedFields; import com.atlassian.jira.rest.v2.issue.IssueBean; import com.atlassian.jira.rest.v2.issue.RESTException; -import com.atlassian.jira.rest.v2.search.SearchResultsBean; import com.atlassian.jira.security.JiraAuthenticationContext; import com.atlassian.jira.security.Permissions; -import com.atlassian.jira.usercompatibility.UserCompatibilityHelper; +import com.atlassian.jira.user.ApplicationUser; +import com.atlassian.jira.user.ApplicationUsers; import com.atlassian.jira.util.collect.CollectionBuilder; import com.atlassian.jira.util.json.JSONArray; import com.atlassian.jira.util.json.JSONException; -import com.atlassian.jira.util.json.JSONObject; import com.atlassian.jira.web.bean.PagerFilter; /** @@ -101,38 +87,6 @@ @Path("/find") public class WorklogQueryResource { - private class IssueBeanWithTimespent extends IssueBean { - @XmlElement - private Long timespent = 0L; - - public IssueBeanWithTimespent(final Long id, final String key, final URI selfUri, - final Long timespent) - { - super(id, key, selfUri); - this.timespent = timespent; - } - - public Long getTimeSpent() { - return timespent; - } - } - - @XmlRootElement - @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) - private class SearchResultsBeanWithTimespent extends SearchResultsBean { - public List issues; - - public SearchResultsBeanWithTimespent(final Integer startAt, final Integer maxResults, - final Integer total, - final List issues) - { - this.startAt = startAt; - this.maxResults = maxResults; - this.total = total; - this.issues = issues; - } - } - private static final int DEFAULT_MAXRESULT_PARAM = 25; private static final int DEFAULT_STARTAT_PARAM = 0; @@ -156,22 +110,19 @@ public SearchResultsBeanWithTimespent(final Integer startAt, final Integer maxRe */ private static final Logger LOGGER = LoggerFactory.getLogger(WorklogQueryResource.class); - private void addFields(final Issue issue, final IssueBean bean) - { + private QuerydslSupport querydslSupport; + + private void addFields(final Issue issue, final IssueBean bean) { // iterate over all the visible layout items from the field layout for this issue and attempt to // add them // to the result - final User loggedInUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(); final FieldLayout layout = ComponentAccessor.getFieldLayoutManager().getFieldLayout(issue); final List fieldLayoutItems = layout.getVisibleLayoutItems( - loggedInUser, issue.getProjectObject(), - CollectionBuilder.list(issue.getIssueTypeObject().getId())); - for (final FieldLayoutItem fieldLayoutItem : fieldLayoutItems) - { + issue.getProjectObject(), CollectionBuilder.list(issue.getIssueTypeObject().getId())); + for (final FieldLayoutItem fieldLayoutItem : fieldLayoutItems) { final OrderableField field = fieldLayoutItem.getOrderableField(); final FieldJsonRepresentation fieldValue = getFieldValue(fieldLayoutItem, issue); - if ((fieldValue != null) && (fieldValue.getStandardData() != null)) - { + if ((fieldValue != null) && (fieldValue.getStandardData() != null)) { bean.addField(field, fieldValue, false); } } @@ -181,35 +132,41 @@ private void addFields(final Issue issue, final IssueBean bean) // This is a bit crap because "getAvailableNavigableFields" doesn't take the issue into account. // All it means is the field is not hidden in at least one project the user has BROWSE // permission on. - try - { + try { + ApplicationUser loggedInUser = ComponentAccessor.getJiraAuthenticationContext().getUser(); final Set fields = ComponentAccessor.getFieldManager() - .getAvailableNavigableFields(loggedInUser); - for (NavigableField field : fields) - { - if (!bean.hasField(field.getId())) - { - if (!(field instanceof OrderableField) || (field instanceof ProjectSystemField)) - { - if (field instanceof RestAwareField) - { + .getAvailableNavigableFields(ApplicationUsers.toDirectoryUser(loggedInUser)); + for (NavigableField field : fields) { + if (!bean.hasField(field.getId())) { + if (!(field instanceof OrderableField) || (field instanceof ProjectSystemField)) { + if (field instanceof RestAwareField) { addRestAwareField(issue, bean, field, (RestAwareField) field); } } } } - } catch (FieldException e) - { + } catch (FieldException e) { // ignored...display as much as we can. } } + private void addFieldsToIssueBeans(final List fields, + final Map issueIdIssue, final List issueBeans) { + IncludedFields includedFields = IncludedFields.includeNavigableByDefault(fields); + boolean isEmptyField = StringList.joinLists(fields) + .asList().contains("emptyFieldValue"); + for (IssueBeanWithTimespent issueBean : issueBeans) { + issueBean.fieldsToInclude(includedFields); + if (!isEmptyField) { + addFields(issueIdIssue.get(Long.valueOf(issueBean.getId())), issueBean); + } + } + } + private void addRestAwareField(final Issue issue, final IssueBean bean, final Field field, - final RestAwareField restAware) - { + final RestAwareField restAware) { FieldJsonRepresentation fieldJsonFromIssue = restAware.getJsonFromIssue(issue, false, null); - if ((fieldJsonFromIssue != null) && (fieldJsonFromIssue.getStandardData() != null)) - { + if ((fieldJsonFromIssue != null) && (fieldJsonFromIssue.getStandardData() != null)) { bean.addField(field, fieldJsonFromIssue, false); } } @@ -263,8 +220,8 @@ private void checkRequiredFindWorklogsByIssuesParameter(final String startDate, private Response checkRequiredFindWorklogsParameter(final String startDate, final String user, final String group) { if (isStringEmpty(startDate)) { - return Response.status(Response.Status.BAD_REQUEST). - entity("The 'startDate' parameter is missing!").build(); + return Response.status(Response.Status.BAD_REQUEST) + .entity("The 'startDate' parameter is missing!").build(); } if ((isStringEmpty(user)) && (isStringEmpty(group))) { return Response.status(Response.Status.BAD_REQUEST) @@ -278,6 +235,14 @@ private Response checkRequiredFindWorklogsParameter(final String startDate, fina return null; } + private Map collectIssueIds(final List issues) { + Map result = new HashMap(); + for (Issue issue : issues) { + result.put(issue.getId(), issue); + } + return result; + } + /** * Convert the endDate String to Calendar. * @@ -327,10 +292,10 @@ private Calendar convertStartDate(final String startDateString) throws ParseExce * @throws GenericEntityException * If the GenericDelegator throw a GenericEntityException. */ - private List createProjects(final String projectString, final User user) { + private List createProjects(final String projectString, final ApplicationUser user) { Collection projects = ComponentAccessor.getPermissionManager() - .getProjectObjects(Permissions.BROWSE, user); + .getProjects(Permissions.BROWSE, user); List projectList = new ArrayList(); for (Project project : projects) { @@ -360,71 +325,19 @@ private List createUsers(final String userName, final String group) { if ((group != null) && (group.length() != 0)) { Set groupUsers = ComponentAccessor.getUserUtil().getAllUsersInGroupNames( Arrays.asList(new String[] { group })); - Set assigneeIds = new TreeSet(); - for (User groupUser : groupUsers) { - assigneeIds.add(groupUser.getName()); - String userKey = UserCompatibilityHelper.getKeyForUser(groupUser); - users.add(userKey); + List appUsers = ApplicationUsers.from(groupUsers); + for (ApplicationUser user : appUsers) { + users.add(user.getKey()); } } else if ((userName != null) && (userName.length() != 0)) { - User user = ComponentAccessor.getUserUtil().getUserObject(userName); + ApplicationUser user = ComponentAccessor.getUserManager().getUserByName(userName); if (user != null) { - String userKey = UserCompatibilityHelper.getKeyForUser(user); - users.add(userKey); + users.add(user.getKey()); } } return users; } - /** - * Convert a ResultSet object to a JSonObject. - * - * @param rs - * The ResultSet worklog. - * @param fields - * @return The worklog JSonObject. - * - * @throws JSONException - * If can't put value to the JSonObject. - * @throws ParseException - * If ParserException when parse the startDate. - */ - private JSONObject createWorklogJSONObject(final ResultSet rs, final List fields) - throws JSONException, - SQLException, ParseException { - JSONObject jsonWorklog = new JSONObject(); - jsonWorklog.put("id", rs.getLong("id")); - - Timestamp sDate = rs.getTimestamp("startdate"); - jsonWorklog.put("startDate", - DateTimeConverterUtil.stringDateToISO8601FormatString(sDate.toString())); - - IssueManager issueManager = ComponentAccessor.getIssueManager(); - String issueKey = issueManager.getIssueObject(rs.getLong("issueid")).getKey(); - jsonWorklog.put("issueKey", issueKey); - - String userKey = rs.getString("author"); - User user = UserCompatibilityHelper.getUserForKey(userKey); - String userName = user.getName(); - jsonWorklog.put("userId", userName); - - long timeSpentInSec = rs.getLong("timeworked"); - jsonWorklog.put("duration", timeSpentInSec); - - if (fields != null) { - if (StringList.joinLists(fields).asList().contains("comment")) { - String comment = rs.getString("worklogbody"); - jsonWorklog.put("comment", comment); - } - if (StringList.joinLists(fields).asList().contains("updated")) { - Timestamp updated = rs.getTimestamp("updated"); - jsonWorklog.put("updated", - DateTimeConverterUtil.stringDateToISO8601FormatString(updated.toString())); - } - } - return jsonWorklog; - } - /** * The updatedWorklogs restful api method. * @@ -476,9 +389,7 @@ public Response findUpdatedWorklogs( .entity("Cannot parse the 'endDate' parameter: " + endDate).build(); } try { - return Response.ok( - worklogQuery(startDateCalendar, endDateCalendar, user, group, project, fields, true)) - .build(); + return worklogQuery(startDateCalendar, endDateCalendar, user, group, project, fields, true); } catch (Exception e) { LOGGER.error("Failed to query the worklogs", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) @@ -557,8 +468,7 @@ public SearchResultsBeanWithTimespent findWorklogsByIssues( @DefaultValue("0") @QueryParam("startAt") int startAt, @DefaultValue("25") @QueryParam("maxResults") int maxResults, @DefaultValue("emptyFieldValue") @QueryParam("fields") final List fields) - throws - URISyntaxException, SQLException { + throws URISyntaxException, SQLException { checkRequiredFindWorklogsByIssuesParameter(startDate, endDate, user, group); @@ -599,38 +509,23 @@ public SearchResultsBeanWithTimespent findWorklogsByIssues( throw new RESTException(Response.Status.BAD_REQUEST, e.getMessage()); } - List issueIds = new ArrayList(); - for (Issue issue : issues) { - issueIds.add(issue.getId()); - } - Collections.reverse(issues); + Map issueIdIssue = collectIssueIds(issues); - Map result = sumWorklogs(startDateCalendar, endDateCalendar, users, issueIds); + List issueBeans = null; + try { + String jiraBaseUrl = ComponentAccessor.getApplicationProperties() + .getString(APKeys.JIRA_BASEURL) + "/rest/api/2/issue/"; + issueBeans = getQuerydslSupport().execute(new FindWorklogsByIssuesQuery(startDateCalendar, + endDateCalendar, users, issueIdIssue.keySet(), startAt, maxResults, jiraBaseUrl)); - IncludedFields includedFields = IncludedFields.includeNavigableByDefault(fields); - String baseUrl = ComponentAccessor.getApplicationProperties().getString(APKeys.JIRA_BASEURL) - + "/rest/api/2/issue/"; - boolean isEmptyField = StringList.joinLists(fields).asList().contains("emptyFieldValue"); - List issueBeans = new ArrayList(); - for (int i = 0, j = 0; ((j < issues.size()) && (i < (startAt + maxResults)));) { - Issue issue = issues.get(j); - if (result.containsKey(issue.getId())) { - if ((i >= startAt)) { - IssueBeanWithTimespent bean = new IssueBeanWithTimespent(issue.getId(), issue.getKey(), - new URI(baseUrl + issue.getId()), result.get(issue.getId())); - bean.fieldsToInclude(includedFields); - if (!isEmptyField) { - addFields(issue, bean); - } - issueBeans.add(bean); - } - i++; - } - j++; + addFieldsToIssueBeans(fields, issueIdIssue, issueBeans); + } catch (Exception e) { + throw new RESTException(Response.Status.BAD_REQUEST, + "Error when try collectig issue beans. " + e.getMessage()); } - SearchResultsBeanWithTimespent searchResultsBean = new SearchResultsBeanWithTimespent(startAt, - maxResults, - result.size(), issueBeans); + SearchResultsBeanWithTimespent searchResultsBean = + new SearchResultsBeanWithTimespent(startAt, maxResults, issueBeans.size(), + issueBeans); return searchResultsBean; } @@ -642,8 +537,7 @@ private FieldJsonRepresentation getFieldValue(final FieldLayoutItem fieldLayoutI if (field instanceof RestAwareField) { RestAwareField restAware = (RestAwareField) field; return restAware.getJsonFromIssue(issue, false, fieldLayoutItem); - } - else { + } else { return null; } } @@ -663,8 +557,7 @@ private List getIssuesByJQL(final String jql) JqlParseException { JiraAuthenticationContext authenticationContext = ComponentAccessor .getJiraAuthenticationContext(); - User loggedInUser = authenticationContext.getLoggedInUser(); - + User loggedInUser = ApplicationUsers.toDirectoryUser(authenticationContext.getUser()); List issues = null; SearchService searchService = ComponentAccessor.getComponentOfType(SearchService.class); final ParseResult parseResult = searchService.parseQuery(loggedInUser, jql); @@ -672,13 +565,23 @@ private List getIssuesByJQL(final String jql) final SearchResults results = searchService.search(loggedInUser, parseResult.getQuery(), PagerFilter.getUnlimitedFilter()); issues = results.getIssues(); - } - else { + } else { throw new JqlParseException(null, parseResult.getErrors().toString()); } return issues; } + private QuerydslSupport getQuerydslSupport() { + if (querydslSupport == null) { + try { + querydslSupport = new QuerydslSupportImpl(); + } catch (Exception e) { + throw new RuntimeException("Cannot create Worklog Query instance.", e); + } + } + return querydslSupport; + } + /** * Check the given String is empty. * @@ -693,94 +596,6 @@ private boolean isStringEmpty(final String theString) { return false; } - /** - * Summarize the worked time by issue. - * - * @param startDateCalendar - * The starting date of the search - * @param endDateCalendar - * The ending date of the search - * @param users - * The List of users whose worklog's are collected. - * @param issueIds - * A List of Issue IDs. Only these issues will be in the returned Map. - * @return A Map which keys are issueIDs and values are the worked time on that issue. - */ - private HashMap sumWorklogs(final Calendar startDateCalendar, - final Calendar endDateCalendar, - final List users, - final List issueIds) throws SQLException { - String schemaName = new DefaultOfBizConnectionFactory().getDatasourceInfo().getSchemaName(); - String worklogTablename = ""; - if ((schemaName != null) && !schemaName.equals("")) { - worklogTablename = schemaName + ".worklog"; - } else { - worklogTablename = "worklog"; - } - String query = "SELECT worklog.issueid, SUM(worklog.timeworked) AS timeworked" - + " FROM " + worklogTablename - + " WHERE worklog.startdate>=? AND worklog.startdate 0) { - authorPreparedParams.deleteCharAt(authorPreparedParams.length() - 1); - } - query += " AND worklog.author IN (" + authorPreparedParams.toString() + ")"; - query += " GROUP BY worklog.issueid"; - - Connection conn = null; - PreparedStatement ps = null; - ResultSet rs = null; - HashMap result = new HashMap(); - try { - conn = new DefaultOfBizConnectionFactory().getConnection(); - ps = conn.prepareStatement(query); - int preparedIndex = 1; - ps.setTimestamp(preparedIndex++, new Timestamp(startDateCalendar.getTimeInMillis())); - ps.setTimestamp(preparedIndex++, new Timestamp(endDateCalendar.getTimeInMillis())); - for (String user : users) { - ps.setString(preparedIndex++, user); - } - - rs = ps.executeQuery(); - - while (rs.next()) - { - Long worklogIssueId = rs.getLong("issueid"); - if (issueIds.contains(worklogIssueId)) { - result.put(worklogIssueId, rs.getLong("timeworked")); - } - } - } finally { - if (rs != null) { - try { - rs.close(); - } catch (SQLException e) { - LOGGER.error("Cannot close ResultSet"); - } - } - if (ps != null) { - try { - ps.close(); - } catch (SQLException e) { - LOGGER.error("Cannot close Statement"); - } - } - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - LOGGER.error("Cannot close Connection"); - } - } - } - - return result; - } - /** * The method to query worklogs. * @@ -809,21 +624,20 @@ private Response worklogQuery(final Calendar startDate, final Calendar endDate, final String userString, final String groupString, final String projectString, final List fields, final boolean updated) - throws DataAccessException, - SQLException, JSONException, ParseException { - - List worklogs = new ArrayList(); + throws DataAccessException, + SQLException, JSONException, ParseException { JiraAuthenticationContext authenticationContext = ComponentAccessor .getJiraAuthenticationContext(); - User loggedInUser = authenticationContext.getLoggedInUser(); + ApplicationUser loggedInUser = authenticationContext.getUser(); List projects = createProjects(projectString, loggedInUser); if ((projectString != null) && projects.isEmpty()) { return Response .status(Response.Status.BAD_REQUEST) .entity( "Error running search: There is no project matching the given 'project' parameter: " - + projectString).build(); + + projectString) + .build(); } List users = createUsers(userString, groupString); if (users.isEmpty()) { @@ -831,104 +645,13 @@ private Response worklogQuery(final Calendar startDate, final Calendar endDate, .entity("Error running search: There is no group or user matching the given parameters.") .build(); } - String schemaName = new DefaultOfBizConnectionFactory().getDatasourceInfo().getSchemaName(); - String worklogTablename = ""; - String issueTablename = ""; - if ((schemaName != null) && !schemaName.equals("")) { - worklogTablename = schemaName + ".worklog"; - issueTablename = schemaName + ".jiraissue"; - } else { - worklogTablename = "worklog"; - issueTablename = "jiraissue"; - } - - if (!projects.isEmpty() && !users.isEmpty()) { - - StringBuilder projectsPreparedParams = new StringBuilder(); - for (int i = 0; i < projects.size(); i++) { - projectsPreparedParams.append("?,"); - } - if (projectsPreparedParams.length() > 0) { - projectsPreparedParams.deleteCharAt(projectsPreparedParams.length() - 1); - } - StringBuilder usersPreparedParams = new StringBuilder(); - for (int i = 0; i < users.size(); i++) { - usersPreparedParams.append("?,"); - } - if (usersPreparedParams.length() > 0) { - usersPreparedParams.deleteCharAt(usersPreparedParams.length() - 1); - } - - String query = "SELECT worklog.id, worklog.startdate, worklog.issueid, worklog.author, worklog.timeworked, worklog.worklogbody, worklog.updated" - + " FROM " + worklogTablename + ", " + issueTablename - + " WHERE worklog.issueid=jiraissue.id" - + " AND worklog.startdate>=? AND worklog.startdate() { - @Override - public int compare(final JSONObject o1, final JSONObject o2) { - long a = 0, b = 0; - try { - a = o1.getLong("id"); - b = o2.getLong("id"); - } catch (JSONException e) { - throw new RuntimeException(e); - } - return a > b ? +1 : a < b ? -1 : 0; - } - }); + List jsonWorklogs = + getQuerydslSupport().execute(new FindWorklogsQuery(startDate, endDate, fields, + users, projects, updated)); JSONArray jsonArrayResult = new JSONArray(); - jsonArrayResult.put(worklogs); + jsonArrayResult.put(jsonWorklogs); + return Response.ok(jsonArrayResult.toString()).build(); // 2.0.0 diff --git a/core/src/main/java/org/everit/jira/worklog/query/plugin/query/FindWorklogsByIssuesQuery.java b/core/src/main/java/org/everit/jira/worklog/query/plugin/query/FindWorklogsByIssuesQuery.java new file mode 100644 index 0000000..2b8e1f7 --- /dev/null +++ b/core/src/main/java/org/everit/jira/worklog/query/plugin/query/FindWorklogsByIssuesQuery.java @@ -0,0 +1,128 @@ +/** + * This file is part of org.everit.jira.worklog.query.plugin.core. + * + * org.everit.jira.worklog.query.plugin.core is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * org.everit.jira.worklog.query.plugin.core is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with org.everit.jira.worklog.query.plugin.core. If not, see . + */ +package org.everit.jira.worklog.query.plugin.query; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.List; +import java.util.Set; + +import org.everit.jira.querydsl.schema.QJiraissue; +import org.everit.jira.querydsl.schema.QProject; +import org.everit.jira.querydsl.schema.QWorklog; +import org.everit.jira.querydsl.support.QuerydslCallable; +import org.everit.jira.worklog.query.plugin.core.IssueBeanWithTimespent; + +import com.querydsl.core.types.Expression; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.core.types.dsl.SimpleExpression; +import com.querydsl.core.types.dsl.StringExpression; +import com.querydsl.core.types.dsl.StringExpressions; +import com.querydsl.sql.Configuration; +import com.querydsl.sql.SQLExpressions; +import com.querydsl.sql.SQLQuery; + +/** + * Query to find worklogs by issues. + */ +public class FindWorklogsByIssuesQuery implements QuerydslCallable> { + + private final Calendar endDate; + + private final Set issueIds; + + private final String jiraBaseUrl; + + private final long limit; + + private final long offset; + + private final Calendar startDate; + + private final List userKeys; + + /** + * Simple constructor. + * + * @param startDate + * the start date of worklogs. + * @param endDate + * the end date of worklogs + * @param userKeys + * a list of user keys. + * @param issueIds + * a collection of user ids. + * @param offset + * the offset for the query results. + * @param limit + * the limit / max results for the query results. + * @param jiraBaseUrl + * the JIRA base url. + */ + public FindWorklogsByIssuesQuery(final Calendar startDate, final Calendar endDate, + final List userKeys, final Set issueIds, final long offset, final long limit, + final String jiraBaseUrl) { + this.endDate = endDate; + this.startDate = startDate; + this.userKeys = userKeys; + this.issueIds = issueIds; + this.offset = offset; + this.limit = limit; + this.jiraBaseUrl = jiraBaseUrl; + } + + @Override + public List call(final Connection connection, + final Configuration configuration) + throws SQLException { + QWorklog worklog = new QWorklog("worklog"); + QJiraissue issue = new QJiraissue("issue"); + QProject project = new QProject("project"); + + Timestamp startTimestamp = new Timestamp(startDate.getTimeInMillis()); + Timestamp endTimestamp = new Timestamp(endDate.getTimeInMillis()); + + StringExpression issueKey = project.pkey.concat("-").concat(issue.issuenum.stringValue()); + SimpleExpression timeworked = SQLExpressions.sum(worklog.timeworked).as("timeworked"); + Expression jiraBaseUrlExpression = Expressions.constant(jiraBaseUrl); + StringExpression jiraBaseUrlStringExpression = StringExpressions.ltrim(jiraBaseUrlExpression); + + StringExpression concat = jiraBaseUrlStringExpression.concat(issue.id.stringValue()); + return new SQLQuery>(connection, configuration) + .select(Projections.constructor(IssueBeanWithTimespent.class, + issue.id, + issueKey, + concat, + timeworked)) + .from(worklog) + .join(issue).on(issue.id.eq(worklog.issueid)) + .join(project).on(project.id.eq(issue.project)) + .where(worklog.startdate.goe(startTimestamp) + .and(worklog.startdate.lt(endTimestamp)) + .and(worklog.author.in(userKeys)) + .and(worklog.issueid.in(issueIds))) + .groupBy(issue.id, project.pkey, issue.issuenum) + .offset(offset) + .limit(limit) + .orderBy(issue.id.asc()) + .fetch(); + } + +} diff --git a/core/src/main/java/org/everit/jira/worklog/query/plugin/query/FindWorklogsQuery.java b/core/src/main/java/org/everit/jira/worklog/query/plugin/query/FindWorklogsQuery.java new file mode 100644 index 0000000..16990a9 --- /dev/null +++ b/core/src/main/java/org/everit/jira/worklog/query/plugin/query/FindWorklogsQuery.java @@ -0,0 +1,135 @@ +/** + * This file is part of org.everit.jira.worklog.query.plugin.core. + * + * org.everit.jira.worklog.query.plugin.core is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * org.everit.jira.worklog.query.plugin.core is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with org.everit.jira.worklog.query.plugin.core. If not, see . + */ +package org.everit.jira.worklog.query.plugin.query; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; + +import org.everit.jira.querydsl.schema.QAppUser; +import org.everit.jira.querydsl.schema.QCwdUser; +import org.everit.jira.querydsl.schema.QJiraissue; +import org.everit.jira.querydsl.schema.QProject; +import org.everit.jira.querydsl.schema.QWorklog; +import org.everit.jira.querydsl.support.QuerydslCallable; + +import com.atlassian.jira.rest.api.util.StringList; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.StringExpression; +import com.querydsl.sql.Configuration; +import com.querydsl.sql.SQLExpressions; +import com.querydsl.sql.SQLQuery; + +/** + * Query to find worklogs. + */ +public class FindWorklogsQuery implements QuerydslCallable> { + + private final Calendar endDate; + + private final List fields; + + private List projectIds; + + private final Calendar startDate; + + private final boolean updated; + + private final List userKeys; + + /** + * Simple constructor. + * + * @param startDate + * the start date of worklogs. + * @param endDate + * the end date of worklogs + * @param fields + * a list of additional fields. + * @param userKeys + * a list of user keys. + * @param projectIds + * a list of project ids. + * @param updated + * True if the method give back the worklogs which were created or updated in the given + * period, else false. The false give back the worklogs of the period. + */ + public FindWorklogsQuery(final Calendar startDate, final Calendar endDate, + final List fields, final List userKeys, final List projectIds, + final boolean updated) { + this.startDate = startDate; + this.endDate = endDate; + this.fields = fields; + this.userKeys = userKeys; + this.projectIds = projectIds; + this.updated = updated; + } + + @Override + public List call(final Connection connection, final Configuration configuration) + throws SQLException { + QWorklog worklog = new QWorklog("worklog"); + QJiraissue issue = new QJiraissue("issue"); + QProject project = new QProject("project"); + QCwdUser cwduser = new QCwdUser("cwd_user"); + QAppUser appuser = new QAppUser("app_user"); + + StringExpression issueKey = project.pkey.concat("-").concat(issue.issuenum.stringValue()); + + Timestamp startTimestamp = new Timestamp(startDate.getTimeInMillis()); + Timestamp endTimestamp = new Timestamp(endDate.getTimeInMillis()); + + List fieldsAsList = + Arrays.asList(StringList.joinLists(fields).toQueryParam().split(",")); + final boolean useComment = fieldsAsList.contains("comment"); + final boolean useUpdated = fieldsAsList.contains("updated"); + + BooleanExpression intervalPredicate = null; + if (updated) { + intervalPredicate = worklog.updated.goe(startTimestamp) + .and(worklog.updated.lt(endTimestamp)); + } else { + intervalPredicate = worklog.startdate.goe(startTimestamp) + .and(worklog.startdate.lt(endTimestamp)); + } + + return new SQLQuery(connection, configuration) + .select(JsonWorklog.createProjection(worklog.id, + worklog.startdate, + issueKey, + SQLExpressions.select(cwduser.userName) + .from(cwduser) + .join(appuser).on(cwduser.lowerUserName.eq(appuser.lowerUserName)) + .where(appuser.userKey.eq(worklog.author)) + .distinct(), + worklog.timeworked, + useComment ? worklog.worklogbody : null, + useUpdated ? worklog.updated : null)) + .from(worklog) + .join(issue).on(issue.id.eq(worklog.issueid)) + .join(project).on(project.id.eq(issue.project)) + .where(intervalPredicate + .and(worklog.author.in(userKeys)) + .and(issue.project.in(projectIds))) + .orderBy(worklog.id.asc()) + .fetch(); + } + +} diff --git a/core/src/main/java/org/everit/jira/worklog/query/plugin/query/JsonWorklog.java b/core/src/main/java/org/everit/jira/worklog/query/plugin/query/JsonWorklog.java new file mode 100644 index 0000000..fa892c8 --- /dev/null +++ b/core/src/main/java/org/everit/jira/worklog/query/plugin/query/JsonWorklog.java @@ -0,0 +1,166 @@ +/** + * This file is part of org.everit.jira.worklog.query.plugin.core. + * + * org.everit.jira.worklog.query.plugin.core is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * org.everit.jira.worklog.query.plugin.core is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with org.everit.jira.worklog.query.plugin.core. If not, see . + */ +package org.everit.jira.worklog.query.plugin.query; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; + +import org.everit.jira.worklog.query.plugin.core.DateTimeConverterUtil; + +import com.atlassian.jira.util.json.JSONException; +import com.atlassian.jira.util.json.JSONObject; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.QBean; +import com.querydsl.core.types.dsl.DateTimeExpression; +import com.querydsl.core.types.dsl.NumberExpression; +import com.querydsl.core.types.dsl.SimpleExpression; +import com.querydsl.core.types.dsl.StringExpression; +import com.querydsl.sql.SQLQuery; + +/** + * JsonWorklog is an unordered collection of name/value pairs. Contains information of worklog. + */ +public class JsonWorklog extends JSONObject { + + private static final String COMMENT = "commentBody"; + + private static final String DURATION = "duration"; + + private static final String ID = "id"; + + private static final String ISSUE_KEY = "issueKey"; + + private static final String START_DATE = "startDate"; + + private static final String UPDATED = "updated"; + + private static final String USER_ID = "userId"; + + /** + * Create a JsonWorklog Bean populating projection for the given type and expressions. + * + * @param worklogId + * the id of the worklog expression. + * @param startDate + * the worklog startdate expression. + * @param issueKey + * the issue key expression. + * @param userId + * the user id SQL subquery. + * @param duration + * the worklog duration expression. + * @param comment + * the worklog comment expression. + * @param updated + * the worklog updated date expression. + * @return the JsonWorklog Bean population projection. + */ + public static QBean createProjection(final NumberExpression worklogId, + final DateTimeExpression startDate, final StringExpression issueKey, + final SQLQuery userId, final NumberExpression duration, + final StringExpression comment, final DateTimeExpression updated) { + + List> expressionList = new ArrayList>(); + expressionList.add(worklogId.as(ID)); + expressionList.add(startDate.as(START_DATE)); + expressionList.add(issueKey.as(ISSUE_KEY)); + expressionList.add(userId.as(USER_ID)); + expressionList.add(duration.as(DURATION)); + if (comment != null) { + expressionList.add(comment.as(COMMENT)); + } + if (updated != null) { + expressionList.add(updated.as(UPDATED)); + } + + SimpleExpression[] expressions = new SimpleExpression[expressionList.size()]; + + return Projections.bean(JsonWorklog.class, expressionList.toArray(expressions)); + } + + /** + * Create a JsonWorklog Bean populating projection for the given type and expressions. + * + * @param worklogId + * the id of the worklog expression. + * @param startDate + * the worklog startdate expression. + * @param issueKey + * the issue key expression. + * @param userId + * the user id expression. + * @param duration + * the worklog duration expression. + * @param comment + * the worklog comment expression. + * @param updated + * the worklog updated date expression. + * @return the JsonWorklog Bean population projection. + */ + public static QBean createProjection(final NumberExpression worklogId, + final DateTimeExpression startDate, final StringExpression issueKey, + final StringExpression userId, final NumberExpression duration, + final StringExpression comment, final DateTimeExpression updated) { + + List> expressionList = new ArrayList>(); + expressionList.add(worklogId.as(ID)); + expressionList.add(startDate.as(START_DATE)); + expressionList.add(issueKey.as(ISSUE_KEY)); + expressionList.add(userId.as(USER_ID)); + expressionList.add(duration.as(DURATION)); + if (comment != null) { + expressionList.add(comment.as(COMMENT)); + } + if (updated != null) { + expressionList.add(updated.as(UPDATED)); + } + + SimpleExpression[] expressions = new SimpleExpression[expressionList.size()]; + + return Projections.bean(JsonWorklog.class, expressionList.toArray(expressions)); + } + + public void setCommentBody(final String comment) throws JSONException { + put("comment", comment); + } + + public void setDuration(final long duration) throws JSONException { + put(DURATION, duration); + } + + public void setId(final long id) throws JSONException { + put(ID, Long.valueOf(id)); + } + + public void setIssueKey(final String issueKey) throws JSONException { + put(ISSUE_KEY, issueKey); + } + + public void setStartDate(final Timestamp startDate) throws JSONException { + put(START_DATE, DateTimeConverterUtil.stringDateToISO8601FormatString(startDate)); + } + + public void setUpdated(final Timestamp updated) throws JSONException { + put(UPDATED, DateTimeConverterUtil.stringDateToISO8601FormatString(updated)); + } + + public void setUserId(final String userId) throws JSONException { + put(USER_ID, userId); + } + +} diff --git a/core/src/main/resources/atlassian-plugin.xml b/core/src/main/resources/atlassian-plugin.xml index 51286f5..69d6a56 100644 --- a/core/src/main/resources/atlassian-plugin.xml +++ b/core/src/main/resources/atlassian-plugin.xml @@ -1,37 +1,40 @@ - - 1.2.1-SNAPSHOT - Jira Worklog Query Plugin - + ${project.version} + Query worklogs in JSON format via an authenticated RESTful service. Using the + Worklog Query Plugin is easy to retrieve time tracking data from any application. + + true + icons/jwqp16.png + icons/jwqp144.png + icons/e_logo16.png + icons/e_logo72.png - + Provides the REST resource for the Worklog Query plugin. diff --git a/core/src/main/resources/icons/e_logo16.png b/core/src/main/resources/icons/e_logo16.png new file mode 100644 index 0000000..c125951 Binary files /dev/null and b/core/src/main/resources/icons/e_logo16.png differ diff --git a/core/src/main/resources/icons/e_logo72.png b/core/src/main/resources/icons/e_logo72.png new file mode 100644 index 0000000..2871f4c Binary files /dev/null and b/core/src/main/resources/icons/e_logo72.png differ diff --git a/core/src/main/resources/icons/jwqp144.png b/core/src/main/resources/icons/jwqp144.png new file mode 100644 index 0000000..01d34ec Binary files /dev/null and b/core/src/main/resources/icons/jwqp144.png differ diff --git a/core/src/main/resources/icons/jwqp16.png b/core/src/main/resources/icons/jwqp16.png new file mode 100644 index 0000000..12307ca Binary files /dev/null and b/core/src/main/resources/icons/jwqp16.png differ diff --git a/itest/pom.xml b/itest/pom.xml index 23ce418..61c6505 100644 --- a/itest/pom.xml +++ b/itest/pom.xml @@ -1,26 +1,23 @@ + @@ -28,7 +25,7 @@ org.everit.jira.worklog.query.plugin - 1.2.1-SNAPSHOT + 1.3.4 org.everit.jira.worklog.query.plugin.parent diff --git a/itest/src/main/java/org/everit/jira/worklog/query/test/WorklogQueryTest.java b/itest/src/main/java/org/everit/jira/worklog/query/test/WorklogQueryTest.java index 43ac613..237d7c7 100644 --- a/itest/src/main/java/org/everit/jira/worklog/query/test/WorklogQueryTest.java +++ b/itest/src/main/java/org/everit/jira/worklog/query/test/WorklogQueryTest.java @@ -1,25 +1,20 @@ -package org.everit.jira.worklog.query.test; - -/* - * Copyright (c) 2013, Everit Kft. - * - * All rights reserved. +/** + * This file is part of org.everit.jira.worklog.query.plugin.itest. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * org.everit.jira.worklog.query.plugin.itest is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * org.everit.jira.worklog.query.plugin.itest is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * You should have received a copy of the GNU Lesser General Public License + * along with org.everit.jira.worklog.query.plugin.itest. If not, see . */ +package org.everit.jira.worklog.query.test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/pom.xml b/pom.xml index 48da730..3ab88fd 100644 --- a/pom.xml +++ b/pom.xml @@ -1,24 +1,20 @@ 4.0.0 - org.everit - oss - 4 + org.everit.config + org.everit.config.oss + 5.0.2 + org.everit.jira.worklog.query.plugin org.everit.jira.worklog.query.plugin.parent - 1.2.1-SNAPSHOT + 1.3.4 pom 2013 - 5.0 + 6.2 + 1.7 + 1.7 + 5.1.9 @@ -56,8 +56,8 @@ - Jenkins - https://ci.everit.biz/jenkins/job/jira-worklog-query-plugin + Travis CI + https://travis-ci.org/everit-org/everit-org/jira-worklog-query-plugin @@ -65,6 +65,22 @@ https://github.com/everit-org/jira-worklog-query-plugin/issues + + + atlassian-public + https://maven.atlassian.com/repository/public + + true + never + warn + + + true + warn + + + + 3dparty @@ -79,7 +95,7 @@ atlassian-public https://maven.atlassian.com/repository/public - + true never warn @@ -89,6 +105,11 @@ warn + + everit.release + everit-releases + https://repo.everit.biz/artifactory/public-release/ +