diff --git a/src/main/java/com/jaspersoft/jasperserver/jaxrs/client/apiadapters/jobs/JobsService.java b/src/main/java/com/jaspersoft/jasperserver/jaxrs/client/apiadapters/jobs/JobsService.java index dad714ea..0c70ddbf 100644 --- a/src/main/java/com/jaspersoft/jasperserver/jaxrs/client/apiadapters/jobs/JobsService.java +++ b/src/main/java/com/jaspersoft/jasperserver/jaxrs/client/apiadapters/jobs/JobsService.java @@ -1,116 +1,231 @@ -/* - * Copyright (C) 2005 - 2014 Jaspersoft Corporation. All rights reserved. - * http://www.jaspersoft.com. - * - * Unless you have purchased a commercial license agreement from Jaspersoft, - * the following license terms apply: - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program.  If not, see . - */ - -package com.jaspersoft.jasperserver.jaxrs.client.apiadapters.jobs; - -import com.jaspersoft.jasperserver.jaxrs.client.apiadapters.AbstractAdapter; -import com.jaspersoft.jasperserver.jaxrs.client.apiadapters.jobs.calendar.CalendarType; -import com.jaspersoft.jasperserver.jaxrs.client.apiadapters.jobs.calendar.SingleCalendarOperationsAdapter; -import com.jaspersoft.jasperserver.jaxrs.client.core.*; -import com.jaspersoft.jasperserver.jaxrs.client.core.operationresult.OperationResult; -import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.Job; -import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.jaxb.wrappers.CalendarNameListWrapper; - -import static com.jaspersoft.jasperserver.jaxrs.client.core.JerseyRequest.buildRequest; - -public class JobsService extends AbstractAdapter { - - public JobsService(SessionStorage sessionStorage) { - super(sessionStorage); - } - - public BatchJobsOperationsAdapter jobs() { - return new BatchJobsOperationsAdapter(sessionStorage); - } - - public SingleJobOperationsAdapter job(long jobId) { - return new SingleJobOperationsAdapter(sessionStorage, String.valueOf(jobId)); - } - - public OperationResult scheduleReport(Job report) { - JerseyRequest request = buildRequest(sessionStorage, Job.class, new String[]{"/jobs"}, new JobValidationErrorHandler()); - if (sessionStorage.getConfiguration().getJrsVersion().compareTo(JRSVersion.v5_5_0) > 0) { - request.setContentType(MimeTypeUtil.toCorrectContentMime(sessionStorage.getConfiguration(), "application/job+{mime}")); - request.setAccept(MimeTypeUtil.toCorrectAcceptMime(sessionStorage.getConfiguration(), "application/job+{mime}")); - } else { - request.setContentType("application/job+json"); - request.setAccept("application/job+json"); - } - return request.put(report); - } - - public RequestExecution asyncScheduleReport(final Job report, final Callback, R> callback) { - final JerseyRequest request = buildRequest(sessionStorage, Job.class, new String[]{"/jobs"}, new JobValidationErrorHandler()); - if (sessionStorage.getConfiguration().getJrsVersion().compareTo(JRSVersion.v5_5_0) > 0) { - request.setContentType(MimeTypeUtil.toCorrectContentMime(sessionStorage.getConfiguration(), "application/job+{mime}")); - request.setAccept(MimeTypeUtil.toCorrectAcceptMime(sessionStorage.getConfiguration(), "application/job+{mime}")); - } else { - request.setContentType("application/job+json"); - request.setAccept("application/job+json"); - } - RequestExecution task = new RequestExecution(new Runnable() { - @Override - public void run() { - callback.execute(request.put(report)); - } - }); - ThreadPoolUtil.runAsynchronously(task); - return task; - } - - public OperationResult calendars() { - return calendars(null); - } - - public RequestExecution asyncCalendars(final Callback, R> callback) { - return asyncCalendars(null, callback); - } - - public OperationResult calendars(CalendarType type) { - JerseyRequest request = buildRequest(sessionStorage, CalendarNameListWrapper.class, new String[]{"/jobs", "/calendars"}); - if (type != null) { - request.addParam("calendarType", type.name().toLowerCase()); - } - return request.get(); - } - - public RequestExecution asyncCalendars(final CalendarType type, final Callback, R> callback) { - final JerseyRequest request = buildRequest(sessionStorage, CalendarNameListWrapper.class, new String[]{"/jobs", "/calendars"}); - if (type != null) { - request.addParam("calendarType", type.name().toLowerCase()); - } - RequestExecution task = new RequestExecution(new Runnable() { - @Override - public void run() { - callback.execute(request.get()); - } - }); - ThreadPoolUtil.runAsynchronously(task); - return task; - } - - public SingleCalendarOperationsAdapter calendar(String calendarName) { - if ("".equals(calendarName) || "/".equals(calendarName)) { - throw new IllegalArgumentException("'calendarName' mustn't be an empty string"); - } - return new SingleCalendarOperationsAdapter(sessionStorage, calendarName); - } -} +/* + * Copyright (C) 2005 - 2014 Jaspersoft Corporation. All rights reserved. + * http://www.jaspersoft.com. + * + * Unless you have purchased a commercial license agreement from Jaspersoft, + * the following license terms apply: + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program.  If not, see . + */ + +package com.jaspersoft.jasperserver.jaxrs.client.apiadapters.jobs; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.ObjectMapper; + +import com.google.common.annotations.VisibleForTesting; +import com.jaspersoft.jasperserver.jaxrs.client.apiadapters.AbstractAdapter; +import com.jaspersoft.jasperserver.jaxrs.client.apiadapters.jobs.calendar.CalendarType; +import com.jaspersoft.jasperserver.jaxrs.client.apiadapters.jobs.calendar.SingleCalendarOperationsAdapter; +import com.jaspersoft.jasperserver.jaxrs.client.core.Callback; +import com.jaspersoft.jasperserver.jaxrs.client.core.JRSVersion; +import com.jaspersoft.jasperserver.jaxrs.client.core.JerseyRequest; +import com.jaspersoft.jasperserver.jaxrs.client.core.MimeTypeUtil; +import com.jaspersoft.jasperserver.jaxrs.client.core.RequestExecution; +import com.jaspersoft.jasperserver.jaxrs.client.core.SessionStorage; +import com.jaspersoft.jasperserver.jaxrs.client.core.ThreadPoolUtil; +import com.jaspersoft.jasperserver.jaxrs.client.core.operationresult.OperationResult; +import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.Job; +import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.JobSource; +import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.OutputFormat; +import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.SimpleTrigger; +import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.jaxb.wrappers.CalendarNameListWrapper; + +import static com.jaspersoft.jasperserver.jaxrs.client.core.JerseyRequest.buildRequest; + +public class JobsService extends AbstractAdapter { + + public JobsService(SessionStorage sessionStorage) { + super(sessionStorage); + } + + public BatchJobsOperationsAdapter jobs() { + return new BatchJobsOperationsAdapter(sessionStorage); + } + + public SingleJobOperationsAdapter job(long jobId) { + return new SingleJobOperationsAdapter(sessionStorage, String.valueOf(jobId)); + } + + public OperationResult scheduleReport(Job report) { + JerseyRequest request = buildRequest(sessionStorage, Job.class, new String[]{"/jobs"}, new JobValidationErrorHandler()); + if (sessionStorage.getConfiguration().getJrsVersion().compareTo(JRSVersion.v5_5_0) > 0) { + request.setContentType(MimeTypeUtil.toCorrectContentMime(sessionStorage.getConfiguration(), "application/job+{mime}")); + request.setAccept(MimeTypeUtil.toCorrectAcceptMime(sessionStorage.getConfiguration(), "application/job+{mime}")); + } else { + request.setContentType("application/job+json"); + request.setAccept("application/job+json"); + } + return request.put(report); + } + + public RequestExecution asyncScheduleReport(final Job report, final Callback, R> callback) { + final JerseyRequest request = buildRequest(sessionStorage, Job.class, new String[]{"/jobs"}, new JobValidationErrorHandler()); + if (sessionStorage.getConfiguration().getJrsVersion().compareTo(JRSVersion.v5_5_0) > 0) { + request.setContentType(MimeTypeUtil.toCorrectContentMime(sessionStorage.getConfiguration(), "application/job+{mime}")); + request.setAccept(MimeTypeUtil.toCorrectAcceptMime(sessionStorage.getConfiguration(), "application/job+{mime}")); + } else { + request.setContentType("application/job+json"); + request.setAccept("application/job+json"); + } + RequestExecution task = new RequestExecution(new Runnable() { + @Override + public void run() { + callback.execute(request.put(report)); + } + }); + ThreadPoolUtil.runAsynchronously(task); + return task; + } + + public OperationResult calendars() { + return calendars(null); + } + + public RequestExecution asyncCalendars(final Callback, R> callback) { + return asyncCalendars(null, callback); + } + + public OperationResult calendars(CalendarType type) { + JerseyRequest request = buildRequest(sessionStorage, CalendarNameListWrapper.class, new String[]{"/jobs", "/calendars"}); + if (type != null) { + request.addParam("calendarType", type.name().toLowerCase()); + } + return request.get(); + } + + public RequestExecution asyncCalendars(final CalendarType type, final Callback, R> callback) { + final JerseyRequest request = buildRequest(sessionStorage, CalendarNameListWrapper.class, new String[]{"/jobs", "/calendars"}); + if (type != null) { + request.addParam("calendarType", type.name().toLowerCase()); + } + RequestExecution task = new RequestExecution(new Runnable() { + @Override + public void run() { + callback.execute(request.get()); + } + }); + ThreadPoolUtil.runAsynchronously(task); + return task; + } + + public SingleCalendarOperationsAdapter calendar(String calendarName) { + if ("".equals(calendarName) || "/".equals(calendarName)) { + throw new IllegalArgumentException("'calendarName' mustn't be an empty string"); + } + return new SingleCalendarOperationsAdapter(sessionStorage, calendarName); + } + + //START: palash: changes to get report scheduling working + public long scheduleReportWithHack(Job report) { + JerseyRequest request = buildRequest(sessionStorage, String.class, new String[]{"/jobs"}, new JobValidationErrorHandler()); + request.setContentType("application/job+json"); + request.setAccept("application/job+json"); + + String inputJson = getJobAsJsonString(report); + + System.err.println("inputJson:\n" + inputJson); + + OperationResult result = request.put(inputJson); + String jsonResult = result.getEntity(); + + System.err.println("Result:\n" + jsonResult); + + JsonNode jsonNode; + try { + jsonNode = new ObjectMapper().readTree(jsonResult); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return jsonNode.findValue("id").asLong(); + } + + @VisibleForTesting + String getJobAsJsonString(Job job) { + + String jsonStringTemplate = "{\"label\":\"%s\",\"description\":\"%s\"," + + "\"trigger\":{\"simpleTrigger\":{\"startType\":%d,\"misfireInstruction\":%d,\"occurrenceCount\":%d%s}}," + + "\"source\":{\"reportUnitURI\":\"%s\",\"parameters\":{\"parameterValues\":%s}},\"baseOutputFilename\":\"%s\"," + + "\"repositoryDestination\":{\"folderURI\":\"%s\",\"outputLocalFolder\":\"%s\",\"sequentialFilenames\":false,\"overwriteFiles\":true,\"saveToRepository\":%s," + + "\"usingDefaultReportOutputFolderURI\":false},\"outputFormats\":{\"outputFormat\":%s}}"; + + + JobSource jobSource = job.getSource(); + SimpleTrigger simpleTrigger = (SimpleTrigger) job.getTrigger(); + + String recurrenceDetails; + + if (simpleTrigger.getOccurrenceCount() > 1){ + recurrenceDetails = ",\"recurrenceInterval\":"+simpleTrigger.getRecurrenceInterval() + + ",\"recurrenceIntervalUnit\":\""+simpleTrigger.getRecurrenceIntervalUnit().name() + + "\""; + } else { + recurrenceDetails=""; + } + + String jsonString = String.format(jsonStringTemplate, job.getLabel(), job.getDescription(), simpleTrigger.getStartType(), + simpleTrigger.getMisfireInstruction(), simpleTrigger.getOccurrenceCount(),recurrenceDetails, + jobSource.getReportUnitURI(), getReportParamsAsJsonString(jobSource.getParameters()), job.getBaseOutputFilename(), job.getRepositoryDestination().getFolderURI(), + job.getRepositoryDestination().getOutputLocalFolder(),job.getRepositoryDestination().isSaveToRepository(), getOutputFormatsAsJsonString(job.getOutputFormats())); + + + return jsonString; + } + + private String getReportParamsAsJsonString(Map reportParams) { + StringBuilder sb = new StringBuilder(100); + sb.append("{"); + + for (Entry paramKeyValue : reportParams.entrySet()) { + //key + sb.append('"').append(paramKeyValue.getKey()).append('"'); + sb.append(":"); + //value + sb.append("[\"").append(paramKeyValue.getValue()).append("\"]"); + sb.append(","); + } + + //remove the xtra , + sb.setLength(sb.length() - 1); + + sb.append("}"); + return sb.toString(); + } + + private String getOutputFormatsAsJsonString(Set outputFormats) { + StringBuilder sb = new StringBuilder(60); + + sb.append("["); + + for (OutputFormat outputFormat : outputFormats) { + sb.append('"').append(outputFormat.name()).append('"').append(","); + } + + //remove the xtra , + sb.setLength(sb.length() - 1); + + sb.append("]"); + + return sb.toString(); + } + + //END: palash: changes to get report scheduling working + +} \ No newline at end of file diff --git a/src/test/java/com/jaspersoft/jasperserver/jaxrs/client/apiadapters/jobs/JobsServiceTest.java b/src/test/java/com/jaspersoft/jasperserver/jaxrs/client/apiadapters/jobs/JobsServiceTest.java index fc086e3a..ad98b061 100644 --- a/src/test/java/com/jaspersoft/jasperserver/jaxrs/client/apiadapters/jobs/JobsServiceTest.java +++ b/src/test/java/com/jaspersoft/jasperserver/jaxrs/client/apiadapters/jobs/JobsServiceTest.java @@ -1,5 +1,21 @@ package com.jaspersoft.jasperserver.jaxrs.client.apiadapters.jobs; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +import org.mockito.Mock; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.testng.PowerMockTestCase; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + import com.jaspersoft.jasperserver.jaxrs.client.apiadapters.jobs.calendar.CalendarType; import com.jaspersoft.jasperserver.jaxrs.client.apiadapters.jobs.calendar.SingleCalendarOperationsAdapter; import com.jaspersoft.jasperserver.jaxrs.client.core.Callback; @@ -10,19 +26,13 @@ import com.jaspersoft.jasperserver.jaxrs.client.core.RestClientConfiguration; import com.jaspersoft.jasperserver.jaxrs.client.core.SessionStorage; import com.jaspersoft.jasperserver.jaxrs.client.core.operationresult.OperationResult; +import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.IntervalUnitType; import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.Job; +import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.JobSource; +import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.OutputFormat; +import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.RepositoryDestination; +import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.SimpleTrigger; import com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.jaxb.wrappers.CalendarNameListWrapper; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.testng.PowerMockTestCase; -import org.testng.Assert; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.concurrent.atomic.AtomicInteger; import static com.jaspersoft.jasperserver.jaxrs.client.core.JerseyRequest.buildRequest; import static org.mockito.Matchers.any; @@ -233,7 +243,6 @@ public void should_return_proper_op_result_object_when_param_is_not_null() { verify(wrapperRequestMock, times(1)).addParam("calendarType", CalendarType.daily.toString().toLowerCase()); } - @Test(testName = "calendars_with_param") public void should_return_proper_op_result_object_when_param_is_null() { @@ -257,7 +266,6 @@ public void should_return_proper_op_result_object_when_param_is_null() { verify(wrapperRequestMock, never()).addParam("calendarType", CalendarType.daily.toString().toLowerCase()); } - @Test(testName = "calendar") public void should_return_an_calendar_adapter() throws Exception { @@ -426,9 +434,60 @@ public Void execute(OperationResult data) { Mockito.verify(configurationMock).getJrsVersion(); } + @Test(testName = "getJobAsJsonString") + public void testGetJobAsJsonString() { + //given + String expected = "{\"label\":\"AAAAAAAAAAAAAAA\",\"description\":\"BBBBBBBBBBBBBBBBBBBBBB\"," + + "\"trigger\":{\"simpleTrigger\":{\"startType\":1,\"misfireInstruction\":6,\"occurrenceCount\":5,\"recurrenceInterval\":10,\"recurrenceIntervalUnit\":\"WEEK\"}}," + + "\"source\":{\"reportUnitURI\":\"CCCCCCCCCCCCCCCCCCCC\",\"parameters\":{\"parameterValues\":{\"param_1\":[\"value_1\"],\"param_2\":[\"value_2\"]," + + "\"param_3\":[\"value_3\"],\"param_4\":[\"value_4\"]}}},\"baseOutputFilename\":\"DDDDDDDDDDDDDDDDDDDDD\"," + + "\"repositoryDestination\":{\"folderURI\":\"EEEEEEEEEEEEEEEEE\",\"sequentialFilenames\":false,\"overwriteFiles\":true,\"saveToRepository\":true," + + "\"usingDefaultReportOutputFolderURI\":false},\"outputFormats\":{\"outputFormat\":[\"XLSX\",\"PDF\",\"CSV\"]}}"; + + Job job = new Job(); + job.setLabel("AAAAAAAAAAAAAAA"); + job.setDescription("BBBBBBBBBBBBBBBBBBBBBB"); + JobSource jobSource = new JobSource(); + jobSource.setReportUnitURI("CCCCCCCCCCCCCCCCCCCC"); + + Map parameters = new LinkedHashMap(); + parameters.put("param_1", "value_1"); + parameters.put("param_2", "value_2"); + parameters.put("param_3", "value_3"); + parameters.put("param_4", "value_4"); + + jobSource.setParameters(parameters); + job.setSource(jobSource); + Set outputFormats = new LinkedHashSet(); + outputFormats.add(OutputFormat.XLSX); + outputFormats.add(OutputFormat.PDF); + outputFormats.add(OutputFormat.CSV); + job.setOutputFormats(outputFormats); + RepositoryDestination repositoryDestination = new RepositoryDestination(); + repositoryDestination.setSaveToRepository(true); + repositoryDestination.setFolderURI("EEEEEEEEEEEEEEEEE"); + job.setRepositoryDestination(repositoryDestination); + SimpleTrigger trigger = new SimpleTrigger(); + trigger.setStartType(SimpleTrigger.START_TYPE_NOW); + trigger.setMisfireInstruction(6); + trigger.setOccurrenceCount(5); + trigger.setRecurrenceInterval(10); + trigger.setRecurrenceIntervalUnit(IntervalUnitType.WEEK); + job.setTrigger(trigger); + job.setBaseOutputFilename("DDDDDDDDDDDDDDDDDDDDD"); + + JobsService testClass = new JobsService(sessionStorageMock); + + //when + String result = testClass.getJobAsJsonString(job); + + //then + Assert.assertEquals(result, expected); + } + @AfterMethod public void after() { reset(sessionStorageMock, expectedAdapterMock, expectedJobOperationsAdapter, - jobRequestMock, expectedJobOperationResultMock, reportMock, configurationMock); + jobRequestMock, expectedJobOperationResultMock, reportMock, configurationMock); } } \ No newline at end of file