diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..c9b76619
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,56 @@
+# Created by .gitignore support plugin (hsz.mobi)
+### Android template
+# Built application files
+*.apk
+*.ap_
+
+# Files for the Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
+
+## Directory-based project format
+.idea/
+
+## File-based project format
+*.ipr
+*.iml
+*.iws
+
+## Additional for IntelliJ
+out/
+
+# generated by mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# generated by JIRA plugin
+atlassian-ide-plugin.xml
+
+# generated by Crashlytics plugin (for Android Studio and Intellij)
+com_crashlytics_export_strings.xml.DS_Store
+.idea*
+*.iml
+*.db
+out
+bin
+gen
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 00000000..b1f1bf29
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,41 @@
+buildscript {
+ repositories {
+ jcenter()
+ mavenCentral()
+ maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
+ mavenLocal()
+ }
+ dependencies {
+ classpath "com.android.tools.build:gradle:0.14.2"
+ classpath "com.github.dcendents:android-maven-plugin:1.2"
+ }
+}
+
+subprojects {
+ group = 'com.jaspersoft.android.sdk'
+ version = '1.9'
+
+ ext.androidMinSdkVersion = 9
+ ext.androidTargetSdkVersion = 19
+ ext.androidCompileSdkVersion = 19
+ ext.androidBuildToolsVersion = "19.1"
+
+ repositories {
+ jcenter()
+ mavenCentral()
+ mavenLocal()
+ maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
+ maven { url "file://${System.getenv("ANDROID_HOME")}/extras/android/m2repository" }
+ }
+}
+
+apply plugin: 'java' // ensure clean is also triggered for root build folder
+apply plugin: 'build-dashboard'
+
+buildDashboard {
+ reports.html.destination = "build/"
+}
+
+test.reports.html.enabled = false // just clean up dashboard from not generated reports
+test.reports.junitXml.enabled = false // just clean up dashboard from not generated reports
+
diff --git a/client/build.gradle b/client/build.gradle
new file mode 100644
index 00000000..e0fe023f
--- /dev/null
+++ b/client/build.gradle
@@ -0,0 +1,51 @@
+apply plugin: 'com.android.library'
+apply plugin: 'android-maven'
+
+description = 'js-android-sdk-client'
+
+ext {
+ PUBLISH_GROUP_ID = group
+ PUBLISH_ARTIFACT_ID = description
+ PUBLISH_VERSION = '1.9'
+}
+
+android {
+ compileSdkVersion androidCompileSdkVersion
+ buildToolsVersion androidBuildToolsVersion
+
+ defaultConfig {
+ minSdkVersion androidMinSdkVersion
+ targetSdkVersion androidTargetSdkVersion
+ versionCode 9010900
+ versionName version
+ }
+
+ packagingOptions {
+ exclude 'META-INF/notice.txt'
+ exclude 'META-INF/license.txt'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/NOTICE.txt'
+ }
+ lintOptions {
+ abortOnError false
+ }
+
+ buildTypes {
+ debug {
+ runProguard false
+ }
+ }
+}
+
+dependencies {
+ compile 'org.springframework.android:spring-android-rest-template:1.0.1.RELEASE'
+ compile 'com.octo.android.robospice:robospice:1.4.14'
+ compile 'com.octo.android.robospice:robospice-spring-android:1.4.14'
+ compile('org.simpleframework:simple-xml:2.7') {
+ exclude group: 'stax', module: 'stax'
+ exclude group: 'stax', module: 'stax-api'
+ exclude group: 'xpp3', module: 'xpp3'
+ }
+}
+
+apply from: '../scripts/android-release-aar.gradle'
\ No newline at end of file
diff --git a/client/pom.xml b/client/pom.xml
deleted file mode 100644
index 9d044551..00000000
--- a/client/pom.xml
+++ /dev/null
@@ -1,101 +0,0 @@
-
-
-
-
- 4.0.0
-
-
- js-android-sdk-aggregator
- com.jaspersoft.android.sdk
- 1.8
-
-
- js-android-sdk-client
- js-android-sdk-client
- 1.8
-
-
-
-
- com.google.android
- android
-
-
- org.springframework.android
- spring-android-rest-template
-
-
- com.octo.android.robospice
- robospice
-
-
- com.octo.android.robospice
- robospice-spring-android
-
-
-
- org.simpleframework
- simple-xml
-
-
-
- stax
- stax
-
-
- stax-api
- stax
-
-
-
- xpp3
- xpp3
-
-
-
-
-
- junit
- junit
-
-
- org.mockito
- mockito-all
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
-
-
-
-
-
\ No newline at end of file
diff --git a/client/src/androidTest/AndroidManifest.xml b/client/src/androidTest/AndroidManifest.xml
new file mode 100644
index 00000000..9813f103
--- /dev/null
+++ b/client/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
diff --git a/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/CheckReportStatusRequestTest.java b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/CheckReportStatusRequestTest.java
new file mode 100644
index 00000000..f09fdaf3
--- /dev/null
+++ b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/CheckReportStatusRequestTest.java
@@ -0,0 +1,35 @@
+package com.jaspersoft.android.sdk.integration;
+
+import com.jaspersoft.android.sdk.client.async.request.CheckReportStatusRequest;
+import com.jaspersoft.android.sdk.client.async.request.RunReportExecutionRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportExecutionRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportExecutionResponse;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportStatusResponse;
+import com.jaspersoft.android.sdk.integration.utils.ProtoInstrumentation;
+import com.jaspersoft.android.sdk.integration.utils.SampleData;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class CheckReportStatusRequestTest extends ProtoInstrumentation {
+
+ private RunReportExecutionRequest runReportExecutionRequest;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ ReportExecutionRequest reportExecutionRequest = SampleData.getSampleExecutionData(getJsRestClient(), RESOURCE_URI);
+ runReportExecutionRequest = new RunReportExecutionRequest(getJsRestClient(), reportExecutionRequest);
+ }
+
+ public void test_requestReportStatus() throws Exception {
+ ReportExecutionResponse runReportExecutionResponse = runReportExecutionRequest.loadDataFromNetwork();
+ String requestId = runReportExecutionResponse.getRequestId();
+
+ CheckReportStatusRequest checkReportStatusRequest = new CheckReportStatusRequest(getJsRestClient(), requestId);
+ ReportStatusResponse response = checkReportStatusRequest.loadDataFromNetwork();
+ assertFalse(response.getStatus() == null);
+ }
+
+}
diff --git a/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/GetRootFolderDataRequestTest.java b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/GetRootFolderDataRequestTest.java
new file mode 100644
index 00000000..adb90921
--- /dev/null
+++ b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/GetRootFolderDataRequestTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
+ * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
+ * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
+ * Vestibulum commodo. Ut rhoncus gravida arcu.
+ */
+
+package com.jaspersoft.android.sdk.integration;
+
+import com.jaspersoft.android.sdk.client.async.request.GetRootFolderDataRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.FolderDataResponse;
+import com.jaspersoft.android.sdk.integration.utils.ProtoInstrumentation;
+
+public class GetRootFolderDataRequestTest extends ProtoInstrumentation {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void test_getRootFolderUriMethod() throws Exception {
+ GetRootFolderDataRequest request = new GetRootFolderDataRequest(getJsRestClient());
+ FolderDataResponse response = request.loadDataFromNetwork();
+ assertTrue(response.getUri().equals("/"));
+ }
+}
diff --git a/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/ReportDetailsRequestTest.java b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/ReportDetailsRequestTest.java
new file mode 100644
index 00000000..67b35f5d
--- /dev/null
+++ b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/ReportDetailsRequestTest.java
@@ -0,0 +1,34 @@
+package com.jaspersoft.android.sdk.integration;
+
+import com.jaspersoft.android.sdk.client.async.request.ReportDetailsRequest;
+import com.jaspersoft.android.sdk.client.async.request.RunReportExecutionRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportExecutionRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportExecutionResponse;
+import com.jaspersoft.android.sdk.integration.utils.ProtoInstrumentation;
+import com.jaspersoft.android.sdk.integration.utils.SampleData;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class ReportDetailsRequestTest extends ProtoInstrumentation {
+
+ private RunReportExecutionRequest runReportExecutionRequest;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ ReportExecutionRequest reportExecutionRequest = SampleData.getSampleExecutionData(getJsRestClient(), RESOURCE_URI);
+ runReportExecutionRequest = new RunReportExecutionRequest(getJsRestClient(), reportExecutionRequest);
+ }
+
+ public void test_requestReportDetails() throws Exception {
+ ReportExecutionResponse runReportExecutionResponse = runReportExecutionRequest.loadDataFromNetwork();
+ String requestId = runReportExecutionResponse.getRequestId();
+
+ ReportDetailsRequest reportDetailsRequest = new ReportDetailsRequest(getJsRestClient(), requestId);
+ ReportExecutionResponse response = reportDetailsRequest.loadDataFromNetwork();
+ assertFalse(response == null);
+ }
+
+}
diff --git a/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/RunReportExportsRequestTest.java b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/RunReportExportsRequestTest.java
new file mode 100644
index 00000000..36008b71
--- /dev/null
+++ b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/RunReportExportsRequestTest.java
@@ -0,0 +1,54 @@
+package com.jaspersoft.android.sdk.integration;
+
+import android.test.suitebuilder.annotation.LargeTest;
+
+import com.jaspersoft.android.sdk.client.async.request.RunReportExecutionRequest;
+import com.jaspersoft.android.sdk.client.async.request.RunReportExportOutputRequest;
+import com.jaspersoft.android.sdk.client.async.request.RunReportExportsRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.ExportExecution;
+import com.jaspersoft.android.sdk.client.oxm.report.ExportsRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportDataResponse;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportExecutionRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportExecutionResponse;
+import com.jaspersoft.android.sdk.integration.utils.ProtoInstrumentation;
+import com.jaspersoft.android.sdk.integration.utils.SampleData;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+@LargeTest
+public class RunReportExportsRequestTest extends ProtoInstrumentation {
+
+ private RunReportExecutionRequest runReportExecutionRequest;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ ReportExecutionRequest reportExecutionRequest = SampleData.getSampleExecutionData(getJsRestClient(), RESOURCE_URI);
+ runReportExecutionRequest = new RunReportExecutionRequest(getJsRestClient(), reportExecutionRequest);
+ }
+
+ public void test_requestForExportsOnReport() throws Exception {
+ ReportExecutionResponse runReportExecutionResponse = runReportExecutionRequest.loadDataFromNetwork();
+ String requestId = runReportExecutionResponse.getRequestId();
+
+ ExportsRequest exr = new ExportsRequest();
+// exr.configureExecutionForProfile(getJsRestClient());
+ exr.setMarkupType(ReportExecutionRequest.MARKUP_TYPE_EMBEDDABLE);
+ exr.setAllowInlineScripts(false);
+ exr.setOutputFormat("html");
+ exr.setPages("1");
+
+ RunReportExportsRequest runReportExportsRequest = new RunReportExportsRequest(getJsRestClient(), exr, requestId);
+ ExportExecution runReportExportsResponse = runReportExportsRequest.loadDataFromNetwork();
+ assertFalse(runReportExportsResponse == null);
+
+ String executionId = runReportExportsResponse.getId();
+ RunReportExportOutputRequest runReportExportOutputRequest
+ = new RunReportExportOutputRequest(getJsRestClient(), requestId, executionId);
+ ReportDataResponse response = runReportExportOutputRequest.loadDataFromNetwork();
+ assertFalse(response == null);
+ }
+
+}
diff --git a/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/utils/ProtoInstrumentation.java b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/utils/ProtoInstrumentation.java
new file mode 100644
index 00000000..53b5ec98
--- /dev/null
+++ b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/utils/ProtoInstrumentation.java
@@ -0,0 +1,54 @@
+package com.jaspersoft.android.sdk.integration.utils;
+
+import android.test.InstrumentationTestCase;
+
+import com.jaspersoft.android.sdk.client.JsRestClient;
+import com.jaspersoft.android.sdk.client.JsServerProfile;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public abstract class ProtoInstrumentation extends InstrumentationTestCase {
+
+ private static final String DEFAULT_ALIAS = "Mobile Demo";
+ private static final String DEFAULT_ORGANIZATION = "organization_1";
+ private static final String DEFAULT_SERVER_URL = "http://mobiledemo.jaspersoft.com/jasperserver-pro";
+ private static final String DEFAULT_USERNAME = "phoneuser";
+ private static final String DEFAULT_PASS = "phoneuser";
+
+ public static final String RESOURCE_URI = "/Reports/1._Geographic_Results_by_Segment_Report";
+
+ private JsServerProfile testProfile;
+ private JsRestClient jsRestClient;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ testProfile = new JsServerProfile();
+ testProfile.setAlias(DEFAULT_ALIAS);
+ testProfile.setServerUrl(DEFAULT_SERVER_URL);
+ testProfile.setOrganization(DEFAULT_ORGANIZATION);
+ testProfile.setUsername(DEFAULT_USERNAME);
+ testProfile.setPassword(DEFAULT_PASS);
+
+ jsRestClient = new JsRestClient();
+ jsRestClient.setServerProfile(testProfile);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ testProfile = null;
+ jsRestClient = null;
+ }
+
+ public JsServerProfile getTestProfile() {
+ return testProfile;
+ }
+
+ public JsRestClient getJsRestClient() {
+ return jsRestClient;
+ }
+
+}
diff --git a/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/utils/SampleData.java b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/utils/SampleData.java
new file mode 100644
index 00000000..1e89244c
--- /dev/null
+++ b/client/src/androidTest/java/com/jaspersoft/android/sdk/integration/utils/SampleData.java
@@ -0,0 +1,39 @@
+package com.jaspersoft.android.sdk.integration.utils;
+
+import com.jaspersoft.android.sdk.client.JsRestClient;
+import com.jaspersoft.android.sdk.client.JsServerProfile;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportExecutionRequest;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class SampleData {
+ private static final String ATTACHMENT_PREFIX_5_6 = "/reportExecutions/{reportExecutionId}/exports/{exportExecutionId}/attachments/";
+ private static final String ATTACHMENT_PREFIX_5_0 = "/reportExecutions/{reportExecutionId}/exports/{exportOptions}/attachments/";
+
+ private SampleData() {}
+
+ public static ReportExecutionRequest getSampleExecutionData(JsRestClient jsRestClient, String resourceUri) {
+ ReportExecutionRequest reportExecutionRequest = new ReportExecutionRequest();
+
+ String prefix = ATTACHMENT_PREFIX_5_6;
+ JsServerProfile jsServerProfile = jsRestClient.getServerProfile();
+ String serverUrl = jsServerProfile.getServerUrl();
+ String attachmentsPrefix = (jsServerProfile.getServerUrl() + JsRestClient.REST_SERVICES_V2_URI + prefix);
+ reportExecutionRequest.setAttachmentsPrefix(attachmentsPrefix);
+ reportExecutionRequest.setBaseUrl(serverUrl);
+
+ reportExecutionRequest.setReportUnitUri(resourceUri);
+ reportExecutionRequest.setMarkupType(ReportExecutionRequest.MARKUP_TYPE_EMBEDDABLE);
+ reportExecutionRequest.setOutputFormat("HTML");
+ reportExecutionRequest.setPages("1");
+ reportExecutionRequest.setAsync(true);
+ reportExecutionRequest.setInteractive(true);
+ reportExecutionRequest.setFreshData(false);
+ reportExecutionRequest.setSaveDataSnapshot(false);
+ reportExecutionRequest.setAllowInlineScripts(false);
+ return reportExecutionRequest;
+ }
+
+}
diff --git a/client/src/main/AndroidManifest.xml b/client/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..e5494232
--- /dev/null
+++ b/client/src/main/AndroidManifest.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/JsRestClient.java b/client/src/main/java/com/jaspersoft/android/sdk/client/JsRestClient.java
index 49dcb672..fe448789 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/JsRestClient.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/JsRestClient.java
@@ -24,21 +24,49 @@
package com.jaspersoft.android.sdk.client;
-import android.util.Base64;
-import com.jaspersoft.android.sdk.client.oxm.*;
+import com.jaspersoft.android.sdk.client.oxm.ReportDescriptor;
+import com.jaspersoft.android.sdk.client.oxm.ResourceDescriptor;
+import com.jaspersoft.android.sdk.client.oxm.ResourceParameter;
+import com.jaspersoft.android.sdk.client.oxm.ResourceProperty;
+import com.jaspersoft.android.sdk.client.oxm.ResourcesList;
import com.jaspersoft.android.sdk.client.oxm.control.InputControl;
import com.jaspersoft.android.sdk.client.oxm.control.InputControlState;
import com.jaspersoft.android.sdk.client.oxm.control.InputControlStatesList;
import com.jaspersoft.android.sdk.client.oxm.control.InputControlsList;
-import com.jaspersoft.android.sdk.client.oxm.report.*;
+import com.jaspersoft.android.sdk.client.oxm.report.ExportExecution;
+import com.jaspersoft.android.sdk.client.oxm.report.ExportsRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.FolderDataResponse;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportDataResponse;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportExecutionRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportExecutionResponse;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportParameter;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportParametersList;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportStatusResponse;
+import com.jaspersoft.android.sdk.client.oxm.resource.ResourceLookupSearchCriteria;
import com.jaspersoft.android.sdk.client.oxm.resource.ResourceLookupsList;
import com.jaspersoft.android.sdk.client.oxm.server.ServerInfo;
-import org.springframework.http.*;
+import com.jaspersoft.android.sdk.util.CookieHttpRequestInterceptor;
+import com.jaspersoft.android.sdk.util.KeepAliveHttpRequestInterceptor;
+import com.jaspersoft.android.sdk.util.LocalesHttpRequestInterceptor;
+import com.jaspersoft.android.sdk.util.StaticCacheHelper;
+
+import org.simpleframework.xml.Serializer;
+import org.simpleframework.xml.convert.AnnotationStrategy;
+import org.simpleframework.xml.core.Persister;
+import org.simpleframework.xml.strategy.Strategy;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequest;
-import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.http.converter.xml.SimpleXmlHttpMessageConverter;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.ResourceAccessException;
@@ -50,7 +78,9 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
-import java.net.*;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -75,21 +105,44 @@ public class JsRestClient {
public static final String REST_INPUT_CONTROLS_URI = "/inputControls";
public static final String REST_VALUES_URI = "/values";
public static final String REST_SERVER_INFO_URI = "/serverInfo";
- public static final String REST_REPORT_EXECUTIONS= "/reportExecutions";
+ public static final String REST_REPORT_EXECUTIONS = "/reportExecutions";
+ public static final String REST_REPORT_EXPORTS = "/exports";
+ public static final String REST_REPORT_STATUS = "/status";
+ public static final String REST_THUMBNAILS = "/thumbnails";
+
+ private SimpleXmlHttpMessageConverter simpleXmlHttpMessageConverter;
// the timeout in milliseconds until a connection is established
private int connectTimeout = 15 * 1000;
// the socket timeout in milliseconds for waiting for data
private int readTimeout = 120 * 1000;
- private RestTemplate restTemplate;
private JsServerProfile jsServerProfile;
private String restServicesUrl;
private ServerInfo serverInfo;
+ private final RestTemplate restTemplate;
+ private final SimpleClientHttpRequestFactory requestFactory;
+
+ //---------------------------------------------------------------------
+ // Constructors
+ //---------------------------------------------------------------------
public JsRestClient() {
- this.restTemplate = new RestTemplate(true);
+ this(new RestTemplate(true), new SimpleClientHttpRequestFactory());
+ }
+
+ public JsRestClient(RestTemplate restTemplate) {
+ this(restTemplate, new SimpleClientHttpRequestFactory());
+ }
+
+ public JsRestClient(RestTemplate restTemplate,
+ SimpleClientHttpRequestFactory factory) {
+ this.restTemplate = restTemplate;
+ this.requestFactory = factory;
+
+ fetchXmlConverter();
+ configureAnnotationStrategy();
}
//---------------------------------------------------------------------
@@ -100,7 +153,6 @@ public JsRestClient() {
* Set the underlying URLConnection's connect timeout. A timeout value of 0 specifies an infinite timeout.
*
* @param timeout the timeout value in milliseconds
- *
* @since 1.5
*/
public void setConnectTimeout(int timeout) {
@@ -110,8 +162,8 @@ public void setConnectTimeout(int timeout) {
/**
* Set the underlying URLConnection's read timeout. A timeout value of 0 specifies an infinite timeout.
- * @param timeout the timeout value in milliseconds
*
+ * @param timeout the timeout value in milliseconds
* @since 1.5
*/
public void setReadTimeout(int timeout) {
@@ -130,22 +182,20 @@ public JsServerProfile getServerProfile() {
public void setServerProfile(final JsServerProfile serverProfile) {
this.serverInfo = null;
this.jsServerProfile = serverProfile;
- this.restServicesUrl = serverProfile.getServerUrl() + REST_SERVICES_URI;
-
- ClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory() {
- @Override
- protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
- super.prepareConnection(connection, httpMethod);
- // Basic Authentication
- String authorisation = serverProfile.getUsernameWithOrgId() + ":" + serverProfile.getPassword();
- byte[] encodedAuthorisation = Base64.encode(authorisation.getBytes(), Base64.NO_WRAP);
- connection.setRequestProperty("Authorization", "Basic " + new String(encodedAuthorisation));
- // disable buggy keep-alive
- connection.setRequestProperty("Connection", "close");
- }
- };
- restTemplate.setRequestFactory(factory);
- updateRequestFactoryTimeouts();
+
+ // We allow user to set profile to null value
+ if (jsServerProfile != null) {
+ this.restServicesUrl = serverProfile.getServerUrl() + REST_SERVICES_URI;
+
+ updateRequestFactoryTimeouts();
+ restTemplate.setRequestFactory(requestFactory);
+
+ List interceptors = new ArrayList();
+ interceptors.add(new LocalesHttpRequestInterceptor());
+ interceptors.add(new CookieHttpRequestInterceptor(jsServerProfile));
+ interceptors.add(new KeepAliveHttpRequestInterceptor());
+ restTemplate.setInterceptors(interceptors);
+ }
}
/**
@@ -153,7 +203,6 @@ protected void prepareConnection(HttpURLConnection connection, String httpMethod
*
* @return the ServerInfo value
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.4
*/
public ServerInfo getServerInfo() throws RestClientException {
@@ -166,11 +215,10 @@ public ServerInfo getServerInfo() throws RestClientException {
* @param forceUpdate set to true
to force update of the server info
* @return the ServerInfo value
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.4
*/
public ServerInfo getServerInfo(boolean forceUpdate) throws RestClientException {
- if(forceUpdate || serverInfo == null) {
+ if (forceUpdate || serverInfo == null) {
String uri = getServerProfile().getServerUrl() + REST_SERVICES_V2_URI + REST_SERVER_INFO_URI;
try {
serverInfo = restTemplate.getForObject(uri, ServerInfo.class);
@@ -408,24 +456,70 @@ public ResourceLookupsList getResourceLookups(String folderUri, boolean recursiv
*/
public ResourceLookupsList getResourceLookups(String folderUri, String query, List types, boolean recursive,
int offset, int limit) throws RestClientException {
+ return getResourceLookups(folderUri, query, types, null, recursive, offset, limit);
+ }
+
+ /**
+ * Retrieves the list of resource lookup objects for the resources contained in the given parent folder
+ * and matching the specified parameters.
+ *
+ * @param folderUri parent folder URI (e.g. /reports/samples/)
+ * @param query Match only resources having the specified text in the name or description.
+ * (can be null
)
+ * @param types Match only resources of the given types. Multiple resource types allowed.
+ * (can be null
)
+ * @param sortBy Represents a field in the results to sort by: uri, label, description, type, creationDate,
+ * updateDate, accessTime, or popularity (based on access events).
+ * (can be null
)
+ * @param recursive Get resources recursively
+ * @param offset Pagination. Start index for requested page.
+ * @param limit Pagination. Resources count per page.
+ * @return the ResourceLookupsList value
+ * @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
+ */
+ public ResourceLookupsList getResourceLookups(String folderUri, String query, List types, String sortBy, boolean recursive,
+ int offset, int limit) throws RestClientException {
+ ResourceLookupSearchCriteria criteria = new ResourceLookupSearchCriteria();
+ criteria.setFolderUri(folderUri);
+ criteria.setQuery(query);
+ criteria.setTypes(types);
+ criteria.setSortBy(sortBy);
+ criteria.setRecursive(recursive);
+ criteria.setOffset(offset);
+ criteria.setLimit(limit);
+ return getResourceLookups(criteria);
+ }
+
+ /**
+ * Retrieves the list of resource lookup objects matching the specified search criteria.
+ *
+ * @param searchCriteria the search criteria
+ * @return the ResourceLookupsList value
+ * @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
+ */
+ public ResourceLookupsList getResourceLookups(ResourceLookupSearchCriteria searchCriteria) throws RestClientException {
StringBuilder fullUri = new StringBuilder();
fullUri.append(getServerProfile().getServerUrl())
.append(REST_SERVICES_V2_URI)
.append(REST_RESOURCES_URI)
.append("?folderUri={folderUri}")
.append("&q={query}")
+ .append("&sortBy={sortBy}")
.append("&recursive={recursive}")
+ .append("&forceFullPage={forceFullPage}")
.append("&offset={offset}")
.append("&limit={limit}");
- if (types != null) {
- for (String type : types) {
+ if (searchCriteria.getTypes() != null) {
+ for (String type : searchCriteria.getTypes()) {
fullUri.append("&type=").append(type);
}
}
ResponseEntity responseEntity = restTemplate.exchange(fullUri.toString(), HttpMethod.GET,
- null, ResourceLookupsList.class, folderUri, query, recursive, offset, limit);
+ null, ResourceLookupsList.class, searchCriteria.getFolderUri(), searchCriteria.getQuery(),
+ searchCriteria.getSortBy(), searchCriteria.isRecursive(), searchCriteria.isForceFullPage(),
+ searchCriteria.getOffset(), searchCriteria.getLimit());
if (responseEntity.getStatusCode() == HttpStatus.NO_CONTENT) {
return new ResourceLookupsList();
@@ -433,10 +527,28 @@ public ResourceLookupsList getResourceLookups(String folderUri, String query, Li
ResourceLookupsList resourceLookupsList = responseEntity.getBody();
resourceLookupsList.setResultCount(responseEntity.getHeaders().getFirst("Result-Count"));
resourceLookupsList.setTotalCount(responseEntity.getHeaders().getFirst("Total-Count"));
+ resourceLookupsList.setStartIndex(responseEntity.getHeaders().getFirst("Start-Index"));
+ resourceLookupsList.setNextOffset(responseEntity.getHeaders().getFirst("Next-Offset"));
return resourceLookupsList;
}
}
+ /**
+ * Retrives all data for the root folder
+ */
+ public FolderDataResponse getRootFolderData() {
+ String fullUri = jsServerProfile.getServerUrl() + REST_SERVICES_V2_URI + REST_RESOURCES_URI;
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("Accept", "application/repository.folder+xml");
+ headers.add("Content-Type", "application/xml");
+ HttpEntity httpEntity = new HttpEntity("", headers);
+
+ ResponseEntity responseEntity = restTemplate.exchange(fullUri,
+ HttpMethod.GET, httpEntity, FolderDataResponse.class);
+
+ return responseEntity.getBody();
+ }
+
//---------------------------------------------------------------------
// The Report Service
//---------------------------------------------------------------------
@@ -446,8 +558,8 @@ public ResourceLookupsList getResourceLookups(String folderUri, String query, Li
* with the ID of the saved output for downloading later with a GET request.
*
* @param resourceDescriptor resource descriptor of this report
- * @param format The format of the report output. Possible values: PDF, HTML, XLS, RTF, CSV,
- * XML, JRPRINT. The Default is PDF.
+ * @param format The format of the report output. Possible values: PDF, HTML, XLS, RTF, CSV,
+ * XML, JRPRINT. The Default is PDF.
* @return ReportDescriptor
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
*/
@@ -503,10 +615,9 @@ public void saveReportAttachmentToFile(String uuid, String name, File file) thro
/**
* Generates the fully qualified report URL to receive all pages report output in HTML format.
*
- * @param reportUri repository URI of the report
+ * @param reportUri repository URI of the report
* @param parameters list of report parameter/input control values
* @return the fully qualified report URL
- *
* @since 1.4
*/
public String generateReportUrl(String reportUri, List parameters) {
@@ -516,11 +627,10 @@ public String generateReportUrl(String reportUri, List paramete
/**
* Generates the fully qualified report URL to receive all pages report output in specified format.
*
- * @param reportUri repository URI of the report
+ * @param reportUri repository URI of the report
* @param parameters list of report parameter/input control values
- * @param format the format of the report output. Possible values: PDF, HTML, XLS, RTF, CSV, XML.
+ * @param format the format of the report output. Possible values: PDF, HTML, XLS, RTF, CSV, XML.
* @return the fully qualified report URL
- *
* @since 1.4
*/
public String generateReportUrl(String reportUri, List parameters, String format) {
@@ -531,12 +641,11 @@ public String generateReportUrl(String reportUri, List paramete
* Generates the fully qualified report URL according to specified parameters. The new v2/reports service allows clients
* to receive report output in a single request-response using this url.
*
- * @param reportUri repository URI of the report
+ * @param reportUri repository URI of the report
* @param parameters list of report parameter/input control values
- * @param page a positive integer value used to output a specific page or 0 to output all pages
- * @param format the format of the report output. Possible values: PDF, HTML, XLS, RTF, CSV, XML.
+ * @param page a positive integer value used to output a specific page or 0 to output all pages
+ * @param format the format of the report output. Possible values: PDF, HTML, XLS, RTF, CSV, XML.
* @return the fully qualified report URL
- *
* @since 1.4
*/
public String generateReportUrl(String reportUri, List parameters, int page, String format) {
@@ -545,9 +654,9 @@ public String generateReportUrl(String reportUri, List paramete
reportUrl.append(REST_REPORTS_URI).append(reportUri).append(".").append(format);
if (parameters == null) parameters = new ArrayList();
- if(page > 0) parameters.add(new ReportParameter("page", Integer.toString(page)));
+ if (page > 0) parameters.add(new ReportParameter("page", Integer.toString(page)));
- if (!parameters.isEmpty() ) {
+ if (!parameters.isEmpty()) {
reportUrl.append("?");
Iterator paramIterator = parameters.iterator();
while (paramIterator.hasNext()) {
@@ -557,7 +666,8 @@ public String generateReportUrl(String reportUri, List paramete
try {
String value = URLEncoder.encode(valueIterator.next(), "UTF-8");
reportUrl.append(parameter.getName()).append("=").append(value);
- if (paramIterator.hasNext() || valueIterator.hasNext() ) reportUrl.append("&");
+ if (paramIterator.hasNext() || valueIterator.hasNext())
+ reportUrl.append("&");
} catch (UnsupportedEncodingException ex) {
throw new IllegalArgumentException(ex);
}
@@ -571,9 +681,8 @@ public String generateReportUrl(String reportUri, List paramete
* Downloads report output, once it has been generated and saves it in the specified file.
*
* @param reportUrl the fully qualified report URL
- * @param file The file in which the output will be saved
+ * @param file The file in which the output will be saved
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.4
*/
public void saveReportOutputToFile(String reportUrl, File file) throws RestClientException {
@@ -591,38 +700,175 @@ public void saveReportOutputToFile(String reportUrl, File file) throws RestClien
// Report Execution Service
//---------------------------------------------------------------------
+ /**
+ * Forms and executes url "{server url}/rest_v2/reportExecutions"
+ *
+ * @param request we delegate to the restTemplate.
+ * @return report execution response. Includes executionId for later use.
+ * @throws RestClientException
+ */
public ReportExecutionResponse runReportExecution(ReportExecutionRequest request) throws RestClientException {
String url = jsServerProfile.getServerUrl() + REST_SERVICES_V2_URI + REST_REPORT_EXECUTIONS;
return restTemplate.postForObject(url, request, ReportExecutionResponse.class);
}
- public URI getExportOuptutResourceURI(String executionId, String exportOutput) {
- String outputResourceUri = "/{executionId}/exports/{exportOutput}/outputResource";
- String fullUri = jsServerProfile.getServerUrl() + REST_SERVICES_V2_URI + REST_REPORT_EXECUTIONS + outputResourceUri;
+ /**
+ * Sends request with porpose to fetch current export datum.
+ *
+ * @param executionId Identifies current id of running report.
+ * @param request we delegate to the restTemplate.
+ * @return response with all exports datum associated with request.
+ * @throws RestClientException
+ */
+ public ExportExecution runExportForReport(String executionId, ExportsRequest request) throws RestClientException {
+ return restTemplate.postForObject(getExportForReportURI(executionId), request, ExportExecution.class);
+ }
- UriTemplate uriTemplate = new UriTemplate(fullUri);
- return uriTemplate.expand(executionId, exportOutput);
+ /**
+ * Generates link for requesting data on specified export resource.
+ *
+ * @param executionId Identifies current id of running report.
+ * @return "{server url}/rest_v2/reportExecutions/{executionId}/exports"
+ */
+ public URI getExportForReportURI(String executionId) {
+ String outputResourceUri = "/{executionId}";
+ String fullUri = jsServerProfile.getServerUrl() +
+ REST_SERVICES_V2_URI + REST_REPORT_EXECUTIONS +
+ outputResourceUri + REST_REPORT_EXPORTS;
+
+ return new UriTemplate(fullUri).expand(executionId, executionId);
+ }
+
+ /**
+ * Sends request for the current running report for the status check.
+ *
+ * @param executionId Identifies current id of running report.
+ * @return response which expose current report status.
+ */
+ public ReportStatusResponse runReportStatusCheck(String executionId) {
+ return restTemplate.getForObject(getReportStatusCheckURI(executionId), ReportStatusResponse.class);
}
+ /**
+ * Generates link for requesting report execution status.
+ *
+ * @param executionId Identifies current id of running report.
+ * @return "{server url}/rest_v2/reportExecutions/{executionId}/status"
+ */
+ public URI getReportStatusCheckURI(String executionId) {
+ String outputResourceUri = "/{executionId}";
+
+ String fullUri = jsServerProfile.getServerUrl() +
+ REST_SERVICES_V2_URI + REST_REPORT_EXECUTIONS +
+ outputResourceUri + REST_REPORT_STATUS;
+
+ return new UriTemplate(fullUri).expand(executionId);
+ }
+
+ /**
+ * Saves resource ouput in file.
+ *
+ * @param executionId Identifies current id of running report.
+ * @param exportOutput Identifier which refers to current requested export.
+ * @param file The file in which the output will be saved
+ * @throws RestClientException
+ */
public void saveExportOutputToFile(String executionId, String exportOutput, File file) throws RestClientException {
- URI outputResourceUri = getExportOuptutResourceURI(executionId, exportOutput);
+ URI outputResourceUri = getExportOutputResourceURI(executionId, exportOutput);
downloadFile(outputResourceUri, file);
}
- public URI getExportAttachmentURI(String executionId, String exportOutput, String attachmentName) {
- String attachmentUri = "/{executionId}/exports/{exportOutput}/attachments/{attachment}";
- String fullUri = jsServerProfile.getServerUrl() + REST_SERVICES_V2_URI + REST_REPORT_EXECUTIONS + attachmentUri;
+ /**
+ * Load output data for export on current request.
+ *
+ * @param executionId Identifies current id of running report.
+ * @param exportOutput Identifier which refers to current requested export.
+ * @return Basically it will be 3 cases HTML/JSON/XML types.
+ */
+ public ReportDataResponse runExportOutputResource(String executionId, String exportOutput) {
+ ResponseEntity response = restTemplate.exchange(
+ getExportOutputResourceURI(executionId, exportOutput), HttpMethod.GET, null, String.class);
+
+ boolean isFinal;
+ boolean hasOutputFinal = response.getHeaders().containsKey("output-final");
+ String data = response.getBody();
+
+ if (hasOutputFinal) {
+ isFinal = Boolean.valueOf(response.getHeaders().getFirst("output-final"));
+ } else {
+ // "output-final" header is missing for JRS 5.5 and lower,
+ // so we consider request to be not final by default
+ isFinal = false;
+ }
+ return new ReportDataResponse(isFinal, data);
+ }
+
+ /**
+ * Generates link for requesting report output resource datum.
+ *
+ * @param executionId Identifies current id of running report.
+ * @param exportOutput Identifier which refers to current requested export.
+ * @return "{server url}/rest_v2/reportExecutions/{executionId}/exports/{exportOutput}/outputResource"
+ */
+ public URI getExportOutputResourceURI(String executionId, String exportOutput) {
+ String outputResourceUri = "/{executionId}/exports/{exportOutput}/outputResource";
+ String fullUri = jsServerProfile.getServerUrl() + REST_SERVICES_V2_URI + REST_REPORT_EXECUTIONS + outputResourceUri;
UriTemplate uriTemplate = new UriTemplate(fullUri);
- return uriTemplate.expand(executionId, exportOutput, attachmentName);
+ return uriTemplate.expand(executionId, exportOutput);
}
+ /**
+ * Save report in file with specified name.
+ *
+ * @param executionId Identifies current id of running report.
+ * @param exportOutput Identifier which refers to current requested export.
+ * @param attachmentName Name of attachment we store on JRS side.
+ * @param file The file in which the output will be saved
+ * @throws RestClientException
+ */
public void saveExportAttachmentToFile(String executionId, String exportOutput,
String attachmentName, File file) throws RestClientException {
URI attachmentUri = getExportAttachmentURI(executionId, exportOutput, attachmentName);
downloadFile(attachmentUri, file);
}
+ /**
+ * Generates link for requesting of report export attachemnt data.
+ *
+ * @param executionId Identifies current id of running report.
+ * @param exportOutput Identifier which refers to current requested export.
+ * @param attachmentName Name of attachment we store on JRS side.
+ * @return "{server url}/rest_v2/reportExecutions/{executionId}/exports/{exportOutput}/attachments/{attachment}"
+ */
+ public URI getExportAttachmentURI(String executionId, String exportOutput, String attachmentName) {
+ String attachmentUri = "/{executionId}/exports/{exportOutput}/attachments/{attachment}";
+ String fullUri = jsServerProfile.getServerUrl() + REST_SERVICES_V2_URI + REST_REPORT_EXECUTIONS + attachmentUri;
+ return new UriTemplate(fullUri).expand(executionId, exportOutput, attachmentName);
+ }
+
+ /**
+ * Sends request for retrieving report details data.
+ *
+ * @param executionId Identifies current id of running report.
+ * @return response which expose current report details.
+ */
+ public ReportExecutionResponse runReportDetailsRequest(String executionId) {
+ return restTemplate.getForObject(getReportDetailsURI(executionId), ReportExecutionResponse.class);
+ }
+
+ /**
+ * Generates link for requesting details on specified report.
+ *
+ * @param executionId Identifies current id of running report.
+ * @return "{server url}/rest_v2/reportExecutions/{executionId}"
+ */
+ public URI getReportDetailsURI(String executionId) {
+ String attachmentUri = "/{executionId}";
+ String fullUri = jsServerProfile.getServerUrl() + REST_SERVICES_V2_URI + REST_REPORT_EXECUTIONS + attachmentUri;
+ return new UriTemplate(fullUri).expand(executionId);
+ }
+
//---------------------------------------------------------------------
// Input Controls
//---------------------------------------------------------------------
@@ -631,9 +877,9 @@ public void saveExportAttachmentToFile(String executionId, String exportOutput,
* Gets the resource descriptor of a query-based input control that contains query data
* according to specified parameters.
*
- * @param uri repository URI of the input control
+ * @param uri repository URI of the input control
* @param datasourceUri repository URI of a datasource for the control
- * @param params parameters for the input control (can be null
)
+ * @param params parameters for the input control (can be null
)
* @return the ResourceDescriptor of a query-based input control that contains query data
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
*/
@@ -642,7 +888,7 @@ public ResourceDescriptor getInputControlWithQueryData(String uri, String dataso
fullUri.append(restServicesUrl).append(REST_RESOURCE_URI).append(uri);
fullUri.append("?IC_GET_QUERY_DATA=").append(datasourceUri);
if (params != null) {
- for(ResourceParameter parameter : params) {
+ for (ResourceParameter parameter : params) {
fullUri.append(parameter.isListItem() ? "&PL_" : "&P_");
fullUri.append(parameter.getName()).append("=").append(parameter.getValue());
}
@@ -653,9 +899,9 @@ public ResourceDescriptor getInputControlWithQueryData(String uri, String dataso
/**
* Gets the query data of a query-based input control, according to specified parameters.
*
- * @param uri repository URI of the input control
+ * @param uri repository URI of the input control
* @param datasourceUri repository URI of a datasource for the control
- * @param params parameters for the input control (can be null
)
+ * @param params parameters for the input control (can be null
)
* @return The query data as list of ResourceProperty objects
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
*/
@@ -673,8 +919,8 @@ public List getInputControlQueryData(String uri, String dataso
property.setName(queryDataRow.getValue());
//cols
StringBuilder value = new StringBuilder();
- for(ResourceProperty queryDataCol : queryDataRow.getProperties()) {
- if(ResourceDescriptor.PROP_QUERY_DATA_ROW_COLUMN.equals(queryDataCol.getName())) {
+ for (ResourceProperty queryDataCol : queryDataRow.getProperties()) {
+ if (ResourceDescriptor.PROP_QUERY_DATA_ROW_COLUMN.equals(queryDataCol.getName())) {
if (value.length() > 0) value.append(" | ");
value.append(queryDataCol.getValue());
}
@@ -697,7 +943,6 @@ public List getInputControlQueryData(String uri, String dataso
* @param reportUri repository URI of the report
* @return a list of input controls
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.6
*/
public List getInputControls(String reportUri) throws RestClientException {
@@ -708,12 +953,11 @@ public List getInputControls(String reportUri) throws RestClientEx
* Gets the list of input controls with specified IDs for the report with specified URI
* and according to selected values.
*
- * @param reportUri repository URI of the report
- * @param controlsIds list of input controls IDs
+ * @param reportUri repository URI of the report
+ * @param controlsIds list of input controls IDs
* @param selectedValues list of selected values
* @return a list of input controls
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.6
*/
public List getInputControls(String reportUri, List controlsIds,
@@ -727,7 +971,6 @@ public List getInputControls(String reportUri, List contro
* @param reportUri repository URI of the report
* @return the InputControlsList value
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.6
*/
public InputControlsList getInputControlsList(String reportUri) throws RestClientException {
@@ -738,16 +981,15 @@ public InputControlsList getInputControlsList(String reportUri) throws RestClien
* Gets the list of input controls with specified IDs for the report with specified URI
* and according to selected values.
*
- * @param reportUri repository URI of the report
- * @param controlsIds list of input controls IDs
+ * @param reportUri repository URI of the report
+ * @param controlsIds list of input controls IDs
* @param selectedValues list of selected values
* @return the InputControlsList value
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.6
*/
public InputControlsList getInputControlsList(String reportUri, List controlsIds,
- List selectedValues) throws RestClientException {
+ List selectedValues) throws RestClientException {
// generate full url
String url = generateInputControlsUrl(reportUri, controlsIds, false);
// add selected values to request
@@ -765,7 +1007,6 @@ public InputControlsList getInputControlsList(String reportUri, List con
* @param reportUri repository URI of the report
* @return the list of the input controls states
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.6
*/
public List getInputControlsValues(String reportUri) throws RestClientException {
@@ -776,16 +1017,15 @@ public List getInputControlsValues(String reportUri) throws R
* Gets the list of states of input controls with specified IDs for the report with specified URI
* and according to selected values.
*
- * @param reportUri repository URI of the report
- * @param controlsIds list of input controls IDs
+ * @param reportUri repository URI of the report
+ * @param controlsIds list of input controls IDs
* @param selectedValues list of selected values
* @return the list of the input controls states
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
- * @since 1.6
+ * @since 1.6
*/
public List getInputControlsValues(String reportUri, List controlsIds,
- List selectedValues) throws RestClientException {
+ List selectedValues) throws RestClientException {
return getInputControlsValuesList(reportUri, controlsIds, selectedValues).getInputControlStates();
}
@@ -795,7 +1035,6 @@ public List getInputControlsValues(String reportUri, List controlsIds,
- List selectedValues) throws RestClientException {
+ List selectedValues) throws RestClientException {
// generate full url
String url = generateInputControlsUrl(reportUri, controlsIds, true);
// add selected values to request
@@ -823,20 +1061,19 @@ public InputControlStatesList getInputControlsValuesList(String reportUri, List<
parametersList.setReportParameters(selectedValues);
// execute POST request
try {
- return restTemplate.postForObject(url, parametersList, InputControlStatesList.class);
+ return restTemplate.postForObject(url, parametersList, InputControlStatesList.class);
} catch (HttpMessageNotReadableException exception) {
- return new InputControlStatesList();
+ return new InputControlStatesList();
}
}
/**
* Validates the input controls values on the server side and returns states only for invalid controls.
*
- * @param reportUri repository URI of the report
+ * @param reportUri repository URI of the report
* @param inputControls list of input controls that should be validated
* @return the list of the input controls states
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.4
*/
public List validateInputControlsValues(String reportUri, List inputControls)
@@ -847,34 +1084,32 @@ public List validateInputControlsValues(String reportUri, Lis
/**
* Validates the input controls values on the server side and returns states only for invalid controls.
*
- * @param reportUri repository URI of the report
- * @param controlsIds list of input controls IDs that should be validated
+ * @param reportUri repository URI of the report
+ * @param controlsIds list of input controls IDs that should be validated
* @param selectedValues list of selected values for validation
* @return the list of the input controls states
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.6
*/
public List validateInputControlsValues(String reportUri, List controlsIds,
- List selectedValues) throws RestClientException {
+ List selectedValues) throws RestClientException {
return validateInputControlsValuesList(reportUri, controlsIds, selectedValues).getInputControlStates();
}
/**
* Validates the input controls values on the server side and returns states only for invalid controls.
*
- * @param reportUri repository URI of the report
+ * @param reportUri repository URI of the report
* @param inputControls list of input controls that should be validated
* @return the InputControlStatesList value
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.6
*/
public InputControlStatesList validateInputControlsValuesList(String reportUri, List inputControls)
throws RestClientException {
List controlsIds = new ArrayList();
List selectedValues = new ArrayList();
- for(InputControl control : inputControls) {
+ for (InputControl control : inputControls) {
controlsIds.add(control.getId());
selectedValues.add(new ReportParameter(control.getId(), control.getSelectedValues()));
}
@@ -885,27 +1120,59 @@ public InputControlStatesList validateInputControlsValuesList(String reportUri,
/**
* Validates the input controls values on the server side and returns states only for invalid controls.
*
- * @param reportUri repository URI of the report
- * @param controlsIds list of input controls IDs that should be validated
+ * @param reportUri repository URI of the report
+ * @param controlsIds list of input controls IDs that should be validated
* @param selectedValues list of selected values for validation
* @return the InputControlStatesList value
* @throws RestClientException thrown by RestTemplate whenever it encounters client-side HTTP errors
- *
* @since 1.6
*/
public InputControlStatesList validateInputControlsValuesList(String reportUri, List controlsIds,
- List selectedValues) throws RestClientException {
+ List selectedValues) throws RestClientException {
InputControlStatesList statesList = getInputControlsValuesList(reportUri, controlsIds, selectedValues);
// remove states without validation errors
Iterator iterator = statesList.getInputControlStates().iterator();
- while(iterator.hasNext()) {
- if(iterator.next().getError() == null) {
+ while (iterator.hasNext()) {
+ if (iterator.next().getError() == null) {
iterator.remove();
}
}
return statesList;
}
+ /**
+ * Method which flashes all stared cookies.
+ */
+ public static void flushCookies() {
+ StaticCacheHelper.clearCache();
+ }
+
+ //---------------------------------------------------------------------
+ // Thumbnails API
+ //---------------------------------------------------------------------
+
+ /**
+ * Returns thumbnail image or encoded image of the requested URI without placeholder
+ *
+ * @param resourceUri Uri of resource
+ * @return {serverUrl}/rest_v2/thumbnails/{resourceUri}?defaultAllowed=false
+ */
+ public String generateThumbNailUri(String resourceUri) {
+ return generateThumbNailUri(resourceUri, false);
+ }
+
+ /**
+ * Returns thumbnail image or encoded image of the requested URI
+ *
+ * @param resourceUri Uri of resource
+ * @param defaultAllowed If true, a placeholder thumbnail will be provided when no thumbnail is available (default: false)
+ * @return {serverUrl}/rest_v2/thumbnails/{resourceUri}?defaultAllowed={allowedFlag}
+ */
+ public String generateThumbNailUri(String resourceUri, boolean defaultAllowed) {
+ return jsServerProfile.getServerUrl() + REST_SERVICES_V2_URI + REST_THUMBNAILS
+ + resourceUri + "?defaultAllowed=" + Boolean.toString(defaultAllowed);
+ }
+
//---------------------------------------------------------------------
// Helper methods
//---------------------------------------------------------------------
@@ -940,13 +1207,11 @@ private void updateRequestFactoryTimeouts() {
}
private void updateConnectTimeout() {
- SimpleClientHttpRequestFactory factory = (SimpleClientHttpRequestFactory) getRestTemplate().getRequestFactory();
- factory.setConnectTimeout(connectTimeout);
+ requestFactory.setConnectTimeout(connectTimeout);
}
private void updateReadTimeout() {
- SimpleClientHttpRequestFactory factory = (SimpleClientHttpRequestFactory) getRestTemplate().getRequestFactory();
- factory.setReadTimeout(readTimeout);
+ requestFactory.setReadTimeout(readTimeout);
}
private String generateInputControlsUrl(String reportUri, List controlsIds, boolean valuesOnly) {
@@ -970,6 +1235,24 @@ private String generateInputControlsUrl(String reportUri, List controlsI
return fullUri.toString();
}
+ private void fetchXmlConverter() {
+ List> converters = restTemplate.getMessageConverters();
+ for (HttpMessageConverter> converter : converters) {
+ if (converter instanceof SimpleXmlHttpMessageConverter) {
+ simpleXmlHttpMessageConverter =
+ (SimpleXmlHttpMessageConverter) converter;
+ }
+ }
+ }
+
+ private void configureAnnotationStrategy() {
+ if (simpleXmlHttpMessageConverter != null) {
+ Strategy annotationStrategy = new AnnotationStrategy();
+ Serializer serializer = new Persister(annotationStrategy);
+ simpleXmlHttpMessageConverter.setSerializer(serializer);
+ }
+ }
+
//---------------------------------------------------------------------
// Getters & Setters
//---------------------------------------------------------------------
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/JsServerProfile.java b/client/src/main/java/com/jaspersoft/android/sdk/client/JsServerProfile.java
index a35d97b9..05a23e30 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/JsServerProfile.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/JsServerProfile.java
@@ -139,4 +139,31 @@ public void setPassword(String password) {
this.password = password;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ JsServerProfile that = (JsServerProfile) o;
+
+ if (!alias.equals(that.alias)) return false;
+ if (organization != null ? !organization.equals(that.organization) : that.organization != null)
+ return false;
+ if (!password.equals(that.password)) return false;
+ if (!serverUrl.equals(that.serverUrl)) return false;
+ if (!username.equals(that.username)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (int) (id ^ (id >>> 32));
+ result = 31 * result + alias.hashCode();
+ result = 31 * result + serverUrl.hashCode();
+ result = 31 * result + (organization != null ? organization.hashCode() : 0);
+ result = 31 * result + username.hashCode();
+ result = 31 * result + password.hashCode();
+ return result;
+ }
}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/async/JsAsyncTaskManager.java b/client/src/main/java/com/jaspersoft/android/sdk/client/async/JsAsyncTaskManager.java
index 2db9ab6d..94887031 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/async/JsAsyncTaskManager.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/async/JsAsyncTaskManager.java
@@ -32,6 +32,7 @@
import android.os.Build;
import android.util.Log;
import android.view.WindowManager;
+
import com.jaspersoft.android.sdk.client.async.task.JsAsyncTask;
import java.util.ArrayList;
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/async/JsXmlSpiceService.java b/client/src/main/java/com/jaspersoft/android/sdk/client/async/JsXmlSpiceService.java
index f1fb7340..38c243dc 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/async/JsXmlSpiceService.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/async/JsXmlSpiceService.java
@@ -25,10 +25,12 @@
package com.jaspersoft.android.sdk.client.async;
import android.app.Application;
+
import com.octo.android.robospice.SpiceService;
import com.octo.android.robospice.persistence.CacheManager;
import com.octo.android.robospice.persistence.exception.CacheCreationException;
import com.octo.android.robospice.persistence.springandroid.xml.SimpleSerializerObjectPersisterFactory;
+import com.octo.android.robospice.persistence.string.InFileStringObjectPersister;
/**
* This class offers a {@link SpiceService} dedicated to xml web services. Provides
@@ -42,6 +44,8 @@ public class JsXmlSpiceService extends SpiceService {
@Override
public CacheManager createCacheManager(Application application) throws CacheCreationException {
CacheManager cacheManager = new CacheManager();
+ // It is really important to keep proper persister order.
+ cacheManager.addPersister(new InFileStringObjectPersister(application));
cacheManager.addPersister(new SimpleSerializerObjectPersisterFactory(application));
return cacheManager;
}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/BaseRequest.java b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/BaseRequest.java
index f65055e7..e55fa8ef 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/BaseRequest.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/BaseRequest.java
@@ -27,6 +27,7 @@
import com.jaspersoft.android.sdk.client.JsRestClient;
import com.octo.android.robospice.request.SpiceRequest;
import com.octo.android.robospice.retry.DefaultRetryPolicy;
+
import roboguice.util.temp.Ln;
/**
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/CheckReportStatusRequest.java b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/CheckReportStatusRequest.java
new file mode 100644
index 00000000..1151c995
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/CheckReportStatusRequest.java
@@ -0,0 +1,41 @@
+package com.jaspersoft.android.sdk.client.async.request;
+
+import com.jaspersoft.android.sdk.client.JsRestClient;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportStatusResponse;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ *
+ * Check the status of export execution.
+ */
+public class CheckReportStatusRequest extends BaseRequest {
+ private String executionId;
+
+ /**
+ *
+ * @param jsRestClient Rest client. Encapsulates call logic
+ * @param executionId Current report identifier.
+ */
+ public CheckReportStatusRequest(JsRestClient jsRestClient, String executionId) {
+ super(jsRestClient, ReportStatusResponse.class);
+ this.executionId = executionId;
+ }
+
+ public CheckReportStatusRequest(JsRestClient jsRestClient) {
+ super(jsRestClient, ReportStatusResponse.class);
+ }
+
+ @Override
+ public ReportStatusResponse loadDataFromNetwork() throws Exception {
+ return getJsRestClient().runReportStatusCheck(executionId);
+ }
+
+ public String getExportExecutionId() {
+ return executionId;
+ }
+
+ public void setExportExecutionId(String exportExecutionId) {
+ this.executionId = exportExecutionId;
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/GetRootFolderDataRequest.java b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/GetRootFolderDataRequest.java
new file mode 100644
index 00000000..003bd697
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/GetRootFolderDataRequest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2014. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
+ * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
+ * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
+ * Vestibulum commodo. Ut rhoncus gravida arcu.
+ */
+
+package com.jaspersoft.android.sdk.client.async.request;
+
+import com.jaspersoft.android.sdk.client.JsRestClient;
+import com.jaspersoft.android.sdk.client.async.request.cacheable.CacheableRequest;
+import com.jaspersoft.android.sdk.client.oxm.report.FolderDataResponse;
+
+public class GetRootFolderDataRequest extends CacheableRequest {
+
+ public GetRootFolderDataRequest(JsRestClient jsRestClient) {
+ super(jsRestClient, FolderDataResponse.class);
+ }
+
+ @Override
+ public FolderDataResponse loadDataFromNetwork() throws Exception {
+ return getJsRestClient().getRootFolderData();
+ }
+
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/ReportDetailsRequest.java b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/ReportDetailsRequest.java
new file mode 100644
index 00000000..982e3c54
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/ReportDetailsRequest.java
@@ -0,0 +1,26 @@
+package com.jaspersoft.android.sdk.client.async.request;
+
+import com.jaspersoft.android.sdk.client.JsRestClient;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportExecutionResponse;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class ReportDetailsRequest extends BaseRequest {
+ private String executionId;
+
+ public ReportDetailsRequest(JsRestClient jsRestClient) {
+ super(jsRestClient, ReportExecutionResponse.class);
+ }
+
+ public ReportDetailsRequest(JsRestClient jsRestClient, String executionId) {
+ super(jsRestClient, ReportExecutionResponse.class);
+ this.executionId = executionId;
+ }
+
+ @Override
+ public ReportExecutionResponse loadDataFromNetwork() throws Exception {
+ return getJsRestClient().runReportDetailsRequest(executionId);
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/RunReportExportOutputRequest.java b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/RunReportExportOutputRequest.java
new file mode 100644
index 00000000..5a492681
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/RunReportExportOutputRequest.java
@@ -0,0 +1,44 @@
+package com.jaspersoft.android.sdk.client.async.request;
+
+import com.jaspersoft.android.sdk.client.JsRestClient;
+import com.jaspersoft.android.sdk.client.oxm.report.ReportDataResponse;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class RunReportExportOutputRequest extends BaseRequest {
+ private String requestId;
+ private String executionId;
+
+ public RunReportExportOutputRequest(JsRestClient jsRestClient) {
+ super(jsRestClient, ReportDataResponse.class);
+ }
+
+ public RunReportExportOutputRequest(JsRestClient jsRestClient, String requestId, String executionId) {
+ super(jsRestClient, ReportDataResponse.class);
+ this.requestId = requestId;
+ this.executionId = executionId;
+ }
+
+ @Override
+ public ReportDataResponse loadDataFromNetwork() throws Exception {
+ return getJsRestClient().runExportOutputResource(requestId, executionId);
+ }
+
+ public String getRequestId() {
+ return requestId;
+ }
+
+ public void setRequestId(String requestId) {
+ this.requestId = requestId;
+ }
+
+ public String getExecutionId() {
+ return executionId;
+ }
+
+ public void setExecutionId(String executionId) {
+ this.executionId = executionId;
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/RunReportExportsRequest.java b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/RunReportExportsRequest.java
new file mode 100644
index 00000000..f5171ecb
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/RunReportExportsRequest.java
@@ -0,0 +1,51 @@
+package com.jaspersoft.android.sdk.client.async.request;
+
+import com.jaspersoft.android.sdk.client.JsRestClient;
+import com.jaspersoft.android.sdk.client.oxm.report.ExportExecution;
+import com.jaspersoft.android.sdk.client.oxm.report.ExportsRequest;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class RunReportExportsRequest extends BaseRequest {
+
+ private ExportsRequest request;
+ private String executionId;
+
+ public RunReportExportsRequest(JsRestClient jsRestClient) {
+ super(jsRestClient, ExportExecution.class);
+ }
+
+ public RunReportExportsRequest(JsRestClient jsRestClient,
+ ExportsRequest request, String executionId) {
+ super(jsRestClient, ExportExecution.class);
+ this.request = request;
+ this.executionId = executionId;
+ }
+
+ @Override
+ public ExportExecution loadDataFromNetwork() throws Exception {
+ return getJsRestClient().runExportForReport(executionId, request);
+ }
+
+ //---------------------------------------------------------------------
+ // Getters & Setters
+ //---------------------------------------------------------------------
+
+ public ExportsRequest getRequest() {
+ return request;
+ }
+
+ public void setRequest(ExportsRequest request) {
+ this.request = request;
+ }
+
+ public String getExecutionId() {
+ return executionId;
+ }
+
+ public void setExecutionId(String executionId) {
+ this.executionId = executionId;
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/cacheable/GetResourceLookupsRequest.java b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/cacheable/GetResourceLookupsRequest.java
index 4e62f1a4..8b0e046c 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/cacheable/GetResourceLookupsRequest.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/async/request/cacheable/GetResourceLookupsRequest.java
@@ -25,6 +25,7 @@
package com.jaspersoft.android.sdk.client.async.request.cacheable;
import com.jaspersoft.android.sdk.client.JsRestClient;
+import com.jaspersoft.android.sdk.client.oxm.resource.ResourceLookupSearchCriteria;
import com.jaspersoft.android.sdk.client.oxm.resource.ResourceLookupsList;
import java.util.List;
@@ -38,12 +39,7 @@
*/
public class GetResourceLookupsRequest extends CacheableRequest {
- private String folderUri;
- private String query;
- private List types;
- private boolean recursive;
- private int offset;
- private int limit;
+ private ResourceLookupSearchCriteria searchCriteria;
/**
* Creates a new instance of {@link GetResourceLookupsRequest}.
@@ -84,53 +80,70 @@ public GetResourceLookupsRequest(JsRestClient jsRestClient, String folderUri, Li
*/
public GetResourceLookupsRequest(JsRestClient jsRestClient, String folderUri, String query, List types,
boolean recursive, int offset, int limit) {
+ this(jsRestClient, folderUri, query, types, null, recursive, offset, limit);
+ }
+
+ /**
+ * Creates a new instance of {@link GetResourceLookupsRequest}.
+ *
+ * @param folderUri parent folder URI (e.g. /reports/samples/)
+ * @param query Match only resources having the specified text in the name or description.
+ * (can be null
)
+ * @param types Match only resources of the given types. Multiple resource types allowed.
+ * (can be null
)
+ * @param sortBy Represents a field in the results to sort by: uri, label, description, type, creationDate,
+ * updateDate, accessTime, or popularity (based on access events).
+ * (can be null
)
+ * @param recursive Get resources recursively
+ * @param offset Pagination. Start index for requested page.
+ * @param limit Pagination. Resources count per page.
+ */
+ public GetResourceLookupsRequest(JsRestClient jsRestClient, String folderUri, String query, List types,
+ String sortBy, boolean recursive, int offset, int limit) {
super(jsRestClient, ResourceLookupsList.class);
- this.folderUri = folderUri;
- this.query = query;
- this.types = types;
- this.recursive = recursive;
- this.offset = offset;
- this.limit = limit;
+ searchCriteria = new ResourceLookupSearchCriteria();
+ searchCriteria.setFolderUri(folderUri);
+ searchCriteria.setQuery(query);
+ searchCriteria.setTypes(types);
+ searchCriteria.setSortBy(sortBy);
+ searchCriteria.setRecursive(recursive);
+ searchCriteria.setOffset(offset);
+ searchCriteria.setLimit(limit);
}
+ /**
+ * Creates a new instance of {@link GetResourceLookupsRequest}.
+ *
+ * @param searchCriteria the search criteria
+ */
+ public GetResourceLookupsRequest(JsRestClient jsRestClient, ResourceLookupSearchCriteria searchCriteria) {
+ super(jsRestClient, ResourceLookupsList.class);
+ this.searchCriteria = searchCriteria;
+ }
@Override
public ResourceLookupsList loadDataFromNetwork() throws Exception {
- return getJsRestClient().getResourceLookups(folderUri, query, types, recursive, offset, limit);
+ return getJsRestClient().getResourceLookups(searchCriteria);
}
@Override
protected String createCacheKeyString() {
- return super.createCacheKeyString() + folderUri + query + types + recursive + offset + limit;
+ return super.createCacheKeyString()
+ + searchCriteria.getFolderUri()
+ + searchCriteria.getQuery()
+ + searchCriteria.getTypes()
+ + searchCriteria.getSortBy()
+ + searchCriteria.isRecursive()
+ + searchCriteria.getOffset()
+ + searchCriteria.getLimit();
}
//---------------------------------------------------------------------
// Getters & Setters
//---------------------------------------------------------------------
-
- public String getFolderUri() {
- return folderUri;
- }
-
- public String getQuery() {
- return query;
- }
-
- public List getTypes() {
- return types;
- }
-
- public boolean isRecursive() {
- return recursive;
- }
-
- public int getOffset() {
- return offset;
- }
-
- public int getLimit() {
- return limit;
+ public ResourceLookupSearchCriteria getSearchCriteria() {
+ return searchCriteria;
}
}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/async/task/JsAsyncTask.java b/client/src/main/java/com/jaspersoft/android/sdk/client/async/task/JsAsyncTask.java
index 6c14cdb6..53fc8bf3 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/async/task/JsAsyncTask.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/async/task/JsAsyncTask.java
@@ -25,6 +25,7 @@
package com.jaspersoft.android.sdk.client.async.task;
import android.os.AsyncTask;
+
import com.jaspersoft.android.sdk.client.async.JsProgressTracker;
import java.util.Timer;
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/ic/InputControlWrapper.java b/client/src/main/java/com/jaspersoft/android/sdk/client/ic/InputControlWrapper.java
index 87dbbd7e..c010bb42 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/ic/InputControlWrapper.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/ic/InputControlWrapper.java
@@ -25,6 +25,7 @@
package com.jaspersoft.android.sdk.client.ic;
import android.view.View;
+
import com.jaspersoft.android.sdk.client.oxm.ResourceDescriptor;
import com.jaspersoft.android.sdk.client.oxm.ResourceParameter;
import com.jaspersoft.android.sdk.client.oxm.ResourceProperty;
@@ -41,6 +42,7 @@
* @version $Id$
* @since 1.0
*/
+@Deprecated
public class InputControlWrapper {
public static final String NULL_SUBSTITUTE = "~NULL~";
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/ResourceDescriptor.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/ResourceDescriptor.java
index 5983aff9..551536ad 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/ResourceDescriptor.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/ResourceDescriptor.java
@@ -22,6 +22,7 @@
package com.jaspersoft.android.sdk.client.oxm;
import android.util.Log;
+
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControl.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControl.java
index 235793c5..c7407174 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControl.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControl.java
@@ -27,8 +27,10 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.view.View;
+
import com.jaspersoft.android.sdk.client.oxm.control.validation.ValidationRule;
import com.jaspersoft.android.sdk.client.oxm.control.validation.ValidationRulesList;
+
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
@@ -50,6 +52,7 @@ public enum Type {
bool,
singleValueText,
singleValueNumber,
+ singleValueTime,
singleValueDate,
singleValueDatetime,
singleSelect,
@@ -155,6 +158,7 @@ public Set getSelectedValues() {
case bool:
case singleValueText:
case singleValueNumber:
+ case singleValueTime:
case singleValueDate:
case singleValueDatetime:
if (getState().getValue() != null) {
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControlOption.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControlOption.java
index 3edff252..b20e4233 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControlOption.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControlOption.java
@@ -26,6 +26,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControlState.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControlState.java
index b931eeb9..df029a05 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControlState.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/InputControlState.java
@@ -26,6 +26,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/DateTimeFormatValidationRule.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/DateTimeFormatValidationRule.java
index 6026beb4..66e4d4cd 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/DateTimeFormatValidationRule.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/DateTimeFormatValidationRule.java
@@ -25,6 +25,7 @@
package com.jaspersoft.android.sdk.client.oxm.control.validation;
import android.os.Parcel;
+
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/MandatoryValidationRule.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/MandatoryValidationRule.java
index f67e2325..a4f1a841 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/MandatoryValidationRule.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/MandatoryValidationRule.java
@@ -25,6 +25,7 @@
package com.jaspersoft.android.sdk.client.oxm.control.validation;
import android.os.Parcel;
+
import org.simpleframework.xml.Root;
/**
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/ValidationRule.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/ValidationRule.java
index 598a80a3..34b5d726 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/ValidationRule.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/ValidationRule.java
@@ -26,6 +26,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/ValidationRulesList.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/ValidationRulesList.java
index 82bbfeaa..0f407ca3 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/ValidationRulesList.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/control/validation/ValidationRulesList.java
@@ -26,6 +26,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.ElementListUnion;
import org.simpleframework.xml.Root;
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/converter/ReportStatusConverter.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/converter/ReportStatusConverter.java
new file mode 100644
index 00000000..baa74b47
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/converter/ReportStatusConverter.java
@@ -0,0 +1,23 @@
+package com.jaspersoft.android.sdk.client.oxm.converter;
+
+import com.jaspersoft.android.sdk.client.oxm.report.ReportStatusResponse;
+
+import org.simpleframework.xml.convert.Converter;
+import org.simpleframework.xml.stream.InputNode;
+import org.simpleframework.xml.stream.OutputNode;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class ReportStatusConverter implements Converter {
+ @Override
+ public ReportStatusResponse read(InputNode node) throws Exception {
+ return new ReportStatusResponse(node.getValue());
+ }
+
+ @Override
+ public void write(OutputNode node, ReportStatusResponse value) throws Exception {
+ // Do nothing
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ErrorDescriptor.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ErrorDescriptor.java
new file mode 100644
index 00000000..b2106631
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ErrorDescriptor.java
@@ -0,0 +1,49 @@
+package com.jaspersoft.android.sdk.client.oxm.report;
+
+import org.simpleframework.xml.Element;
+import org.simpleframework.xml.Root;
+import org.simpleframework.xml.Serializer;
+import org.simpleframework.xml.core.Persister;
+import org.springframework.web.client.HttpStatusCodeException;
+
+import java.io.StringWriter;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+@Root(strict = false)
+public class ErrorDescriptor {
+ @Element
+ private String errorCode;
+ @Element(required = false)
+ private String message;
+
+ public static ErrorDescriptor valueOf(HttpStatusCodeException exception) {
+ String response = exception.getResponseBodyAsString();
+ Serializer serializer = new Persister();
+ StringWriter stringWriter = new StringWriter();
+ stringWriter.append(response);
+ try {
+ return serializer.read(ErrorDescriptor.class, response);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ public void setErrorCode(String errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
\ No newline at end of file
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ExecutionRequest.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ExecutionRequest.java
new file mode 100644
index 00000000..b96dfc46
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ExecutionRequest.java
@@ -0,0 +1,172 @@
+package com.jaspersoft.android.sdk.client.oxm.report;
+
+import org.simpleframework.xml.Element;
+import org.simpleframework.xml.ElementList;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.List;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class ExecutionRequest {
+ public static final String DEFAULT_ATTACHMENT_PREFIX = "/reportExecutions/{reportExecutionId}/exports/{exportExecutionId}/attachments/";
+ public static final String MARKUP_TYPE_EMBEDDABLE = "embeddable";
+ public static final String MARKUP_TYPE_FULL = "full";
+
+ @Element(required=false)
+ protected String reportUnitUri;
+
+ @Element(required=false)
+ protected String markupType;
+
+ @Element(required=false)
+ protected String baseUrl;
+
+ @Element(required=false)
+ protected Boolean async;
+
+ @Element(required=false)
+ protected Boolean freshData;
+
+ @Element(required=false)
+ protected Boolean saveDataSnapshot;
+
+ @Element
+ protected String outputFormat;
+
+ @Element(required=false)
+ protected Boolean interactive;
+
+ @Element(required=false)
+ protected Boolean ignorePagination;
+
+ @Element(required=false)
+ protected Boolean allowInlineScripts;
+
+ @Element(required=false)
+ protected String pages;
+
+ @Element(required=false)
+ protected String attachmentsPrefix;
+
+ @ElementList(required=false)
+ protected List parameters;
+
+ public void setAttachmentsPrefix(String attachmentsPrefix) {
+ this.attachmentsPrefix = attachmentsPrefix;
+ }
+
+ public void setEscapedAttachmentsPrefix(String attachmentsPrefix) {
+ try {
+ this.attachmentsPrefix = URLEncoder.encode(attachmentsPrefix, "UTF-8");
+ } catch (UnsupportedEncodingException exception) {
+ this.attachmentsPrefix = attachmentsPrefix;
+ } catch (NullPointerException exception) {
+ this.attachmentsPrefix = attachmentsPrefix;
+ }
+ }
+
+ public String getAttachmentsPrefix() {
+ return attachmentsPrefix;
+ }
+
+ public String getReportUnitUri() {
+ return reportUnitUri;
+ }
+
+ public void setReportUnitUri(String reportUnitUri) {
+ this.reportUnitUri = reportUnitUri;
+ }
+
+ public boolean isAsync() {
+ return async;
+ }
+
+ public void setAsync(boolean async) {
+ this.async = async;
+ }
+
+ public boolean isFreshData() {
+ return freshData;
+ }
+
+ public void setFreshData(boolean freshData) {
+ this.freshData = freshData;
+ }
+
+ public boolean isSaveDataSnapshot() {
+ return saveDataSnapshot;
+ }
+
+ public void setSaveDataSnapshot(boolean saveDataSnapshot) {
+ this.saveDataSnapshot = saveDataSnapshot;
+ }
+
+ public String getOutputFormat() {
+ return outputFormat;
+ }
+
+ public void setOutputFormat(String outputFormat) {
+ this.outputFormat = outputFormat;
+ }
+
+ public boolean isInteractive() {
+ return interactive;
+ }
+
+ public void setInteractive(boolean interactive) {
+ this.interactive = interactive;
+ }
+
+ public boolean isIgnorePagination() {
+ return ignorePagination;
+ }
+
+ public void setIgnorePagination(boolean ignorePagination) {
+ this.ignorePagination = ignorePagination;
+ }
+
+ public String getPages() {
+ return pages;
+ }
+
+ public void setPages(String pages) {
+ this.pages = pages;
+ }
+
+ public List getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(List parameters) {
+ this.parameters = parameters;
+ }
+
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ public void setBaseUrl(String baseUrl) {
+ this.baseUrl = baseUrl;
+ }
+
+ public String getMarkupType() {
+ return markupType;
+ }
+
+ public void setMarkupType(String markupType) {
+ this.markupType = markupType;
+ }
+
+ public Boolean getAllowInlineScripts() {
+ return allowInlineScripts;
+ }
+
+ public void setAllowInlineScripts(Boolean allowInlineScripts) {
+ this.allowInlineScripts = allowInlineScripts;
+ }
+
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ExportExecution.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ExportExecution.java
index 9bb22818..c89299e5 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ExportExecution.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ExportExecution.java
@@ -44,7 +44,7 @@ public class ExportExecution {
@Element
private String status;
- @Element
+ @Element(required=false)
private ReportOutputResource outputResource;
@ElementList(empty=false, entry="attachment", required=false)
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ExportsRequest.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ExportsRequest.java
new file mode 100644
index 00000000..8801e530
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ExportsRequest.java
@@ -0,0 +1,11 @@
+package com.jaspersoft.android.sdk.client.oxm.report;
+
+import org.simpleframework.xml.Root;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+@Root(name="export")
+public class ExportsRequest extends ExecutionRequest {
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/FolderDataResponse.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/FolderDataResponse.java
new file mode 100644
index 00000000..86693034
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/FolderDataResponse.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
+ * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
+ * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
+ * Vestibulum commodo. Ut rhoncus gravida arcu.
+ */
+
+package com.jaspersoft.android.sdk.client.oxm.report;
+
+import com.jaspersoft.android.sdk.client.oxm.resource.ResourceLookup;
+
+import org.simpleframework.xml.Root;
+
+@Root(name = "folder")
+public class FolderDataResponse extends ResourceLookup {
+ public FolderDataResponse() {
+ this.resourceType = ResourceType.folder.toString();
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportDataResponse.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportDataResponse.java
new file mode 100644
index 00000000..11a11834
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportDataResponse.java
@@ -0,0 +1,23 @@
+package com.jaspersoft.android.sdk.client.oxm.report;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class ReportDataResponse {
+ private final boolean isFinal;
+ private final String data;
+
+ public ReportDataResponse(boolean isFinal, String data) {
+ this.isFinal = isFinal;
+ this.data = data;
+ }
+
+ public boolean isFinal() {
+ return isFinal;
+ }
+
+ public String getData() {
+ return data;
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportExecutionRequest.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportExecutionRequest.java
index 5694ec2f..600d31ed 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportExecutionRequest.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportExecutionRequest.java
@@ -24,137 +24,13 @@
package com.jaspersoft.android.sdk.client.oxm.report;
-import org.simpleframework.xml.Element;
-import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.List;
-
/**
* @author Ivan Gadzhega
* @since 1.8
*/
@Root
-public class ReportExecutionRequest {
-
- @Element
- private String reportUnitUri;
-
- @Element(required=false)
- private boolean async;
-
- @Element(required=false)
- private boolean freshData;
-
- @Element(required=false)
- private boolean saveDataSnapshot;
-
- @Element
- private String outputFormat;
-
- @Element(required=false)
- private boolean interactive;
-
- @Element(required=false)
- private boolean ignorePagination;
-
- @Element(required=false)
- private String pages;
-
- @Element(required=false)
- private String attachmentsPrefix;
-
- @ElementList(required=false)
- private List parameters;
-
-
- public void setAttachmentsPrefix(String attachmentsPrefix) {
- try {
- this.attachmentsPrefix = URLEncoder.encode(attachmentsPrefix, "UTF-8");
- } catch (UnsupportedEncodingException exception) {
- this.attachmentsPrefix = attachmentsPrefix;
- } catch (NullPointerException exception) {
- this.attachmentsPrefix = attachmentsPrefix;
- }
- }
-
- public String getAttachmentsPrefix() {
- return attachmentsPrefix;
- }
-
- public String getReportUnitUri() {
- return reportUnitUri;
- }
-
- public void setReportUnitUri(String reportUnitUri) {
- this.reportUnitUri = reportUnitUri;
- }
-
- public boolean isAsync() {
- return async;
- }
-
- public void setAsync(boolean async) {
- this.async = async;
- }
-
- public boolean isFreshData() {
- return freshData;
- }
-
- public void setFreshData(boolean freshData) {
- this.freshData = freshData;
- }
-
- public boolean isSaveDataSnapshot() {
- return saveDataSnapshot;
- }
-
- public void setSaveDataSnapshot(boolean saveDataSnapshot) {
- this.saveDataSnapshot = saveDataSnapshot;
- }
-
- public String getOutputFormat() {
- return outputFormat;
- }
-
- public void setOutputFormat(String outputFormat) {
- this.outputFormat = outputFormat;
- }
-
- public boolean isInteractive() {
- return interactive;
- }
-
- public void setInteractive(boolean interactive) {
- this.interactive = interactive;
- }
-
- public boolean isIgnorePagination() {
- return ignorePagination;
- }
-
- public void setIgnorePagination(boolean ignorePagination) {
- this.ignorePagination = ignorePagination;
- }
-
- public String getPages() {
- return pages;
- }
-
- public void setPages(String pages) {
- this.pages = pages;
- }
-
- public List getParameters() {
- return parameters;
- }
-
- public void setParameters(List parameters) {
- this.parameters = parameters;
- }
-
+public class ReportExecutionRequest extends ExecutionRequest {
}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportExecutionResponse.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportExecutionResponse.java
index 594d4feb..1e1ff44b 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportExecutionResponse.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportExecutionResponse.java
@@ -106,4 +106,7 @@ public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
+ public ReportStatus getReportStatus() {
+ return ReportStatus.valueOf(status.toUpperCase());
+ }
}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportParameter.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportParameter.java
index 8d80e9d1..ef16b0a3 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportParameter.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportParameter.java
@@ -26,6 +26,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.ElementList;
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportStatus.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportStatus.java
new file mode 100644
index 00000000..317d8385
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportStatus.java
@@ -0,0 +1,9 @@
+package com.jaspersoft.android.sdk.client.oxm.report;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public enum ReportStatus {
+ QUEUED, READY, FAILED, EXECUTION
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportStatusResponse.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportStatusResponse.java
new file mode 100644
index 00000000..33b7ed1d
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/report/ReportStatusResponse.java
@@ -0,0 +1,43 @@
+package com.jaspersoft.android.sdk.client.oxm.report;
+
+import com.jaspersoft.android.sdk.client.oxm.converter.ReportStatusConverter;
+
+import org.simpleframework.xml.Element;
+import org.simpleframework.xml.Root;
+import org.simpleframework.xml.convert.Convert;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+@Root(name = "status")
+@Convert(ReportStatusConverter.class)
+public class ReportStatusResponse {
+
+ @Element(required = false)
+ private String mStatus;
+
+ /**
+ * Otherwise, the framework cannot instantiate the class for deserialization.
+ *
+ * http://stackoverflow.com/questions/7470992/exception-with-simple-xml-framework-deserialization
+ */
+ public ReportStatusResponse() {
+ }
+
+ public ReportStatusResponse(String status) {
+ mStatus = status;
+ }
+
+ public ReportStatus getReportStatus() {
+ return ReportStatus.valueOf(mStatus.toUpperCase());
+ }
+
+ public String getStatus() {
+ return mStatus;
+ }
+
+ public void setStatus(String status) {
+ this.mStatus = status;
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookup.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookup.java
index f7a6e39b..196a0d8e 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookup.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 Jaspersoft Corporation. All rights reserved.
+ * Copyright (C) 2012-2014 Jaspersoft Corporation. All rights reserved.
* http://community.jaspersoft.com/project/mobile-sdk-android
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
@@ -24,6 +24,9 @@
package com.jaspersoft.android.sdk.client.oxm.resource;
+import android.os.Parcel;
+import android.os.Parcelable;
+
import org.simpleframework.xml.Element;
/**
@@ -32,25 +35,69 @@
* @author Ivan Gadzhega
* @since 1.7
*/
-public class ResourceLookup {
+public class ResourceLookup implements Parcelable {
@Element(required=false)
- private String label;
+ protected String label;
@Element(required=false)
- private String description;
- @Element
- private String uri;
+ protected String description;
@Element
- private String resourceType;
+ protected String uri;
+ @Element(required=false)
+ protected String resourceType;
@Element(required=false)
- private Integer version;
+ protected int version;
@Element(required=false)
- private Integer permissionMask;
+ protected int permissionMask;
@Element(required=false)
- private String creationDate;
+ protected String creationDate;
@Element(required=false)
- private String updateDate;
+ protected String updateDate;
+
+ public ResourceLookup() { }
+
+ //---------------------------------------------------------------------
+ // Parcelable
+ //---------------------------------------------------------------------
+
+ public ResourceLookup(Parcel source) {
+ this.label = source.readString();
+ this.description = source.readString();
+ this.uri = source.readString();
+ this.resourceType = source.readString();
+ this.creationDate = source.readString();
+ this.updateDate = source.readString();
+ this.version = source.readInt();
+ this.permissionMask = source.readInt();
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+ public ResourceLookup createFromParcel(Parcel source) {
+ return new ResourceLookup(source);
+ }
+
+ public ResourceLookup[] newArray(int size) {
+ return new ResourceLookup[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(label);
+ dest.writeString(description);
+ dest.writeString(uri);
+ dest.writeString(resourceType);
+ dest.writeString(creationDate);
+ dest.writeString(updateDate);
+ dest.writeInt(version);
+ dest.writeInt(permissionMask);
+ }
//---------------------------------------------------------------------
// Getters & Setters
@@ -96,19 +143,19 @@ public void setUri(String uri) {
this.uri = uri;
}
- public Integer getVersion() {
+ public int getVersion() {
return version;
}
- public void setVersion(Integer version) {
+ public void setVersion(int version) {
this.version = version;
}
- public Integer getPermissionMask() {
+ public int getPermissionMask() {
return permissionMask;
}
- public void setPermissionMask(Integer permissionMask) {
+ public void setPermissionMask(int permissionMask) {
this.permissionMask = permissionMask;
}
@@ -136,6 +183,7 @@ public enum ResourceType {
folder,
reportUnit,
dashboard,
+ legacyDashboard,
unknown
}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookupSearchCriteria.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookupSearchCriteria.java
new file mode 100644
index 00000000..7fc52460
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookupSearchCriteria.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2012-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.android.sdk.client.oxm.resource;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Ivan Gadzhega
+ * @since 2.0
+ */
+public class ResourceLookupSearchCriteria implements Parcelable {
+
+ private String folderUri;
+ private String query;
+ private List types;
+ private String sortBy;
+
+ private boolean recursive = true;
+ private boolean forceFullPage;
+ private int offset = 0;
+ private int limit = 100;
+
+ public ResourceLookupSearchCriteria() {
+ }
+
+ public ResourceLookupSearchCriteria(ResourceLookupSearchCriteria oldCriteria) {
+ this.folderUri = oldCriteria.getFolderUri();
+ this.query = oldCriteria.getQuery();
+ this.types = new ArrayList(oldCriteria.getTypes());
+ this.sortBy = oldCriteria.getSortBy();
+ this.recursive = oldCriteria.isRecursive();
+ this.forceFullPage = oldCriteria.isForceFullPage();
+ this.offset = oldCriteria.getOffset();
+ this.limit = oldCriteria.getLimit();
+ }
+
+ //---------------------------------------------------------------------
+ // Parcelable
+ //---------------------------------------------------------------------
+
+ public ResourceLookupSearchCriteria(Parcel source) {
+ this.folderUri = source.readString();
+ this.query = source.readString();
+ this.types = source.createStringArrayList();
+ this.sortBy = source.readString();
+ this.recursive = source.readByte() != 0;
+ this.forceFullPage = source.readByte() != 0;
+ this.offset = source.readInt();
+ this.limit = source.readInt();
+ }
+
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+ public ResourceLookupSearchCriteria createFromParcel(Parcel source) {
+ return new ResourceLookupSearchCriteria(source);
+ }
+
+ public ResourceLookupSearchCriteria[] newArray(int size) {
+ return new ResourceLookupSearchCriteria[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(folderUri);
+ dest.writeString(query);
+ dest.writeStringList(types);
+ dest.writeString(sortBy);
+ dest.writeByte((byte) (recursive ? 1 : 0));
+ dest.writeByte((byte) (forceFullPage ? 1 : 0));
+ dest.writeInt(offset);
+ dest.writeInt(limit);
+ }
+
+ //---------------------------------------------------------------------
+ // Getters & Setters
+ //---------------------------------------------------------------------
+
+ /**
+ * {@link ResourceLookupSearchCriteria#setFolderUri}
+ */
+ public String getFolderUri() {
+ return folderUri;
+ }
+
+ /**
+ * The path of the base folder for the search.
+ */
+ public void setFolderUri(String folderUri) {
+ this.folderUri = folderUri;
+ }
+
+ /**
+ * {@link ResourceLookupSearchCriteria#setQuery}
+ */
+ public String getQuery() {
+ return query;
+ }
+
+ /**
+ * Search for resources having the specified text in the name or description.
+ * Note that the search string does not match in the ID of resources.
+ */
+ public void setQuery(String query) {
+ this.query = query;
+ }
+
+ /**
+ * {@link ResourceLookupSearchCriteria#setTypes}
+ */
+ public List getTypes() {
+ return types;
+ }
+
+ /**
+ * Match only resources of the given type. Multiple type parameters are allowed.
+ * Wrong values are ignored.
+ */
+ public void setTypes(List types) {
+ this.types = types;
+ }
+
+ /**
+ * {@link ResourceLookupSearchCriteria#setSortBy}
+ */
+ public String getSortBy() {
+ return sortBy;
+ }
+
+ /**
+ * One of the following strings representing a field in the results to sort by: uri,
+ * label, description, type, creationDate, updateDate, accessTime, or popularity
+ * (based on access events).
+ */
+ public void setSortBy(String sortBy) {
+ this.sortBy = sortBy;
+ }
+
+ /**
+ * {@link ResourceLookupSearchCriteria#setRecursive}
+ */
+ public boolean isRecursive() {
+ return recursive;
+ }
+
+ /**
+ * Indicates whether search should include all sub-folders recursively. When
+ * omitted, the default behavior is recursive (true).
+ */
+ public void setRecursive(boolean recursive) {
+ this.recursive = recursive;
+ }
+
+ /**
+ * {@link ResourceLookupSearchCriteria#setOffset}
+ */
+ public int getOffset() {
+ return offset;
+ }
+
+ /**
+ * Used for pagination to request an offset in the set of results. This is
+ * equivalent to a specific page number. The default offset is 1 (first page).
+ */
+ public void setOffset(int offset) {
+ this.offset = offset;
+ }
+
+ /**
+ * {@link ResourceLookupSearchCriteria#setLimit}
+ */
+ public int getLimit() {
+ return limit;
+ }
+
+ /**
+ * Used for pagination to specify the maximum number of resources to return in
+ * each response. This is equivalent to the number of results per page. The
+ * default limit is 100.
+ */
+ public void setLimit(int limit) {
+ this.limit = limit;
+ }
+
+ /**
+ * {@link ResourceLookupSearchCriteria#setForceFullPage}
+ */
+ public boolean isForceFullPage() {
+ return forceFullPage;
+ }
+
+ /**
+ * With forceFullPage=false,
+ * This is the offset to request the next page. The Next-Offset is equivalent to Start-Index+limit, except on the last page.
+ * On the the last page, the Next-Offset is omitted to indicate there are no further pages.
+ * {@link ResourceLookupSearchCriteria#setLimit}
+ */
+
+ /**
+ * With forceFullPage=false we receive different pagination experience. Considering header
+ * for response Next-Offset which is the offset to request the next page. The Next-Offset
+ * is equivalent to Start-Index+limit, except on the last page.
+ * On the the last page, the Next-Offset is omitted to indicate there are no further pages.
+ *
+ *
+ * With forceFullPage=true enables full page pagination. Depending on the type of search and
+ * user permissions, this parameter can cause significant performance delays.
+ *
+ * @param forceFullPage accepts boolean value
+ */
+ public void setForceFullPage(boolean forceFullPage) {
+ this.forceFullPage = forceFullPage;
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookupsList.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookupsList.java
index 36dd817a..688462e9 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookupsList.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/resource/ResourceLookupsList.java
@@ -35,6 +35,7 @@
@Root(name="resources")
public class ResourceLookupsList {
+ public static int NO_OFFSET = -1;
@ElementList(entry="resourceLookup", inline=true, required=false, empty=false)
private List resourceLookups;
@@ -45,6 +46,12 @@ public class ResourceLookupsList {
@Element(required=false)
private int totalCount;
+ @Element(required=false)
+ private int nextOffset;
+
+ @Element(required=false)
+ private int startIndex;
+
public ResourceLookupsList() {
this.resourceLookups = new ArrayList();
this.resultCount = 0;
@@ -86,4 +93,28 @@ public void setTotalCount(int totalCount) {
public void setTotalCount(String totalCount) {
this.totalCount = (totalCount != null) ? Integer.parseInt(totalCount) : 0;
}
+
+ public int getStartIndex() {
+ return startIndex;
+ }
+
+ public void setStartIndex(String startIndex) {
+ this.startIndex = (startIndex != null) ? Integer.parseInt(startIndex) : 0;
+ }
+
+ public void setStartIndex(int startIndex) {
+ this.startIndex = startIndex;
+ }
+
+ public int getNextOffset() {
+ return nextOffset;
+ }
+
+ public void setNextOffset(String nextOffset) {
+ this.nextOffset = (nextOffset != null) ? Integer.parseInt(nextOffset) : NO_OFFSET;
+ }
+
+ public void setNextOffset(int nextOffset) {
+ this.nextOffset = nextOffset;
+ }
}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/server/ServerInfo.java b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/server/ServerInfo.java
index c95ab5dd..a5bef84a 100644
--- a/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/server/ServerInfo.java
+++ b/client/src/main/java/com/jaspersoft/android/sdk/client/oxm/server/ServerInfo.java
@@ -24,6 +24,8 @@
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
+import java.math.BigDecimal;
+
/**
* @author Ivan Gadzhega
* @since 1.4
@@ -33,9 +35,11 @@ public class ServerInfo {
public static class VERSION_CODES {
public static final int UNKNOWN = 0;
- public static final int EMERALD = 50000;
- public static final int EMERALD_MR1 = 50200;
- public static final int EMERALD_TWO = 50500;
+ public static final double EMERALD = 5.0;
+ public static final double EMERALD_MR1 = 5.2;
+ public static final double EMERALD_TWO = 5.5;
+ public static final double EMERALD_THREE = 5.6;
+ public static final double AMBER = 6.0;
}
public static class EDITIONS {
@@ -63,7 +67,7 @@ public static class EDITIONS {
private String version;
- private int versionCode;
+ private double versionCode;
public ServerInfo() {
@@ -78,18 +82,21 @@ public void setVersion(String version) {
// update version code
if (version != null) {
String[] subs = version.split("\\.");
- for (int i = 0; i < subs.length; i++) {
- int exponent = ((subs.length - 1) - i) * 2;
- int subVersion;
+ BigDecimal decimalSubVersion, decimalFactor, decimalResult;
+ BigDecimal decimalVersion = new BigDecimal("0");
+ for (int i = 0; i < subs.length; i++) {
try {
- subVersion = Integer.parseInt(subs[i]);
+ decimalSubVersion = new BigDecimal(Integer.parseInt(subs[i]));
} catch (NumberFormatException ex) {
- subVersion = 0;
+ decimalSubVersion = new BigDecimal("0");
}
- versionCode += subVersion * Math.pow(10, exponent);
+ decimalFactor = new BigDecimal(String.valueOf(Math.pow(10, i * -1)));
+ decimalResult = decimalSubVersion.multiply(decimalFactor);
+ decimalVersion = decimalVersion.add(decimalResult);
}
+ versionCode = decimalVersion.doubleValue();
}
}
@@ -150,11 +157,11 @@ public void setLicenseType(String licenseType) {
this.licenseType = licenseType;
}
- public int getVersionCode() {
+ public double getVersionCode() {
return versionCode;
}
- public void setVersionCode(int versionCode) {
+ public void setVersionCode(double versionCode) {
this.versionCode = versionCode;
}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/util/CookieHttpRequestInterceptor.java b/client/src/main/java/com/jaspersoft/android/sdk/util/CookieHttpRequestInterceptor.java
new file mode 100644
index 00000000..db2b449c
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/util/CookieHttpRequestInterceptor.java
@@ -0,0 +1,67 @@
+package com.jaspersoft.android.sdk.util;
+
+import android.util.Base64;
+import android.util.Log;
+
+import com.jaspersoft.android.sdk.client.JsServerProfile;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class CookieHttpRequestInterceptor implements ClientHttpRequestInterceptor {
+ private static final String SET_COOKIE = "set-cookie";
+ private static final String COOKIE = "Cookie";
+ private static final String COOKIE_STORE = "cookieStore";
+ private final JsServerProfile jsServerProfile;
+
+ public CookieHttpRequestInterceptor(JsServerProfile jsServerProfile) {
+ this.jsServerProfile = jsServerProfile;
+ }
+
+ @Override
+ public ClientHttpResponse intercept(HttpRequest request, byte[] byteArray,
+ ClientHttpRequestExecution execution) throws IOException {
+
+ Log.d(getClass().getSimpleName(), ">>> entering intercept");
+ List cookies = request.getHeaders().get(COOKIE);
+ // if the header doesn't exist, add any existing, saved cookies
+ if (cookies == null) {
+ List cookieStore = (List) StaticCacheHelper.retrieveObjectFromCache(COOKIE_STORE);
+ // if we have stored cookies, add them to the headers
+ if (cookieStore != null) {
+ request.getHeaders().add(COOKIE, StringUtils.join(cookieStore, ";"));
+ } else {
+ Log.d(getClass().getSimpleName(), "Setting basic auth");
+ // Basic Authentication
+ String authorisation = jsServerProfile.getUsernameWithOrgId() + ":" + jsServerProfile.getPassword();
+ byte[] encodedAuthorisation = Base64.encode(authorisation.getBytes(), Base64.NO_WRAP);
+ request.getHeaders().set("Authorization", "Basic " + new String(encodedAuthorisation));
+ // disable buggy keep-alive
+ request.getHeaders().set("Connection", "close");
+ }
+ }
+
+ // execute the request
+ ClientHttpResponse response = execution.execute(request, byteArray);
+ // pull any cookies off and store them
+ cookies = response.getHeaders().get(SET_COOKIE);
+ if (cookies != null) {
+ for (String cookie : cookies) {
+ Log.d(getClass().getSimpleName(), ">>> response cookie = " + cookie);
+ }
+ StaticCacheHelper.storeObjectInCache(COOKIE_STORE, cookies);
+ }
+ Log.d(getClass().getSimpleName(), ">>> leaving intercept");
+ return response;
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/util/KeepAliveHttpRequestInterceptor.java b/client/src/main/java/com/jaspersoft/android/sdk/util/KeepAliveHttpRequestInterceptor.java
new file mode 100644
index 00000000..0586ce00
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/util/KeepAliveHttpRequestInterceptor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
+ * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
+ * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
+ * Vestibulum commodo. Ut rhoncus gravida arcu.
+ */
+
+package com.jaspersoft.android.sdk.util;
+
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+
+import java.io.IOException;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class KeepAliveHttpRequestInterceptor implements ClientHttpRequestInterceptor {
+ @Override
+ public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
+ request.getHeaders().add("Connection", "Close");
+ return execution.execute(request, body);
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/util/LocalesHttpRequestInterceptor.java b/client/src/main/java/com/jaspersoft/android/sdk/util/LocalesHttpRequestInterceptor.java
new file mode 100644
index 00000000..275aea1a
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/util/LocalesHttpRequestInterceptor.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
+ * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
+ * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
+ * Vestibulum commodo. Ut rhoncus gravida arcu.
+ */
+
+package com.jaspersoft.android.sdk.util;
+
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+
+import java.io.IOException;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class LocalesHttpRequestInterceptor implements ClientHttpRequestInterceptor {
+ private static final String ACCEPT_TIMEZONE = "Accept-Timezone";
+
+ @Override
+ public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
+ String timeZone = createGmtOffsetString(true, true, TimeZone.getDefault().getRawOffset());
+ // Because of HTTP accepts this type separator '-' we replace default one
+ String locale = Locale.getDefault().toString().replaceAll("_", "-");
+
+ request.getHeaders().setAcceptLanguage(locale);
+ request.getHeaders().add(ACCEPT_TIMEZONE, timeZone);
+
+ return execution.execute(request, body);
+ }
+
+ private String createGmtOffsetString(boolean includeGmt,
+ boolean includeMinuteSeparator, int offsetMillis) {
+ int offsetMinutes = offsetMillis / 60000;
+ char sign = '+';
+ if (offsetMinutes < 0) {
+ sign = '-';
+ offsetMinutes = -offsetMinutes;
+ }
+ StringBuilder builder = new StringBuilder(9);
+ if (includeGmt) {
+ builder.append("GMT");
+ }
+ builder.append(sign);
+ appendNumber(builder, 2, offsetMinutes / 60);
+ if (includeMinuteSeparator) {
+ builder.append(':');
+ }
+ appendNumber(builder, 2, offsetMinutes % 60);
+ return builder.toString();
+ }
+
+ private void appendNumber(StringBuilder builder, int count, int value) {
+ String string = Integer.toString(value);
+ for (int i = 0; i < count - string.length(); i++) {
+ builder.append('0');
+ }
+ builder.append(string);
+ }
+}
diff --git a/client/src/main/java/com/jaspersoft/android/sdk/util/StaticCacheHelper.java b/client/src/main/java/com/jaspersoft/android/sdk/util/StaticCacheHelper.java
new file mode 100644
index 00000000..a1e495c8
--- /dev/null
+++ b/client/src/main/java/com/jaspersoft/android/sdk/util/StaticCacheHelper.java
@@ -0,0 +1,117 @@
+package com.jaspersoft.android.sdk.util;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Tom Koptel
+ * @since 1.9
+ */
+public class StaticCacheHelper {
+
+ private static final long TIME_TO_LIVE = TimeUnit.MINUTES.toMillis(20);
+
+ private static final Map cacheMap = new HashMap();
+
+ /**
+ * Retrieves an item from the cache. If found, the method compares
+ * the object's expiration date to the current time and only returns
+ * the object if the expiration date has not passed.
+ *
+ * @param cacheKey
+ * @return
+ */
+ public static Object retrieveObjectFromCache(String cacheKey) {
+ Element e = cacheMap.get(cacheKey);
+ Object o = null;
+ if (e != null) {
+ Date now = new Date();
+ if (e.getExpirationDate().after(now)) {
+ o = e.getObject();
+ } else {
+ removeCacheItem(cacheKey);
+ }
+ }
+ return o;
+ }
+
+ /**
+ * Stores an object in the cache, wrapped by an Element object.
+ * The Element object has an expiration date, which will be set to
+ * now + this class' TIME_TO_LIVE setting.
+ *
+ * @param cacheKey
+ * @param object
+ */
+ public static void storeObjectInCache(String cacheKey, Object object) {
+ Date expirationDate = new Date(System.currentTimeMillis() + TIME_TO_LIVE);
+ Element e = new Element(object, expirationDate);
+ cacheMap.put(cacheKey, e);
+ }
+
+ /**
+ * Stores an object in the cache, wrapped by an Element object.
+ * The Element object has an expiration date, which will be set to
+ * now + the timeToLiveInMilliseconds value that is passed into the method.
+ *
+ * @param cacheKey
+ * @param object
+ * @param timeToLiveInMilliseconds
+ */
+ public static void storeObjectInCache(String cacheKey, Object object, int timeToLiveInMilliseconds) {
+ Date expirationDate = new Date(System.currentTimeMillis() + timeToLiveInMilliseconds);
+ Element e = new Element(object, expirationDate);
+ cacheMap.put(cacheKey, e);
+ }
+
+ public static void removeCacheItem(String cacheKey) {
+ cacheMap.remove(cacheKey);
+ }
+
+ public static void clearCache() {
+ cacheMap.clear();
+ }
+
+ static class Element {
+
+ private Object object;
+ private Date expirationDate;
+
+ /**
+ * @param object
+ * @param key
+ * @param expirationDate
+ */
+ private Element(Object object, Date expirationDate) {
+ super();
+ this.object = object;
+ this.expirationDate = expirationDate;
+ }
+ /**
+ * @return the object
+ */
+ public Object getObject() {
+ return object;
+ }
+ /**
+ * @param object the object to set
+ */
+ public void setObject(Object object) {
+ this.object = object;
+ }
+ /**
+ * @return the expirationDate
+ */
+ public Date getExpirationDate() {
+ return expirationDate;
+ }
+ /**
+ * @param expirationDate the expirationDate to set
+ */
+ public void setExpirationDate(Date expirationDate) {
+ this.expirationDate = expirationDate;
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/src/test/java/InputControlWrapperTest.java b/client/src/test/java/InputControlWrapperTest.java
deleted file mode 100644
index 36382430..00000000
--- a/client/src/test/java/InputControlWrapperTest.java
+++ /dev/null
@@ -1,231 +0,0 @@
-import com.jaspersoft.android.sdk.client.ic.InputControlWrapper;
-import com.jaspersoft.android.sdk.client.oxm.ResourceDescriptor;
-import com.jaspersoft.android.sdk.client.oxm.ResourceProperty;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.mockito.Mockito.*;
-import static junit.framework.Assert.*;
-
-/**
- * @author Ivan Gadzhega
- * @version $Id$
- * @since 1.0
- */
-public class InputControlWrapperTest {
-
- private final static String label = "Input Control";
- private final static String name = "inputControl";
- private final static String uriString = "/Samples/AllAccounts/inputControl";
-
- private ResourceDescriptor resourceDescriptor;
-
-
- @Before
- public void initResourceDescriptor() {
- resourceDescriptor = mock(ResourceDescriptor.class);
- when(resourceDescriptor.getLabel()).thenReturn(label);
- when(resourceDescriptor.getName()).thenReturn(name);
- when(resourceDescriptor.getUriString()).thenReturn(uriString);
- }
-
- @Test
- public void test_init() {
- InputControlWrapper wrapper = new InputControlWrapper(resourceDescriptor);
- assertEquals(label, wrapper.getLabel());
- assertEquals(name, wrapper.getName());
- assertEquals(uriString, wrapper.getUri());
- }
-
- @Test
- public void test_init_type() {
- ResourceProperty typeProperty = mock(ResourceProperty.class);
- when(typeProperty.getName()).thenReturn(ResourceDescriptor.PROP_INPUTCONTROL_TYPE);
- when(typeProperty.getValue()).thenReturn(Byte.toString(ResourceDescriptor.IC_TYPE_BOOLEAN));
-
- List propertyList = new ArrayList();
- propertyList.add(typeProperty);
-
- when(resourceDescriptor.getProperties()).thenReturn(propertyList);
-
- InputControlWrapper wrapper = new InputControlWrapper(resourceDescriptor);
-
- assertEquals(ResourceDescriptor.IC_TYPE_BOOLEAN, wrapper.getType());
- }
-
- @Test
- public void test_init_isMandatory() {
- ResourceProperty typeProperty = mock(ResourceProperty.class);
- when(typeProperty.getName()).thenReturn(ResourceDescriptor.PROP_INPUTCONTROL_IS_MANDATORY);
- when(typeProperty.getValue()).thenReturn("true");
-
- List propertyList = new ArrayList();
- propertyList.add(typeProperty);
-
- when(resourceDescriptor.getProperties()).thenReturn(propertyList);
-
- InputControlWrapper wrapper = new InputControlWrapper(resourceDescriptor);
-
- assertEquals(true, wrapper.isMandatory());
- }
-
- @Test
- public void test_init_isReadOnly() {
- ResourceProperty typeProperty = mock(ResourceProperty.class);
- when(typeProperty.getName()).thenReturn(ResourceDescriptor.PROP_INPUTCONTROL_IS_READONLY);
- when(typeProperty.getValue()).thenReturn("true");
-
- List propertyList = new ArrayList();
- propertyList.add(typeProperty);
-
- when(resourceDescriptor.getProperties()).thenReturn(propertyList);
-
- InputControlWrapper wrapper = new InputControlWrapper(resourceDescriptor);
-
- assertEquals(true, wrapper.isReadOnly());
- }
-
- @Test
- public void test_init_isVisible() {
- ResourceProperty typeProperty = mock(ResourceProperty.class);
- when(typeProperty.getName()).thenReturn(ResourceDescriptor.PROP_INPUTCONTROL_IS_VISIBLE);
- when(typeProperty.getValue()).thenReturn("true");
-
- List propertyList = new ArrayList();
- propertyList.add(typeProperty);
-
- when(resourceDescriptor.getProperties()).thenReturn(propertyList);
-
- InputControlWrapper wrapper = new InputControlWrapper(resourceDescriptor);
-
- assertEquals(true, wrapper.isVisible());
- }
-
- @Test
- public void test_init_query() {
- String query = "query";
- String dataSourceUri = "dataSourceUri";
-
- ResourceProperty queryProperty = mock(ResourceProperty.class);
- when(queryProperty.getValue()).thenReturn(query);
-
- ResourceDescriptor internalResource = mock(ResourceDescriptor.class);
- when(internalResource.getWsType()).thenReturn(ResourceDescriptor.WsType.query);
- when(internalResource.getDataSourceUri()).thenReturn(dataSourceUri);
- when(internalResource.getPropertyByName(ResourceDescriptor.PROP_QUERY)).thenReturn(queryProperty);
-
- List internalResources = new ArrayList();
- internalResources.add(internalResource);
-
- when(resourceDescriptor.getInternalResources()).thenReturn(internalResources);
-
- InputControlWrapper wrapper = new InputControlWrapper(resourceDescriptor);
-
- assertEquals(query, wrapper.getQuery());
- assertEquals(dataSourceUri, wrapper.getDataSourceUri());
- }
-
- @Test
- public void test_init_singleValue_dataType() {
- ResourceProperty typeProperty = mock(ResourceProperty.class);
- when(typeProperty.getName()).thenReturn(ResourceDescriptor.PROP_INPUTCONTROL_TYPE);
- when(typeProperty.getValue()).thenReturn(Byte.toString(ResourceDescriptor.IC_TYPE_SINGLE_VALUE));
-
- List propertyList = new ArrayList();
- propertyList.add(typeProperty);
-
- when(resourceDescriptor.getProperties()).thenReturn(propertyList);
-
- Byte dataTypeValue = ResourceDescriptor.DT_TYPE_TEXT;
-
- ResourceProperty dataTypeProperty = mock(ResourceProperty.class);
- when(dataTypeProperty.getValue()).thenReturn(dataTypeValue.toString());
-
- ResourceDescriptor internalResource = mock(ResourceDescriptor.class);
- when(internalResource.getWsType()).thenReturn(ResourceDescriptor.WsType.dataType);
- when(internalResource.getPropertyByName(ResourceDescriptor.PROP_DATATYPE_TYPE)).thenReturn(dataTypeProperty);
-
- List internalResources = new ArrayList();
- internalResources.add(internalResource);
-
- when(resourceDescriptor.getInternalResources()).thenReturn(internalResources);
-
- InputControlWrapper wrapper = new InputControlWrapper(resourceDescriptor);
-
- assertEquals(dataTypeValue.byteValue(), wrapper.getDataType());
- }
-
- @Test
- public void test_init_parameterDependencies() {
- Map queries = new HashMap();
- queries.put(
- "Standart Parameter",
- "select distinct billing_address_state, billing_address_country from accounts where "
- + "billing_address_country = $P{Country_multi_select} order by billing_address_country, billing_address_state"
- );
- queries.put(
- "Include Parameter",
- "select distinct billing_address_state, billing_address_country from accounts where "
- + "billing_address_country = $P!{Country_multi_select} order by billing_address_country, billing_address_state"
- );
- queries.put(
- "Dynamic Parameter",
- "select distinct billing_address_state, billing_address_country from accounts where "
- + "$X{IN, billing_address_country, Country_multi_select} order by billing_address_country, billing_address_state"
- );
-
- for (Map.Entry query : queries.entrySet()) {
- ResourceProperty queryProperty = mock(ResourceProperty.class);
- when(queryProperty.getValue()).thenReturn(query.getValue());
-
- ResourceDescriptor internalResource = mock(ResourceDescriptor.class);
- when(internalResource.getWsType()).thenReturn(ResourceDescriptor.WsType.query);
- when(internalResource.getPropertyByName(ResourceDescriptor.PROP_QUERY)).thenReturn(queryProperty);
-
- List internalResources = new ArrayList();
- internalResources.add(internalResource);
-
- when(resourceDescriptor.getInternalResources()).thenReturn(internalResources);
-
- InputControlWrapper wrapper = new InputControlWrapper(resourceDescriptor);
-
- assertFalse(query.getKey(), wrapper.getParameterDependencies().isEmpty());
- }
- }
-
-
- @Test
- public void test_init_valuesList() {
- List listOfValues = (List) mock(List.class);
-
- ResourceProperty lovProperty = mock(ResourceProperty.class);
- when(lovProperty.getProperties()).thenReturn(listOfValues);
-
- ResourceDescriptor internalResource = mock(ResourceDescriptor.class);
- when(internalResource.getWsType()).thenReturn(ResourceDescriptor.WsType.lov);
- when(internalResource.getPropertyByName(ResourceDescriptor.PROP_LOV)).thenReturn(lovProperty);;
-
- List internalResources = new ArrayList();
- internalResources.add(internalResource);
-
- ResourceProperty typeProperty = mock(ResourceProperty.class);
- when(typeProperty.getName()).thenReturn(ResourceDescriptor.PROP_INPUTCONTROL_TYPE);
- when(typeProperty.getValue()).thenReturn(Byte.toString(ResourceDescriptor.IC_TYPE_SINGLE_SELECT_LIST_OF_VALUES));
-
- List propertyList = new ArrayList();
- propertyList.add(typeProperty);
-
- when(resourceDescriptor.getInternalResources()).thenReturn(internalResources);
- when(resourceDescriptor.getProperties()).thenReturn(propertyList);
-
- InputControlWrapper wrapper = new InputControlWrapper(resourceDescriptor);
-
- assertEquals(listOfValues, wrapper.getListOfValues());
- }
-
-}
diff --git a/client/src/test/java/JsRestClientTest.java b/client/src/test/java/JsRestClientTest.java
deleted file mode 100644
index c2a72993..00000000
--- a/client/src/test/java/JsRestClientTest.java
+++ /dev/null
@@ -1,269 +0,0 @@
-import com.jaspersoft.android.sdk.client.JsRestClient;
-import com.jaspersoft.android.sdk.client.oxm.*;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.ClientHttpRequest;
-import org.springframework.http.client.ClientHttpRequestFactory;
-import org.springframework.http.client.ClientHttpResponse;
-import org.springframework.web.client.ResourceAccessException;
-import org.springframework.web.client.ResponseErrorHandler;
-import org.springframework.web.client.RestTemplate;
-import org.springframework.web.util.UriTemplate;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
-import static org.mockito.Mockito.*;
-
-/**
- * @author Ivan Gadzhega
- * @version $Id$
- * @since 1.0
- */
-public class JsRestClientTest {
-
- @Mock
- private RestTemplate restTemplate;
-
- @InjectMocks
- private JsRestClient jsRestClient = new JsRestClient() {
- @Override
- protected int copyResponseToFile(ClientHttpResponse response, File file) {
- // do nothing
- return 0;
- }
- };
-
- private final static String resourceUri = "/Samples/AllAccounts";
- private final static String folderUri = "/reports/samples";
- private final static String inputControlUri = "/Samples/AllAccounts/inputControl";
- private final static String datasourceUri = "/datasource";
- private final String uuid = "d7bf6c9-9077-41f7-a2d4-8682e74b637e";
- private final static String attachmentName = "img_0_0_0";
-
- @Before
- public void initMocks() {
- MockitoAnnotations.initMocks(this);
- }
-
- //---------------------------------------------------------------------
- // The Resource Service
- //---------------------------------------------------------------------
-
- @Test
- public void test_getResource() {
- String fullUri = jsRestClient.getRestServicesUrl() + JsRestClient.REST_RESOURCE_URI + resourceUri;
-
- ResourceDescriptor expectedDescriptor = mock(ResourceDescriptor.class);
- when(restTemplate.getForObject(fullUri, ResourceDescriptor.class)).thenReturn(expectedDescriptor);
-
- ResourceDescriptor actualDescriptor = jsRestClient.getResource(resourceUri);
-
- verify(restTemplate).getForObject(fullUri, ResourceDescriptor.class);
- assertEquals(expectedDescriptor, actualDescriptor);
- }
-
- @Test
- public void test_modifyResource() {
- ResourceDescriptor resourceDescriptor = mock(ResourceDescriptor.class);
-
- String fullUri = jsRestClient.getRestServicesUrl() + JsRestClient.REST_RESOURCE_URI + resourceDescriptor.getUriString();
-
- jsRestClient.modifyResource(resourceDescriptor);
- verify(restTemplate).postForLocation(fullUri, resourceDescriptor);
- }
-
- @Test
- public void test_deleteResource() {
- String fullUri = jsRestClient.getRestServicesUrl() + JsRestClient.REST_RESOURCE_URI + resourceUri;
-
- jsRestClient.deleteResource(resourceUri);
- verify(restTemplate).delete(fullUri);
- }
-
- //---------------------------------------------------------------------
- // The Resources Service
- //---------------------------------------------------------------------
-
- @Test
- public void test_getResourcesList() {
- String fullUri = jsRestClient.getRestServicesUrl() + JsRestClient.REST_RESOURCES_URI + folderUri;
-
- List expectedResourcesList = (List) mock(List.class);
-
- ResourcesList resourcesList = mock(ResourcesList.class);
- when(resourcesList.getResourceDescriptors()).thenReturn(expectedResourcesList);
-
- when(restTemplate.getForObject(fullUri, ResourcesList.class)).thenReturn(resourcesList);
-
- List actualResourcesList = jsRestClient.getResourcesList(folderUri);
-
- verify(restTemplate).getForObject(fullUri, ResourcesList.class);
- assertEquals(expectedResourcesList, actualResourcesList);
- }
-
- @Test
- public void test_getResourcesList_matchingParameters() {
- String query = "AllAccounts";
- String type = "reportUnit";
- Boolean recursive = true;
- Integer limit = 10;
-
- String uriVariablesTemplate = "?q={query}&type={type}&recursive={recursive}&limit={limit}";
- String fullUri = jsRestClient.getRestServicesUrl() + JsRestClient.REST_RESOURCES_URI + folderUri + uriVariablesTemplate;
-
- List expectedResourcesList = (List) mock(List.class);
-
- ResourcesList resourcesList = mock(ResourcesList.class);
- when(resourcesList.getResourceDescriptors()).thenReturn(expectedResourcesList);
-
- when(restTemplate.getForObject(fullUri, ResourcesList.class, query, type, recursive, limit))
- .thenReturn(resourcesList);
-
- List actualResourcesList = jsRestClient.getResourcesList(folderUri, query, type, recursive, limit);
-
- verify(restTemplate).getForObject(fullUri, ResourcesList.class, query, type, recursive, limit);
- assertEquals(expectedResourcesList, actualResourcesList);
- }
-
- //---------------------------------------------------------------------
- // The Report Service
- //---------------------------------------------------------------------
-
- @Test
- public void test_getReportDescriptor() {
- String format = "HTML";
- ResourceDescriptor resourceDescriptor = mock(ResourceDescriptor.class);
-
- String fullUri = jsRestClient.getRestServicesUrl() + JsRestClient.REST_REPORT_URI +
- resourceDescriptor.getUriString() + "?IMAGES_URI=./&RUN_OUTPUT_FORMAT={format}";
-
- ReportDescriptor expectedDescriptor = mock(ReportDescriptor.class);
-
- ResponseEntity responseEntity = (ResponseEntity) mock(ResponseEntity.class);
-
- when(responseEntity.getBody()).thenReturn(expectedDescriptor);
-
- when(restTemplate.exchange(eq(fullUri), eq(HttpMethod.PUT), isA(HttpEntity.class), eq(ReportDescriptor.class), eq(format)))
- .thenReturn(responseEntity);
-
- ReportDescriptor actualDescriptor = jsRestClient.getReportDescriptor(resourceDescriptor, format);
-
- verify(restTemplate).exchange(eq(fullUri), eq(HttpMethod.PUT), isA(HttpEntity.class), eq(ReportDescriptor.class), eq(format));
- assertEquals(expectedDescriptor, actualDescriptor);
- }
-
- @Test
- public void test_getReportAttachment() {
- String fullUri = jsRestClient.getRestServicesUrl() + JsRestClient.REST_REPORT_URI + "/{uuid}?file={name}";
-
- byte[] expectedAttachment = new byte[10];
-
- ResponseEntity responseEntity = (ResponseEntity) mock(ResponseEntity.class);
- when(responseEntity.getBody()).thenReturn(expectedAttachment);
-
- when(restTemplate.exchange(eq(fullUri), eq(HttpMethod.GET), isA(HttpEntity.class), eq(byte[].class), eq(uuid), eq(attachmentName)))
- .thenReturn(responseEntity);
-
- byte[] actualAttachment = jsRestClient.getReportAttachment(uuid, attachmentName);
-
- verify(restTemplate).exchange(eq(fullUri), eq(HttpMethod.GET), isA(HttpEntity.class), eq(byte[].class), eq(uuid), eq(attachmentName));
- assertEquals(expectedAttachment, actualAttachment);
- }
-
- @Test
- public void test_saveReportAttachmentToFile() {
- String fullUri = jsRestClient.getRestServicesUrl() + JsRestClient.REST_REPORT_URI + "/{uuid}?file={name}";
-
- ClientHttpRequestFactory factory = mock(ClientHttpRequestFactory.class);
- when(restTemplate.getRequestFactory()).thenReturn(factory);
-
- ResponseErrorHandler errorHandler = mock(ResponseErrorHandler.class);
- when(restTemplate.getErrorHandler()).thenReturn(errorHandler);
-
- UriTemplate uriTemplate = new UriTemplate(fullUri);
- URI expanded = uriTemplate.expand(uuid, attachmentName);
-
- ClientHttpRequest request = mock(ClientHttpRequest.class);
- ClientHttpResponse response = mock(ClientHttpResponse.class);
-
- InputStream inputStream = mock(InputStream.class);
-
- File file = mock(File.class);
-
- try {
- when(factory.createRequest(expanded, HttpMethod.GET)).thenReturn(request);
- when(request.execute()).thenReturn(response);
-
- jsRestClient.saveReportAttachmentToFile(uuid, attachmentName, file);
- verify(restTemplate).getRequestFactory();
- verify(factory).createRequest(expanded, HttpMethod.GET);
- verify(response).close();
- } catch (IOException ex) {
- throw new ResourceAccessException("I/O error: " + ex.getMessage(), ex);
- }
- }
-
- @Test
- public void test_getInputControlWithQueryData() {
- List params = new ArrayList();
- params.add(mock(ResourceParameter.class));
- params.add(mock(ResourceParameter.class));
-
- StringBuilder fullUri = new StringBuilder();
- fullUri.append(jsRestClient.getRestServicesUrl()).append(JsRestClient.REST_RESOURCE_URI).append(inputControlUri);
- fullUri.append("?IC_GET_QUERY_DATA=").append(datasourceUri);
-
- for(ResourceParameter parameter : params) {
- fullUri.append(parameter.isListItem() ? "&PL_" : "&P_");
- fullUri.append(parameter.getName()).append("=").append(parameter.getValue());
- }
-
- ResourceDescriptor expectedDescriptor = mock(ResourceDescriptor.class);
- when(restTemplate.getForObject(fullUri.toString(), ResourceDescriptor.class)).thenReturn(expectedDescriptor);
-
- ResourceDescriptor actualDescriptor = jsRestClient.getInputControlWithQueryData(inputControlUri, datasourceUri, params);
-
- verify(restTemplate).getForObject(fullUri.toString(), ResourceDescriptor.class);
- assertEquals(expectedDescriptor, actualDescriptor);
- }
-
- @Test
- public void test_getInputControlQueryData() {
- List params = new ArrayList();
- params.add(mock(ResourceParameter.class));
- params.add(mock(ResourceParameter.class));
-
-
- JsRestClient spyJsRestClient = spy(jsRestClient);
- ResourceDescriptor resourceDescriptor = mock(ResourceDescriptor.class);
- when(spyJsRestClient.getInputControlWithQueryData(inputControlUri, datasourceUri, params)).thenReturn(resourceDescriptor);
-
- ResourceProperty queryDataProperty = mock(ResourceProperty.class);
-
- List queryData = new ArrayList();
- queryData.add(mock(ResourceProperty.class));
- queryData.add(mock(ResourceProperty.class));
-
- when(queryDataProperty.getProperties()).thenReturn(queryData);
-
- when(resourceDescriptor.getPropertyByName(ResourceDescriptor.PROP_QUERY_DATA)).thenReturn(queryDataProperty);
-
- List listOfValues = jsRestClient.getInputControlQueryData(inputControlUri, datasourceUri, params);
-
- verify(spyJsRestClient).getInputControlWithQueryData(inputControlUri, datasourceUri, params);
- assertNotNull(listOfValues);
- }
-}
diff --git a/client/src/test/java/JsServerProfileTest.java b/client/src/test/java/JsServerProfileTest.java
deleted file mode 100644
index 7a63eeb3..00000000
--- a/client/src/test/java/JsServerProfileTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-import com.jaspersoft.android.sdk.client.JsServerProfile;
-import org.junit.Test;
-
-import static junit.framework.Assert.*;
-
-/**
- * @author Ivan Gadzhega
- * @version $Id$
- * @since 1.0
- */
-public class JsServerProfileTest {
-
- private final static Long id = 1L;
- private final static String alias = "Test Profile";
- private final static String serverUrl = "http://mobiledemo.jaspersoft.com/jasperserver-pro";
- private final static String organization = "organization";
- private final static String username = "user";
- private final static String password = "password";
-
- @Test
- public void test_getUsernameWithOrgId() {
- JsServerProfile serverProfile = new JsServerProfile(id, alias, serverUrl, organization, username, password);
- String actualResult = serverProfile.getUsernameWithOrgId();
- assertEquals(username + "|" + organization, actualResult);
- }
-
- @Test
- public void test_getUsernameWithOrgId_orgNull() {
- JsServerProfile serverProfile = new JsServerProfile(id, alias, serverUrl, null, username, password);
- String actualResult = serverProfile.getUsernameWithOrgId();
- assertEquals(username, actualResult);
- }
-
- @Test
- public void test_getUsernameWithOrgId_orgEmpty() {
- JsServerProfile serverProfile = new JsServerProfile(id, alias, serverUrl, "", username, password);
- String actualResult = serverProfile.getUsernameWithOrgId();
- assertEquals(username, actualResult);
- }
-}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..7b359d71
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..e498f578
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Dec 12 15:16:42 PST 2012
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-2.1-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 00000000..91a7e269
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 00000000..8a0b282a
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index 582ec0ee..00000000
--- a/pom.xml
+++ /dev/null
@@ -1,136 +0,0 @@
-
-
-
-
- 4.0.0
-
-
- UTF-8
-
-
- com.jaspersoft.android.sdk
- js-android-sdk-aggregator
- 1.8
- pom
-
-
- client
- ui
-
-
-
-
-
- com.google.android
- android
- 4.1.1.4
- provided
-
-
- org.springframework.android
- spring-android-rest-template
- 1.0.1.RELEASE
-
-
- com.octo.android.robospice
- robospice
- 1.4.11
-
-
- com.octo.android.robospice
- robospice-spring-android
- 1.4.11
-
-
-
- org.simpleframework
- simple-xml
- 2.7
-
-
-
- stax
- stax
-
-
- stax-api
- stax
-
-
-
- xpp3
- xpp3
-
-
-
-
-
- junit
- junit
- 4.9
- test
-
-
- org.mockito
- mockito-all
- 1.9.0
- test
-
-
-
-
-
-
-
-
- com.jayway.maven.plugins.android.generation2
- android-maven-plugin
- 3.6.0
- true
-
-
- 16
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
-
-
- attach-sources
-
- jar
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/scripts/android-release-aar.gradle b/scripts/android-release-aar.gradle
new file mode 100644
index 00000000..52c30fa7
--- /dev/null
+++ b/scripts/android-release-aar.gradle
@@ -0,0 +1,53 @@
+// ./gradlew clean build generateRelease
+apply plugin: 'maven'
+
+def groupId = project.PUBLISH_GROUP_ID
+def artifactId = project.PUBLISH_ARTIFACT_ID
+def version = project.PUBLISH_VERSION
+
+def localReleaseDest = "${buildDir}/release/${version}"
+
+task androidJavadocs(type: Javadoc) {
+ source = android.sourceSets.main.java.srcDirs
+ classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
+}
+
+task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
+ classifier = 'javadoc'
+ from androidJavadocs.destinationDir
+}
+
+task androidSourcesJar(type: Jar) {
+ classifier = 'sources'
+ from android.sourceSets.main.java.srcDirs
+}
+
+uploadArchives {
+ repositories.mavenDeployer {
+ pom.groupId = groupId
+ pom.artifactId = artifactId
+ pom.version = version
+ // Add other pom properties here if you want (developer details / licenses)
+ repository(url: "file://${localReleaseDest}")
+ }
+}
+
+task zipRelease(type: Zip) {
+ from localReleaseDest
+ destinationDir buildDir
+ archiveName "release-${version}.zip"
+}
+
+task generateRelease << {
+ println "Release ${version} can be found at ${localReleaseDest}/"
+ println "Release ${version} zipped can be found ${buildDir}/release-${version}.zip"
+}
+
+generateRelease.dependsOn(uploadArchives)
+generateRelease.dependsOn(zipRelease)
+
+
+artifacts {
+ archives androidSourcesJar
+ archives androidJavadocsJar
+}
\ No newline at end of file
diff --git a/scripts/android-studio-robolectric-support.gradle b/scripts/android-studio-robolectric-support.gradle
new file mode 100644
index 00000000..ba56c8ef
--- /dev/null
+++ b/scripts/android-studio-robolectric-support.gradle
@@ -0,0 +1,58 @@
+apply plugin: 'idea'
+// workaround to use android studio and robolectric without build classpath effort
+// the 'outputDir' is used as reference to the resource directory, found no other way
+// ** current has this workaround no effect, since android studio 6.0 **
+idea {
+ module {
+ outputDir = file('build/resources/testDebug')
+ testOutputDir = file('build/test-classes/debug')
+ }
+}
+
+// new workaround to force add custom output dirs for android studio
+task addTest {
+ def file = file(project.name + ".iml")
+ doLast {
+ try {
+ def parsedXml = (new XmlParser()).parse(file)
+ def node = parsedXml.component[1]
+ def outputNode = parsedXml.component[1].output[0]
+ def outputTestNode = parsedXml.component[1].'output-test'[0]
+ def rewrite = false
+
+ new Node(node, 'sourceFolder', ['url': 'file://$MODULE_DIR$/' + "${it}", 'isTestSource': "true"])
+
+ if(outputNode == null) {
+ new Node(node, 'output', ['url': 'file://$MODULE_DIR$/build/resources/testDebug'])
+ } else {
+ if(outputNode.attributes['url'] != 'file://$MODULE_DIR$/build/resources/testDebug') {
+ outputNode.attributes = ['url': 'file://$MODULE_DIR$/build/resources/testDebug']
+ rewrite = true
+ }
+ }
+
+ if(outputTestNode == null) {
+ new Node(node, 'output-test', ['url': 'file://$MODULE_DIR$/build/test-classes/debug'])
+ } else {
+ if(outputTestNode.attributes['url'] != 'file://$MODULE_DIR$/build/test-classes/debug') {
+ outputTestNode.attributes = ['url': 'file://$MODULE_DIR$/build/test-classes/debug']
+ rewrite = true
+ }
+ }
+
+ if(rewrite) {
+ def writer = new StringWriter()
+ new XmlNodePrinter(new PrintWriter(writer)).print(parsedXml)
+ file.text = writer.toString()
+ }
+ } catch (FileNotFoundException e) {
+ // iml not found, common on command line only builds
+ }
+
+ }
+}
+
+// always do the addtest on prebuild
+gradle.projectsEvaluated {
+ testDebugClasses.dependsOn(addTest)
+}
\ No newline at end of file
diff --git a/scripts/install-custom-gradle-test-plugin.sh b/scripts/install-custom-gradle-test-plugin.sh
new file mode 100755
index 00000000..85c13d95
--- /dev/null
+++ b/scripts/install-custom-gradle-test-plugin.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+mkdir temp
+cd temp
+
+ git clone https://github.com/nenick/gradle-android-test-plugin.git
+ cd gradle-android-test-plugin
+
+ echo "rootProject.name = 'gradle-android-test-plugin-parent'" > settings.gradle
+ echo "include ':gradle-android-test-plugin'" >> settings.gradle
+
+ ./gradlew :gradle-android-test-plugin:install
+
+ cd ..
+cd ..
\ No newline at end of file
diff --git a/scripts/jacoco-support.gradle b/scripts/jacoco-support.gradle
new file mode 100644
index 00000000..0e8fecc2
--- /dev/null
+++ b/scripts/jacoco-support.gradle
@@ -0,0 +1,26 @@
+jacoco {
+ toolVersion = "0.7.0.201403182114"
+}
+
+coverageSourceDirs = [
+ '../client/src/main/java',
+ '../client/build/source/apt/debug',
+ '../client/build/generated/source/db',
+ '../client/build/generated/source/buildConfig/debug',
+ '../client/build/generated/source/r/debug']
+
+jacocoTestReport {
+ reports {
+ xml.enabled = false
+ html.enabled = true
+ }
+ // class R is used, but usage will not be covered, so ignore this class from report
+ classDirectories = fileTree(dir: '../client/build/intermediates/classes/debug', exclude: 'com/example/R*.class')
+ additionalSourceDirs = files(coverageSourceDirs)
+ executionData = files('build/jacoco/testDebug.exec')
+}
+
+// just clean up dashboard, following reports are not of interest
+testRelease.reports.html.enabled = false
+testRelease.reports.junitXml.enabled = false
+testDebug.reports.junitXml.enabled = false
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 00000000..2e88badc
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,6 @@
+include ':js-android-sdk-client'
+include ':js-android-sdk-ui'
+include ':unitTests'
+
+project(':js-android-sdk-client').projectDir = "$rootDir/client" as File
+project(':js-android-sdk-ui').projectDir = "$rootDir/ui" as File
\ No newline at end of file
diff --git a/ui/AndroidManifest.xml b/ui/AndroidManifest.xml
index b6b45d89..6daca94c 100644
--- a/ui/AndroidManifest.xml
+++ b/ui/AndroidManifest.xml
@@ -24,13 +24,8 @@
-->
-
-
-
+ package="com.jaspersoft.android.sdk.ui">
+
+
diff --git a/ui/build.gradle b/ui/build.gradle
new file mode 100644
index 00000000..a4ce1587
--- /dev/null
+++ b/ui/build.gradle
@@ -0,0 +1,48 @@
+apply plugin: 'com.android.library'
+apply plugin: 'android-maven'
+
+description = 'js-android-sdk-ui'
+
+ext {
+ PUBLISH_GROUP_ID = group
+ PUBLISH_ARTIFACT_ID = description
+ PUBLISH_VERSION = '1.9'
+}
+
+
+android {
+ compileSdkVersion androidCompileSdkVersion
+ buildToolsVersion androidBuildToolsVersion
+
+ defaultConfig {
+ minSdkVersion androidMinSdkVersion
+ targetSdkVersion androidTargetSdkVersion
+
+ versionCode 9010900
+ versionName version
+ }
+
+ lintOptions {
+ abortOnError false
+ }
+
+ packagingOptions {
+ exclude 'asm-license.txt'
+ exclude 'NOTICE'
+ exclude 'LICENSE'
+ exclude 'LICENSE.txt'
+ exclude 'META-INF/license.txt'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/notice.txt'
+ exclude 'META-INF/NOTICE.txt'
+ exclude 'META-INF/NOTICE'
+ }
+}
+
+
+dependencies {
+ compile project(':js-android-sdk-client')
+}
+
+apply from: '../scripts/android-release-aar.gradle'
\ No newline at end of file
diff --git a/ui/pom.xml b/ui/pom.xml
deleted file mode 100644
index e8831903..00000000
--- a/ui/pom.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
- 4.0.0
-
-
- js-android-sdk-aggregator
- com.jaspersoft.android.sdk
- 1.8
-
-
- js-android-sdk-ui
- 1.8
- apklib
-
-
-
- com.google.android
- android
-
-
- com.jaspersoft.android.sdk
- js-android-sdk-client
- 1.8
- provided
-
-
-
-
-
-
- com.jayway.maven.plugins.android.generation2
- android-maven-plugin
-
-
- org.apache.maven.plugins
- maven-source-plugin
-
-
-
-
-
\ No newline at end of file
diff --git a/ui/res/drawable-hdpi/ic_action_date_picker.png b/ui/res/drawable-hdpi/ic_action_date_picker.png
deleted file mode 100644
index 29157092..00000000
Binary files a/ui/res/drawable-hdpi/ic_action_date_picker.png and /dev/null differ
diff --git a/ui/res/drawable-hdpi/ic_action_time_picker.png b/ui/res/drawable-hdpi/ic_action_time_picker.png
deleted file mode 100644
index 6758e1c4..00000000
Binary files a/ui/res/drawable-hdpi/ic_action_time_picker.png and /dev/null differ
diff --git a/ui/res/drawable-ldpi/ic_action_date_picker.png b/ui/res/drawable-ldpi/ic_action_date_picker.png
deleted file mode 100644
index 9bb87ae2..00000000
Binary files a/ui/res/drawable-ldpi/ic_action_date_picker.png and /dev/null differ
diff --git a/ui/res/drawable-ldpi/ic_action_time_picker.png b/ui/res/drawable-ldpi/ic_action_time_picker.png
deleted file mode 100644
index 1a909fdb..00000000
Binary files a/ui/res/drawable-ldpi/ic_action_time_picker.png and /dev/null differ
diff --git a/ui/res/drawable-mdpi/ic_action_date_picker.png b/ui/res/drawable-mdpi/ic_action_date_picker.png
deleted file mode 100644
index 6d312aa2..00000000
Binary files a/ui/res/drawable-mdpi/ic_action_date_picker.png and /dev/null differ
diff --git a/ui/res/drawable-mdpi/ic_action_time_picker.png b/ui/res/drawable-mdpi/ic_action_time_picker.png
deleted file mode 100644
index a6a0f823..00000000
Binary files a/ui/res/drawable-mdpi/ic_action_time_picker.png and /dev/null differ
diff --git a/ui/res/drawable-xhdpi/ic_action_date_picker.png b/ui/res/drawable-xhdpi/ic_action_date_picker.png
deleted file mode 100644
index 29952813..00000000
Binary files a/ui/res/drawable-xhdpi/ic_action_date_picker.png and /dev/null differ
diff --git a/ui/res/drawable-xhdpi/ic_action_time_picker.png b/ui/res/drawable-xhdpi/ic_action_time_picker.png
deleted file mode 100644
index d5f73862..00000000
Binary files a/ui/res/drawable-xhdpi/ic_action_time_picker.png and /dev/null differ
diff --git a/ui/src/main/AndroidManifest.xml b/ui/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..ef105fdb
--- /dev/null
+++ b/ui/src/main/AndroidManifest.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
diff --git a/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/FileArrayAdapter.java b/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/FileArrayAdapter.java
index c2c99042..93f7e059 100644
--- a/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/FileArrayAdapter.java
+++ b/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/FileArrayAdapter.java
@@ -38,6 +38,7 @@
import java.io.File;
import java.util.Arrays;
+import java.util.EnumMap;
import java.util.List;
/**
@@ -48,45 +49,87 @@
*/
public class FileArrayAdapter extends ArrayAdapter {
- private final Context context;
- private final List files;
+ private LayoutInfo layoutInfo;
+ private EnumMap drawableIdsMap;
+ @Deprecated
public FileArrayAdapter(Context context, File[] files) {
this(context, Arrays.asList(files));
}
- public FileArrayAdapter(Context context, List files) {
- super(context, R.layout.file_list_item, files);
- this.context = context;
- this.files = files;
+ public FileArrayAdapter(Context context, LayoutInfo layoutInfo, File[] files) {
+ this(context, layoutInfo, Arrays.asList(files));
}
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- File file = files.get(position);
+ public FileArrayAdapter(Context context, LayoutInfo layoutInfo,
+ EnumMap drawableIdsMap, File[] files) {
+ this(context, layoutInfo, drawableIdsMap, Arrays.asList(files));
+ }
- String fileName = file.getName();
- String baseName = FileUtils.getBaseName(fileName);
- String extension = FileUtils.getExtension(fileName);
+ @Deprecated
+ public FileArrayAdapter(Context context, List files) {
+ this(context, new LayoutInfo(R.layout.file_list_item), new EnumMap(FileType.class), files);
+ layoutInfo.setIconViewId(R.id.file_list_item_icon);
+ layoutInfo.setLabelViewId(R.id.file_list_item_label);
+ layoutInfo.setDateViewId(R.id.file_list_item_date);
+ layoutInfo.setSizeViewId(R.id.file_list_item_size);
- Drawable icon = getFileIconByExtension(extension);
- String dateModified = getFormattedDateModified(file);
- String size = getHumanReadableFileSize(file);
+ drawableIdsMap.put(FileType.HTML, R.drawable.ic_type_html);
+ drawableIdsMap.put(FileType.PDF, R.drawable.ic_type_pdf);
+ drawableIdsMap.put(FileType.XLS, R.drawable.ic_type_xls);
+ drawableIdsMap.put(FileType.UNKNOWN, R.drawable.ic_type_unknown);
+ }
- LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View rowView = inflater.inflate(R.layout.file_list_item, parent, false);
+ public FileArrayAdapter(Context context, LayoutInfo layoutInfo, List files) {
+ this(context, layoutInfo, null, files);
+ }
- ImageView imageView = (ImageView) rowView.findViewById(R.id.file_list_item_icon);
- TextView labelView = (TextView) rowView.findViewById(R.id.file_list_item_label);
- TextView dateView = (TextView) rowView.findViewById(R.id.file_list_item_date);
- TextView sizeView = (TextView) rowView.findViewById(R.id.file_list_item_size);
+ public FileArrayAdapter(Context context, LayoutInfo layoutInfo,
+ EnumMap drawableIdsMap, List files) {
+ super(context, layoutInfo.layoutResId, files);
+ this.layoutInfo = layoutInfo;
+ this.drawableIdsMap = drawableIdsMap;
+ }
- imageView.setImageDrawable(icon);
- labelView.setText(baseName);
- dateView.setText(dateModified);
- sizeView.setText(size);
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ File file = getItem(position);
+
+ // reuse views
+ View rowView = convertView;
+ if (rowView == null) {
+ LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ rowView = inflater.inflate(layoutInfo.getLayoutResId(), parent, false);
+ // configure view holder
+ ViewHolder viewHolder = new ViewHolder();
+ viewHolder.iconView = (ImageView) rowView.findViewById(layoutInfo.getIconViewId());
+ viewHolder.labelView = (TextView) rowView.findViewById(layoutInfo.getLabelViewId());
+ viewHolder.dateView = (TextView) rowView.findViewById(layoutInfo.getDateViewId());
+ viewHolder.sizeView = (TextView) rowView.findViewById(layoutInfo.getSizeViewId());
+ rowView.setTag(viewHolder);
+ }
+ // fill data
+ ViewHolder viewHolder = (ViewHolder) rowView.getTag();
+ if (viewHolder.iconView != null && drawableIdsMap != null) {
+ String extension = FileUtils.getExtension(file.getName());
+ Drawable icon = getFileIconByExtension(extension);
+ viewHolder.iconView.setImageDrawable(icon);
+ }
+ if (viewHolder.labelView != null) {
+ String baseName = FileUtils.getBaseName(file.getName());
+ viewHolder.labelView.setText(baseName);
+ }
+ if (viewHolder.dateView != null) {
+ String dateModified = getFormattedDateModified(file);
+ viewHolder.dateView.setText(dateModified);
+ }
+ if (viewHolder.sizeView != null) {
+ String size = getHumanReadableFileSize(file);
+ viewHolder.sizeView.setText(size);
+ }
+ // return configured view
return rowView;
}
@@ -96,28 +139,20 @@ public View getView(int position, View convertView, ViewGroup parent) {
private Drawable getFileIconByExtension(String extension) {
FileType type = getFileTypeByExtension(extension);
+ int drawableResId = drawableIdsMap.get(type);
+ return getContext().getResources().getDrawable(drawableResId);
+ }
- Drawable fileIcon;
- switch (type) {
- case HTML:
- fileIcon = context.getResources().getDrawable(R.drawable.ic_type_html);
- break;
- case PDF:
- fileIcon = context.getResources().getDrawable(R.drawable.ic_type_pdf);
- break;
- case XLS:
- fileIcon = context.getResources().getDrawable(R.drawable.ic_type_xls);
- break;
- default:
- fileIcon = context.getResources().getDrawable(R.drawable.ic_type_unknown);
- break;
- }
-
- return fileIcon;
+ private FileType getFileTypeByExtension(String extension) {
+ try {
+ return FileType.valueOf(extension);
+ } catch (IllegalArgumentException ex) {
+ return FileType.UNKNOWN;
+ }
}
private String getFormattedDateModified(File file) {
- return DateUtils.formatDateTime(context, file.lastModified(),
+ return DateUtils.formatDateTime(getContext(), file.lastModified(),
DateUtils.FORMAT_SHOW_DATE |
DateUtils.FORMAT_SHOW_TIME |
DateUtils.FORMAT_SHOW_YEAR |
@@ -131,23 +166,70 @@ private String getHumanReadableFileSize(File file) {
return FileUtils.getHumanReadableByteCount(bytes);
}
- private FileType getFileTypeByExtension(String extension) {
- try {
- return FileType.valueOf(extension);
- } catch (IllegalArgumentException ex) {
- return FileType.UNKNOWN;
- }
- }
-
//---------------------------------------------------------------------
// Nested Classes
//---------------------------------------------------------------------
- private enum FileType {
+ public enum FileType {
HTML,
PDF,
XLS,
UNKNOWN
}
+ public static class LayoutInfo {
+ private int layoutResId;
+ private int iconViewId;
+ private int labelViewId;
+ private int dateViewId;
+ private int sizeViewId;
+
+ public LayoutInfo(int layoutResId) {
+ this.layoutResId = layoutResId;
+ }
+
+ public int getLayoutResId() {
+ return layoutResId;
+ }
+
+ public int getIconViewId() {
+ return iconViewId;
+ }
+
+ public void setIconViewId(int iconViewId) {
+ this.iconViewId = iconViewId;
+ }
+
+ public int getLabelViewId() {
+ return labelViewId;
+ }
+
+ public void setLabelViewId(int labelViewId) {
+ this.labelViewId = labelViewId;
+ }
+
+ public int getDateViewId() {
+ return dateViewId;
+ }
+
+ public void setDateViewId(int dateViewId) {
+ this.dateViewId = dateViewId;
+ }
+
+ public int getSizeViewId() {
+ return sizeViewId;
+ }
+
+ public void setSizeViewId(int sizeViewId) {
+ this.sizeViewId = sizeViewId;
+ }
+ }
+
+ private static class ViewHolder {
+ private ImageView iconView;
+ private TextView labelView;
+ private TextView dateView;
+ private TextView sizeView;
+ }
+
}
diff --git a/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/ResourceLookupArrayAdapter.java b/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/ResourceLookupArrayAdapter.java
index d4ae0656..886a653e 100644
--- a/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/ResourceLookupArrayAdapter.java
+++ b/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/ResourceLookupArrayAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 Jaspersoft Corporation. All rights reserved.
+ * Copyright (C) 2012-2014 Jaspersoft Corporation. All rights reserved.
* http://community.jaspersoft.com/project/mobile-sdk-android
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
@@ -35,8 +35,15 @@
import com.jaspersoft.android.sdk.client.oxm.resource.ResourceLookup;
import com.jaspersoft.android.sdk.ui.R;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.EnumMap;
import java.util.List;
+import static com.jaspersoft.android.sdk.client.oxm.resource.ResourceLookup.ResourceType;
+
/**
* A concrete ArrayAdapter that is backed by an array of ResourceLookup objects.
*
@@ -44,47 +51,174 @@
* @since 1.7
*/
public class ResourceLookupArrayAdapter extends ArrayAdapter{
- private final Context context;
- private final List resourceLookups;
+ private LayoutInfo layoutInfo;
+ private EnumMap drawableIdsMap;
+ private String datetimeFormatPattern = "yyyy-MM-dd HH:mm:ss";
+
+ public ResourceLookupArrayAdapter(Context context, LayoutInfo layoutInfo, List resourceLookups) {
+ this(context, layoutInfo, null, resourceLookups);
+ }
+
+ public ResourceLookupArrayAdapter(Context context, LayoutInfo layoutInfo,
+ EnumMap drawableIdsMap,
+ List resourceLookups) {
+ super(context, layoutInfo.layoutResId, resourceLookups);
+ this.layoutInfo = layoutInfo;
+ this.drawableIdsMap = drawableIdsMap;
+ }
+
+ @Deprecated
public ResourceLookupArrayAdapter(Context context, List resourceLookups) {
- super(context, R.layout.resource_list_item, resourceLookups);
- this.context = context;
- this.resourceLookups = resourceLookups;
+ this(context, new LayoutInfo(R.layout.resource_list_item),
+ new EnumMap(ResourceType.class), resourceLookups);
+
+ layoutInfo.setIconViewId(R.id.resource_list_item_icon);
+ layoutInfo.setLabelViewId(R.id.resource_list_item_label);
+ layoutInfo.setUriViewId(R.id.resource_list_item_uri);
+
+ drawableIdsMap.put(ResourceType.folder, R.drawable.ic_type_folder);
+ drawableIdsMap.put(ResourceType.reportUnit, R.drawable.ic_type_report);
+ drawableIdsMap.put(ResourceType.dashboard, R.drawable.ic_type_dashboard);
+ drawableIdsMap.put(ResourceType.unknown, R.drawable.ic_type_unknown);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- ResourceLookup resourceLookup = resourceLookups.get(position);
-
- Drawable drawable;
- switch (resourceLookup.getResourceType()) {
- case folder:
- drawable = context.getResources().getDrawable(R.drawable.ic_type_folder);
- break;
- case reportUnit:
- drawable = context.getResources().getDrawable(R.drawable.ic_type_report);
- break;
- case dashboard:
- drawable = context.getResources().getDrawable(R.drawable.ic_type_dashboard);
- break;
- default:
- // for an unknown resource
- drawable = context.getResources().getDrawable(R.drawable.ic_type_unknown);
- break;
- }
-
- LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View rowView = inflater.inflate(R.layout.resource_list_item, parent, false);
-
- ImageView image = (ImageView) rowView.findViewById(R.id.resource_list_item_icon);
- TextView label = (TextView) rowView.findViewById(R.id.resource_list_item_label);
- TextView uri = (TextView) rowView.findViewById(R.id.resource_list_item_uri);
-
- image.setImageDrawable(drawable);
- label.setText(resourceLookup.getLabel());
- uri.setText(resourceLookup.getUri());
-
+ ResourceLookup resourceLookup = getItem(position);
+ // reuse views
+ View rowView = convertView;
+ if (rowView == null) {
+ LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ rowView = inflater.inflate(layoutInfo.layoutResId, parent, false);
+ // configure view holder
+ ViewHolder viewHolder = new ViewHolder();
+ viewHolder.iconView = (ImageView) rowView.findViewById(layoutInfo.iconViewId);
+ viewHolder.labelView = (TextView) rowView.findViewById(layoutInfo.labelViewId);
+ viewHolder.descriptionView = (TextView) rowView.findViewById(layoutInfo.descriptionViewId);
+ viewHolder.dateView = (TextView) rowView.findViewById(layoutInfo.dateViewId);
+ viewHolder.uriView = (TextView) rowView.findViewById(layoutInfo.uriViewId);
+ rowView.setTag(viewHolder);
+ }
+ // fill data
+ ViewHolder viewHolder = (ViewHolder) rowView.getTag();
+ if (viewHolder.iconView != null && drawableIdsMap != null) {
+ Drawable icon = getIconByType(resourceLookup.getResourceType());
+ viewHolder.iconView.setImageDrawable(icon);
+ }
+ if (viewHolder.labelView != null) {
+ String label = resourceLookup.getLabel();
+ viewHolder.labelView.setText(label);
+ }
+ if (viewHolder.descriptionView != null) {
+ String description = resourceLookup.getDescription();
+ viewHolder.descriptionView.setText(description);
+ }
+ if (viewHolder.dateView != null) {
+ String date = formatDateString(resourceLookup.getUpdateDate());
+ viewHolder.dateView.setText(date);
+ }
+ if (viewHolder.uriView != null) {
+ String uri = resourceLookup.getUri();
+ viewHolder.uriView.setText(uri);
+ }
+ // return configured view
return rowView;
}
-}
+
+ public void setDatetimeFormatPattern(String datetimeFormatPattern) {
+ this.datetimeFormatPattern = datetimeFormatPattern;
+ }
+
+ //---------------------------------------------------------------------
+ // Helper methods
+ //---------------------------------------------------------------------
+
+ private Drawable getIconByType(ResourceType type) {
+ type = (drawableIdsMap.containsKey(type)) ? type : ResourceType.unknown;
+ int drawableResId = drawableIdsMap.get(type);
+ return getContext().getResources().getDrawable(drawableResId);
+ }
+
+ private String formatDateString(String updateDate) {
+ updateDate = (updateDate == null) ? "" : updateDate;
+ try {
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datetimeFormatPattern);
+ Date dateValue = simpleDateFormat.parse(updateDate);
+ DateFormat dateFormat = DateFormat.getDateInstance();
+ return dateFormat.format(dateValue);
+ } catch (ParseException ex) {
+ return updateDate;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ // Nested Classes
+ //---------------------------------------------------------------------
+
+ public static class LayoutInfo {
+ private int layoutResId;
+ private int iconViewId;
+ private int labelViewId;
+ private int descriptionViewId;
+ private int dateViewId;
+ private int uriViewId;
+
+ public LayoutInfo(int layoutResId) {
+ this.layoutResId = layoutResId;
+ }
+
+ public int getLayoutResId() {
+ return layoutResId;
+ }
+
+ public int getIconViewId() {
+ return iconViewId;
+ }
+
+ public void setIconViewId(int iconViewId) {
+ this.iconViewId = iconViewId;
+ }
+
+ public int getLabelViewId() {
+ return labelViewId;
+ }
+
+ public void setLabelViewId(int labelViewId) {
+ this.labelViewId = labelViewId;
+ }
+
+ public int getDescriptionViewId() {
+ return descriptionViewId;
+ }
+
+ public void setDescriptionViewId(int descriptionViewId) {
+ this.descriptionViewId = descriptionViewId;
+ }
+
+ public int getDateViewId() {
+ return dateViewId;
+ }
+
+ public void setDateViewId(int dateViewId) {
+ this.dateViewId = dateViewId;
+ }
+
+ public int getUriViewId() {
+ return uriViewId;
+ }
+
+ public void setUriViewId(int uriViewId) {
+ this.uriViewId = uriViewId;
+ }
+ }
+
+ private static class ViewHolder {
+ private ImageView iconView;
+ private TextView labelView;
+ private TextView descriptionView;
+ private TextView dateView;
+ private TextView uriView;
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/ResourceLookupEndlessAdapter.java b/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/ResourceLookupEndlessAdapter.java
new file mode 100644
index 00000000..4c1f7620
--- /dev/null
+++ b/ui/src/main/java/com/jaspersoft/android/sdk/ui/adapters/ResourceLookupEndlessAdapter.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2012-2014 Jaspersoft Corporation.
+ * Portions (C) 2008-2009 CommonsWare, LLC
+ * Portions (C) 2009 Google, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jaspersoft.android.sdk.ui.adapters;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import com.jaspersoft.android.sdk.client.oxm.resource.ResourceLookup;
+
+import java.util.EnumMap;
+import java.util.List;
+
+import static com.jaspersoft.android.sdk.client.oxm.resource.ResourceLookup.ResourceType;
+
+/**
+ * @author Ivan Gadzhega
+ * @since 2.0
+ */
+public class ResourceLookupEndlessAdapter extends ResourceLookupArrayAdapter {
+
+ private LayoutInfo layoutInfo;
+ private boolean keepOnAppending;
+ private View pendingView;
+
+ public ResourceLookupEndlessAdapter(Context context, LayoutInfo layoutInfo, List resourceLookups) {
+ super(context, layoutInfo, resourceLookups);
+ this.layoutInfo = layoutInfo;
+ }
+
+ public ResourceLookupEndlessAdapter(Context context, LayoutInfo layoutInfo, EnumMap drawableIdsMap,
+ List resourceLookups) {
+ super(context, layoutInfo, drawableIdsMap, resourceLookups);
+ this.layoutInfo = layoutInfo;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (keepOnAppending && position == super.getCount()) {
+ return getPendingView(parent);
+ } else {
+ return super.getView(position, convertView, parent);
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return (keepOnAppending) ? super.getCount() + 1 : super.getCount();
+ }
+
+ public int getItemViewType(int position) {
+ return (position < super.getCount()) ? super.getItemViewType(position) : IGNORE_ITEM_VIEW_TYPE;
+ }
+
+ public int getViewTypeCount() {
+ return super.getViewTypeCount() + 1;
+ }
+
+ @Override
+ public ResourceLookup getItem(int position) {
+ return (position < super.getCount()) ? super.getItem(position) : null;
+ }
+
+ //---------------------------------------------------------------------
+ // Helper methods
+ //---------------------------------------------------------------------
+
+ private View getPendingView(ViewGroup parent) {
+ if (pendingView == null) {
+ LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ pendingView = inflater.inflate(layoutInfo.getPendingViewResId(), parent, false);
+ }
+ return pendingView;
+ }
+
+ //---------------------------------------------------------------------
+ // Getters & Setters
+ //---------------------------------------------------------------------
+
+ public void setKeepOnAppending(boolean keepOnAppending) {
+ this.keepOnAppending = keepOnAppending;
+ }
+
+ public boolean isKeepOnAppending() {
+ return keepOnAppending;
+ }
+
+ //---------------------------------------------------------------------
+ // Nested Classes
+ //---------------------------------------------------------------------
+
+ public static class LayoutInfo extends ResourceLookupArrayAdapter.LayoutInfo {
+
+ private int pendingViewResId;
+
+ public LayoutInfo(int layoutResId) {
+ super(layoutResId);
+ }
+
+ public int getPendingViewResId() {
+ return pendingViewResId;
+ }
+
+ public void setPendingViewResId(int pendingViewResId) {
+ this.pendingViewResId = pendingViewResId;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/ui/src/main/java/com/jaspersoft/android/sdk/ui/widget/MultiSelectSpinner.java b/ui/src/main/java/com/jaspersoft/android/sdk/ui/widget/MultiSelectSpinner.java
index 2e027581..797a1f0a 100644
--- a/ui/src/main/java/com/jaspersoft/android/sdk/ui/widget/MultiSelectSpinner.java
+++ b/ui/src/main/java/com/jaspersoft/android/sdk/ui/widget/MultiSelectSpinner.java
@@ -28,11 +28,17 @@
import android.content.Context;
import android.content.DialogInterface;
import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
+import android.widget.Button;
import android.widget.Spinner;
+
import com.jaspersoft.android.sdk.ui.R;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -52,6 +58,7 @@ public class MultiSelectSpinner extends Spinner implements DialogInterface.On
private List items;
CharSequence[] stringItems;
private boolean[] checkedItems;
+ private boolean[] defaultCheckedItems;
/**
* the text that displays on the spinner if there is nothing selected.
*/
@@ -76,33 +83,25 @@ public MultiSelectSpinner(Context context, AttributeSet attrs, int defStyle) {
/**
* This method will be invoked when an item in the dialog is clicked.
*
- * @param dialog The dialog where the selection was made.
- * @param which The position of the item in the list that was clicked.
+ * @param dialog The dialog where the selection was made.
+ * @param which The position of the item in the list that was clicked.
* @param isChecked True if the click checked the item, else false.
*/
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
checkedItems[which] = isChecked;
+ updateState(false);
}
@Override
public boolean performClick() {
- AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
// The prompt to display when the dialog is shown
if (getPrompt() != null) {
builder.setTitle(getPrompt());
}
+ defaultCheckedItems = Arrays.copyOf(checkedItems, checkedItems.length);
builder.setMultiChoiceItems(stringItems, checkedItems, this);
- builder.setNegativeButton(R.string.mss_btn_uncheck_all,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- unselectAll();
- updateState();
- performClick();
- }
-
- });
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
@@ -110,14 +109,76 @@ public void onClick(DialogInterface dialog, int which) {
updateState();
}
});
- builder.show();
+ builder.setNegativeButton(R.string.mss_btn_check_all, null);
+
+ final AlertDialog dialog = builder.create();
+ dialog.setOnShowListener(new DialogInterface.OnShowListener() {
+ @Override
+ public void onShow(DialogInterface dialogInterface) {
+ dialog.getListView().setAdapter(initCustomAdapter(dialog));
+ Button button = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
+ button.setText(ifAnyChecked() ? R.string.mss_btn_uncheck_all : R.string.mss_btn_check_all);
+
+ dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
+ .setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Button button = (Button) view;
+ boolean ifAnyChecked = ifAnyChecked();
+ button.setText(ifAnyChecked ? R.string.mss_btn_check_all : R.string.mss_btn_uncheck_all);
+
+ if (ifAnyChecked) {
+ unselectAll();
+ } else {
+ selectAll();
+ }
+
+ dialog.getListView().setAdapter(initCustomAdapter(dialog));
+ updateState(false);
+ }
+ });
+ }
+ });
+ dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ checkedItems = defaultCheckedItems;
+ updateState(false);
+ }
+ });
+ dialog.show();
return true;
}
+ private boolean ifAnyChecked() {
+ boolean ifAnyCheckedMask = false;
+ for (boolean checkedItem : checkedItems) {
+ ifAnyCheckedMask = ifAnyCheckedMask || checkedItem;
+ }
+ return ifAnyCheckedMask;
+ }
+
+ private BaseAdapter initCustomAdapter(final AlertDialog dialog) {
+ return new ArrayAdapter(
+ getContext(), R.layout.select_dialog_multichoice, android.R.id.text1, stringItems) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View view = super.getView(position, convertView, parent);
+ if (checkedItems != null) {
+ boolean isItemChecked = checkedItems[position];
+ if (isItemChecked) {
+ dialog.getListView().setItemChecked(position, true);
+ }
+ }
+ return view;
+ }
+ };
+ }
+
/**
* Gets a list of items displayed in the spinner.
*
- * @return list of items
+ * @return list of items
*/
public List getItems() {
return items;
@@ -135,7 +196,7 @@ public void setItemsList(List items) {
/**
* Sets a list of items to be displayed in the spinner.
*
- * @param items list of items
+ * @param items list of items
* @param defaultText the text that displays on the spinner if there is nothing selected.
*/
public void setItemsList(List items, String defaultText) {
@@ -154,7 +215,7 @@ public void setItemsList(List items, String defaultText) {
}
ArrayAdapter adapter = new ArrayAdapter(getContext(),
- android.R.layout.simple_spinner_item, new String[] { defaultText });
+ android.R.layout.simple_spinner_item, new String[]{defaultText});
setAdapter(adapter);
}
@@ -206,7 +267,7 @@ public void setSelection(List positions) {
*/
public List getSelectedItems() {
List selectedItems = new ArrayList();
- for(Integer position : getSelectedItemsPositions()) {
+ for (Integer position : getSelectedItemsPositions()) {
selectedItems.add(items.get(position));
}
return selectedItems;
@@ -234,11 +295,15 @@ public void setSelection(int position, boolean animate) {
//---------------------------------------------------------------------
private void updateState() {
+ updateState(true);
+ }
+
+ private void updateState(boolean notifyListener) {
// refresh text on spinner
StringBuilder spinnerBuilder = new StringBuilder();
for (int i = 0; i < stringItems.length; i++) {
if (checkedItems[i]) {
- if(spinnerBuilder.length() > 0) {
+ if (spinnerBuilder.length() > 0) {
spinnerBuilder.append(TEXT_SEPARATOR);
}
if (spinnerBuilder.length() > TEXT_MAX_LENGTH) {
@@ -249,21 +314,29 @@ private void updateState() {
}
}
- String spinnerText = (spinnerBuilder.length() > 0) ? spinnerBuilder.toString() : defaultText ;
+ String spinnerText = (spinnerBuilder.length() > 0) ? spinnerBuilder.toString() : defaultText;
ArrayAdapter adapter = new ArrayAdapter(getContext(),
android.R.layout.simple_spinner_item,
- new String[] { spinnerText });
+ new String[]{spinnerText});
setAdapter(adapter);
- if (onItemsSelectedListener != null) {
+ if (onItemsSelectedListener != null && notifyListener) {
onItemsSelectedListener.onItemsSelected(getSelectedItems());
}
}
+ private void selectAll() {
+ setSelection(true);
+ }
+
private void unselectAll() {
- for (int i=0; i < checkedItems.length; i++) {
- checkedItems[i] = false;
+ setSelection(false);
+ }
+
+ private void setSelection(boolean isSelected) {
+ for (int i = 0; i < checkedItems.length; i++) {
+ checkedItems[i] = isSelected;
}
}
}
diff --git a/ui/res/color/cs_blue_white.xml b/ui/src/main/res/color/cs_blue_white.xml
similarity index 100%
rename from ui/res/color/cs_blue_white.xml
rename to ui/src/main/res/color/cs_blue_white.xml
diff --git a/ui/res/color/cs_dark_grey_white.xml b/ui/src/main/res/color/cs_dark_grey_white.xml
similarity index 100%
rename from ui/res/color/cs_dark_grey_white.xml
rename to ui/src/main/res/color/cs_dark_grey_white.xml
diff --git a/ui/res/color/cs_grey_white.xml b/ui/src/main/res/color/cs_grey_white.xml
similarity index 100%
rename from ui/res/color/cs_grey_white.xml
rename to ui/src/main/res/color/cs_grey_white.xml
diff --git a/ui/src/main/res/color/cs_light_grey_white.xml b/ui/src/main/res/color/cs_light_grey_white.xml
new file mode 100644
index 00000000..779785f7
--- /dev/null
+++ b/ui/src/main/res/color/cs_light_grey_white.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ui/res/color/cs_orange_white.xml b/ui/src/main/res/color/cs_orange_white.xml
similarity index 100%
rename from ui/res/color/cs_orange_white.xml
rename to ui/src/main/res/color/cs_orange_white.xml
diff --git a/ui/res/drawable-hdpi/ic_action_add.png b/ui/src/main/res/drawable-hdpi/ic_action_add.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_action_add.png
rename to ui/src/main/res/drawable-hdpi/ic_action_add.png
diff --git a/ui/src/main/res/drawable-hdpi/ic_action_date_picker.png b/ui/src/main/res/drawable-hdpi/ic_action_date_picker.png
new file mode 100644
index 00000000..eb14c4d8
Binary files /dev/null and b/ui/src/main/res/drawable-hdpi/ic_action_date_picker.png differ
diff --git a/ui/src/main/res/drawable-hdpi/ic_action_time_picker.png b/ui/src/main/res/drawable-hdpi/ic_action_time_picker.png
new file mode 100644
index 00000000..96c2b0ed
Binary files /dev/null and b/ui/src/main/res/drawable-hdpi/ic_action_time_picker.png differ
diff --git a/ui/res/drawable-hdpi/ic_menu_add.png b/ui/src/main/res/drawable-hdpi/ic_menu_add.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_menu_add.png
rename to ui/src/main/res/drawable-hdpi/ic_menu_add.png
diff --git a/ui/res/drawable-hdpi/ic_menu_logout.png b/ui/src/main/res/drawable-hdpi/ic_menu_logout.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_menu_logout.png
rename to ui/src/main/res/drawable-hdpi/ic_menu_logout.png
diff --git a/ui/res/drawable-hdpi/ic_menu_refresh.png b/ui/src/main/res/drawable-hdpi/ic_menu_refresh.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_menu_refresh.png
rename to ui/src/main/res/drawable-hdpi/ic_menu_refresh.png
diff --git a/ui/res/drawable-hdpi/ic_menu_server_profile.png b/ui/src/main/res/drawable-hdpi/ic_menu_server_profile.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_menu_server_profile.png
rename to ui/src/main/res/drawable-hdpi/ic_menu_server_profile.png
diff --git a/ui/res/drawable-hdpi/ic_type_dashboard.png b/ui/src/main/res/drawable-hdpi/ic_type_dashboard.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_type_dashboard.png
rename to ui/src/main/res/drawable-hdpi/ic_type_dashboard.png
diff --git a/ui/res/drawable-hdpi/ic_type_folder.png b/ui/src/main/res/drawable-hdpi/ic_type_folder.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_type_folder.png
rename to ui/src/main/res/drawable-hdpi/ic_type_folder.png
diff --git a/ui/res/drawable-hdpi/ic_type_html.png b/ui/src/main/res/drawable-hdpi/ic_type_html.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_type_html.png
rename to ui/src/main/res/drawable-hdpi/ic_type_html.png
diff --git a/ui/res/drawable-hdpi/ic_type_image.png b/ui/src/main/res/drawable-hdpi/ic_type_image.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_type_image.png
rename to ui/src/main/res/drawable-hdpi/ic_type_image.png
diff --git a/ui/res/drawable-hdpi/ic_type_pdf.png b/ui/src/main/res/drawable-hdpi/ic_type_pdf.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_type_pdf.png
rename to ui/src/main/res/drawable-hdpi/ic_type_pdf.png
diff --git a/ui/res/drawable-hdpi/ic_type_report.png b/ui/src/main/res/drawable-hdpi/ic_type_report.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_type_report.png
rename to ui/src/main/res/drawable-hdpi/ic_type_report.png
diff --git a/ui/res/drawable-hdpi/ic_type_server_profile.png b/ui/src/main/res/drawable-hdpi/ic_type_server_profile.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_type_server_profile.png
rename to ui/src/main/res/drawable-hdpi/ic_type_server_profile.png
diff --git a/ui/res/drawable-hdpi/ic_type_text.png b/ui/src/main/res/drawable-hdpi/ic_type_text.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_type_text.png
rename to ui/src/main/res/drawable-hdpi/ic_type_text.png
diff --git a/ui/res/drawable-hdpi/ic_type_unknown.png b/ui/src/main/res/drawable-hdpi/ic_type_unknown.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_type_unknown.png
rename to ui/src/main/res/drawable-hdpi/ic_type_unknown.png
diff --git a/ui/res/drawable-hdpi/ic_type_xls.png b/ui/src/main/res/drawable-hdpi/ic_type_xls.png
similarity index 100%
rename from ui/res/drawable-hdpi/ic_type_xls.png
rename to ui/src/main/res/drawable-hdpi/ic_type_xls.png
diff --git a/ui/res/drawable-ldpi/ic_action_add.png b/ui/src/main/res/drawable-ldpi/ic_action_add.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_action_add.png
rename to ui/src/main/res/drawable-ldpi/ic_action_add.png
diff --git a/ui/src/main/res/drawable-ldpi/ic_action_date_picker.png b/ui/src/main/res/drawable-ldpi/ic_action_date_picker.png
new file mode 100644
index 00000000..233e7b65
Binary files /dev/null and b/ui/src/main/res/drawable-ldpi/ic_action_date_picker.png differ
diff --git a/ui/src/main/res/drawable-ldpi/ic_action_time_picker.png b/ui/src/main/res/drawable-ldpi/ic_action_time_picker.png
new file mode 100644
index 00000000..2a23d6b6
Binary files /dev/null and b/ui/src/main/res/drawable-ldpi/ic_action_time_picker.png differ
diff --git a/ui/res/drawable-ldpi/ic_menu_add.png b/ui/src/main/res/drawable-ldpi/ic_menu_add.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_menu_add.png
rename to ui/src/main/res/drawable-ldpi/ic_menu_add.png
diff --git a/ui/res/drawable-ldpi/ic_menu_logout.png b/ui/src/main/res/drawable-ldpi/ic_menu_logout.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_menu_logout.png
rename to ui/src/main/res/drawable-ldpi/ic_menu_logout.png
diff --git a/ui/res/drawable-ldpi/ic_menu_refresh.png b/ui/src/main/res/drawable-ldpi/ic_menu_refresh.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_menu_refresh.png
rename to ui/src/main/res/drawable-ldpi/ic_menu_refresh.png
diff --git a/ui/res/drawable-ldpi/ic_menu_server_profile.png b/ui/src/main/res/drawable-ldpi/ic_menu_server_profile.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_menu_server_profile.png
rename to ui/src/main/res/drawable-ldpi/ic_menu_server_profile.png
diff --git a/ui/res/drawable-ldpi/ic_type_dashboard.png b/ui/src/main/res/drawable-ldpi/ic_type_dashboard.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_type_dashboard.png
rename to ui/src/main/res/drawable-ldpi/ic_type_dashboard.png
diff --git a/ui/res/drawable-ldpi/ic_type_folder.png b/ui/src/main/res/drawable-ldpi/ic_type_folder.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_type_folder.png
rename to ui/src/main/res/drawable-ldpi/ic_type_folder.png
diff --git a/ui/res/drawable-ldpi/ic_type_html.png b/ui/src/main/res/drawable-ldpi/ic_type_html.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_type_html.png
rename to ui/src/main/res/drawable-ldpi/ic_type_html.png
diff --git a/ui/res/drawable-ldpi/ic_type_image.png b/ui/src/main/res/drawable-ldpi/ic_type_image.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_type_image.png
rename to ui/src/main/res/drawable-ldpi/ic_type_image.png
diff --git a/ui/res/drawable-ldpi/ic_type_pdf.png b/ui/src/main/res/drawable-ldpi/ic_type_pdf.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_type_pdf.png
rename to ui/src/main/res/drawable-ldpi/ic_type_pdf.png
diff --git a/ui/res/drawable-ldpi/ic_type_report.png b/ui/src/main/res/drawable-ldpi/ic_type_report.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_type_report.png
rename to ui/src/main/res/drawable-ldpi/ic_type_report.png
diff --git a/ui/res/drawable-ldpi/ic_type_server_profile.png b/ui/src/main/res/drawable-ldpi/ic_type_server_profile.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_type_server_profile.png
rename to ui/src/main/res/drawable-ldpi/ic_type_server_profile.png
diff --git a/ui/res/drawable-ldpi/ic_type_text.png b/ui/src/main/res/drawable-ldpi/ic_type_text.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_type_text.png
rename to ui/src/main/res/drawable-ldpi/ic_type_text.png
diff --git a/ui/res/drawable-ldpi/ic_type_unknown.png b/ui/src/main/res/drawable-ldpi/ic_type_unknown.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_type_unknown.png
rename to ui/src/main/res/drawable-ldpi/ic_type_unknown.png
diff --git a/ui/res/drawable-ldpi/ic_type_xls.png b/ui/src/main/res/drawable-ldpi/ic_type_xls.png
similarity index 100%
rename from ui/res/drawable-ldpi/ic_type_xls.png
rename to ui/src/main/res/drawable-ldpi/ic_type_xls.png
diff --git a/ui/res/drawable-mdpi/ic_action_add.png b/ui/src/main/res/drawable-mdpi/ic_action_add.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_action_add.png
rename to ui/src/main/res/drawable-mdpi/ic_action_add.png
diff --git a/ui/src/main/res/drawable-mdpi/ic_action_date_picker.png b/ui/src/main/res/drawable-mdpi/ic_action_date_picker.png
new file mode 100644
index 00000000..07c23848
Binary files /dev/null and b/ui/src/main/res/drawable-mdpi/ic_action_date_picker.png differ
diff --git a/ui/src/main/res/drawable-mdpi/ic_action_time_picker.png b/ui/src/main/res/drawable-mdpi/ic_action_time_picker.png
new file mode 100644
index 00000000..407be1d0
Binary files /dev/null and b/ui/src/main/res/drawable-mdpi/ic_action_time_picker.png differ
diff --git a/ui/res/drawable-mdpi/ic_menu_add.png b/ui/src/main/res/drawable-mdpi/ic_menu_add.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_menu_add.png
rename to ui/src/main/res/drawable-mdpi/ic_menu_add.png
diff --git a/ui/res/drawable-mdpi/ic_menu_logout.png b/ui/src/main/res/drawable-mdpi/ic_menu_logout.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_menu_logout.png
rename to ui/src/main/res/drawable-mdpi/ic_menu_logout.png
diff --git a/ui/res/drawable-mdpi/ic_menu_refresh.png b/ui/src/main/res/drawable-mdpi/ic_menu_refresh.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_menu_refresh.png
rename to ui/src/main/res/drawable-mdpi/ic_menu_refresh.png
diff --git a/ui/res/drawable-mdpi/ic_menu_server_profile.png b/ui/src/main/res/drawable-mdpi/ic_menu_server_profile.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_menu_server_profile.png
rename to ui/src/main/res/drawable-mdpi/ic_menu_server_profile.png
diff --git a/ui/res/drawable-mdpi/ic_type_dashboard.png b/ui/src/main/res/drawable-mdpi/ic_type_dashboard.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_type_dashboard.png
rename to ui/src/main/res/drawable-mdpi/ic_type_dashboard.png
diff --git a/ui/res/drawable-mdpi/ic_type_folder.png b/ui/src/main/res/drawable-mdpi/ic_type_folder.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_type_folder.png
rename to ui/src/main/res/drawable-mdpi/ic_type_folder.png
diff --git a/ui/res/drawable-mdpi/ic_type_html.png b/ui/src/main/res/drawable-mdpi/ic_type_html.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_type_html.png
rename to ui/src/main/res/drawable-mdpi/ic_type_html.png
diff --git a/ui/res/drawable-mdpi/ic_type_image.png b/ui/src/main/res/drawable-mdpi/ic_type_image.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_type_image.png
rename to ui/src/main/res/drawable-mdpi/ic_type_image.png
diff --git a/ui/res/drawable-mdpi/ic_type_pdf.png b/ui/src/main/res/drawable-mdpi/ic_type_pdf.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_type_pdf.png
rename to ui/src/main/res/drawable-mdpi/ic_type_pdf.png
diff --git a/ui/res/drawable-mdpi/ic_type_report.png b/ui/src/main/res/drawable-mdpi/ic_type_report.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_type_report.png
rename to ui/src/main/res/drawable-mdpi/ic_type_report.png
diff --git a/ui/res/drawable-mdpi/ic_type_server_profile.png b/ui/src/main/res/drawable-mdpi/ic_type_server_profile.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_type_server_profile.png
rename to ui/src/main/res/drawable-mdpi/ic_type_server_profile.png
diff --git a/ui/res/drawable-mdpi/ic_type_text.png b/ui/src/main/res/drawable-mdpi/ic_type_text.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_type_text.png
rename to ui/src/main/res/drawable-mdpi/ic_type_text.png
diff --git a/ui/res/drawable-mdpi/ic_type_unknown.png b/ui/src/main/res/drawable-mdpi/ic_type_unknown.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_type_unknown.png
rename to ui/src/main/res/drawable-mdpi/ic_type_unknown.png
diff --git a/ui/res/drawable-mdpi/ic_type_xls.png b/ui/src/main/res/drawable-mdpi/ic_type_xls.png
similarity index 100%
rename from ui/res/drawable-mdpi/ic_type_xls.png
rename to ui/src/main/res/drawable-mdpi/ic_type_xls.png
diff --git a/ui/res/drawable-xhdpi/ic_action_add.png b/ui/src/main/res/drawable-xhdpi/ic_action_add.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_action_add.png
rename to ui/src/main/res/drawable-xhdpi/ic_action_add.png
diff --git a/ui/src/main/res/drawable-xhdpi/ic_action_date_picker.png b/ui/src/main/res/drawable-xhdpi/ic_action_date_picker.png
new file mode 100644
index 00000000..33e96272
Binary files /dev/null and b/ui/src/main/res/drawable-xhdpi/ic_action_date_picker.png differ
diff --git a/ui/src/main/res/drawable-xhdpi/ic_action_time_picker.png b/ui/src/main/res/drawable-xhdpi/ic_action_time_picker.png
new file mode 100644
index 00000000..68d5de0b
Binary files /dev/null and b/ui/src/main/res/drawable-xhdpi/ic_action_time_picker.png differ
diff --git a/ui/res/drawable-xhdpi/ic_menu_add.png b/ui/src/main/res/drawable-xhdpi/ic_menu_add.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_menu_add.png
rename to ui/src/main/res/drawable-xhdpi/ic_menu_add.png
diff --git a/ui/res/drawable-xhdpi/ic_menu_logout.png b/ui/src/main/res/drawable-xhdpi/ic_menu_logout.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_menu_logout.png
rename to ui/src/main/res/drawable-xhdpi/ic_menu_logout.png
diff --git a/ui/res/drawable-xhdpi/ic_menu_refresh.png b/ui/src/main/res/drawable-xhdpi/ic_menu_refresh.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_menu_refresh.png
rename to ui/src/main/res/drawable-xhdpi/ic_menu_refresh.png
diff --git a/ui/res/drawable-xhdpi/ic_menu_server_profile.png b/ui/src/main/res/drawable-xhdpi/ic_menu_server_profile.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_menu_server_profile.png
rename to ui/src/main/res/drawable-xhdpi/ic_menu_server_profile.png
diff --git a/ui/res/drawable-xhdpi/ic_type_dashboard.png b/ui/src/main/res/drawable-xhdpi/ic_type_dashboard.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_type_dashboard.png
rename to ui/src/main/res/drawable-xhdpi/ic_type_dashboard.png
diff --git a/ui/res/drawable-xhdpi/ic_type_folder.png b/ui/src/main/res/drawable-xhdpi/ic_type_folder.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_type_folder.png
rename to ui/src/main/res/drawable-xhdpi/ic_type_folder.png
diff --git a/ui/res/drawable-xhdpi/ic_type_html.png b/ui/src/main/res/drawable-xhdpi/ic_type_html.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_type_html.png
rename to ui/src/main/res/drawable-xhdpi/ic_type_html.png
diff --git a/ui/res/drawable-xhdpi/ic_type_image.png b/ui/src/main/res/drawable-xhdpi/ic_type_image.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_type_image.png
rename to ui/src/main/res/drawable-xhdpi/ic_type_image.png
diff --git a/ui/res/drawable-xhdpi/ic_type_pdf.png b/ui/src/main/res/drawable-xhdpi/ic_type_pdf.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_type_pdf.png
rename to ui/src/main/res/drawable-xhdpi/ic_type_pdf.png
diff --git a/ui/res/drawable-xhdpi/ic_type_report.png b/ui/src/main/res/drawable-xhdpi/ic_type_report.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_type_report.png
rename to ui/src/main/res/drawable-xhdpi/ic_type_report.png
diff --git a/ui/res/drawable-xhdpi/ic_type_server_profile.png b/ui/src/main/res/drawable-xhdpi/ic_type_server_profile.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_type_server_profile.png
rename to ui/src/main/res/drawable-xhdpi/ic_type_server_profile.png
diff --git a/ui/res/drawable-xhdpi/ic_type_text.png b/ui/src/main/res/drawable-xhdpi/ic_type_text.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_type_text.png
rename to ui/src/main/res/drawable-xhdpi/ic_type_text.png
diff --git a/ui/res/drawable-xhdpi/ic_type_unknown.png b/ui/src/main/res/drawable-xhdpi/ic_type_unknown.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_type_unknown.png
rename to ui/src/main/res/drawable-xhdpi/ic_type_unknown.png
diff --git a/ui/res/drawable-xhdpi/ic_type_xls.png b/ui/src/main/res/drawable-xhdpi/ic_type_xls.png
similarity index 100%
rename from ui/res/drawable-xhdpi/ic_type_xls.png
rename to ui/src/main/res/drawable-xhdpi/ic_type_xls.png
diff --git a/ui/res/drawable/bs_white_blue.xml b/ui/src/main/res/drawable/bs_white_blue.xml
similarity index 100%
rename from ui/res/drawable/bs_white_blue.xml
rename to ui/src/main/res/drawable/bs_white_blue.xml
diff --git a/ui/res/drawable/gradient_light_grey.xml b/ui/src/main/res/drawable/gradient_light_grey.xml
similarity index 100%
rename from ui/res/drawable/gradient_light_grey.xml
rename to ui/src/main/res/drawable/gradient_light_grey.xml
diff --git a/ui/res/layout/file_list_item.xml b/ui/src/main/res/layout/file_list_item.xml
similarity index 100%
rename from ui/res/layout/file_list_item.xml
rename to ui/src/main/res/layout/file_list_item.xml
diff --git a/ui/res/layout/ic_boolean_layout.xml b/ui/src/main/res/layout/ic_boolean_layout.xml
similarity index 100%
rename from ui/res/layout/ic_boolean_layout.xml
rename to ui/src/main/res/layout/ic_boolean_layout.xml
diff --git a/ui/res/layout/ic_multi_select_layout.xml b/ui/src/main/res/layout/ic_multi_select_layout.xml
similarity index 100%
rename from ui/res/layout/ic_multi_select_layout.xml
rename to ui/src/main/res/layout/ic_multi_select_layout.xml
diff --git a/ui/res/layout/ic_single_select_layout.xml b/ui/src/main/res/layout/ic_single_select_layout.xml
similarity index 100%
rename from ui/res/layout/ic_single_select_layout.xml
rename to ui/src/main/res/layout/ic_single_select_layout.xml
diff --git a/ui/res/layout/ic_single_value_date_layout.xml b/ui/src/main/res/layout/ic_single_value_date_layout.xml
similarity index 100%
rename from ui/res/layout/ic_single_value_date_layout.xml
rename to ui/src/main/res/layout/ic_single_value_date_layout.xml
diff --git a/ui/res/layout/ic_single_value_layout.xml b/ui/src/main/res/layout/ic_single_value_layout.xml
similarity index 100%
rename from ui/res/layout/ic_single_value_layout.xml
rename to ui/src/main/res/layout/ic_single_value_layout.xml
diff --git a/ui/res/layout/resource_list_item.xml b/ui/src/main/res/layout/resource_list_item.xml
similarity index 100%
rename from ui/res/layout/resource_list_item.xml
rename to ui/src/main/res/layout/resource_list_item.xml
diff --git a/ui/src/main/res/layout/select_dialog_multichoice.xml b/ui/src/main/res/layout/select_dialog_multichoice.xml
new file mode 100644
index 00000000..40034a85
--- /dev/null
+++ b/ui/src/main/res/layout/select_dialog_multichoice.xml
@@ -0,0 +1,31 @@
+
+
+
+
\ No newline at end of file
diff --git a/ui/res/layout/server_profile_list_item.xml b/ui/src/main/res/layout/server_profile_list_item.xml
similarity index 100%
rename from ui/res/layout/server_profile_list_item.xml
rename to ui/src/main/res/layout/server_profile_list_item.xml
diff --git a/ui/res/layout/two_line_breadcrumbs.xml b/ui/src/main/res/layout/two_line_breadcrumbs.xml
similarity index 100%
rename from ui/res/layout/two_line_breadcrumbs.xml
rename to ui/src/main/res/layout/two_line_breadcrumbs.xml
diff --git a/ui/res/values/colors.xml b/ui/src/main/res/values/colors.xml
similarity index 92%
rename from ui/res/values/colors.xml
rename to ui/src/main/res/values/colors.xml
index 2ad043c8..3f16d15a 100644
--- a/ui/res/values/colors.xml
+++ b/ui/src/main/res/values/colors.xml
@@ -1,6 +1,6 @@
#333333
#7d7d7d
- #c0c0c0
+ #949494
#e7e7e7
#ff0000
diff --git a/ui/res/values/strings.xml b/ui/src/main/res/values/strings.xml
similarity index 90%
rename from ui/res/values/strings.xml
rename to ui/src/main/res/values/strings.xml
index bd62f620..89c37cec 100644
--- a/ui/res/values/strings.xml
+++ b/ui/src/main/res/values/strings.xml
@@ -26,6 +26,7 @@
- Uncheck All
+ Check all
+ Uncheck all
diff --git a/ui/res/values/styles.xml b/ui/src/main/res/values/styles.xml
similarity index 93%
rename from ui/res/values/styles.xml
rename to ui/src/main/res/values/styles.xml
index 167ff1bc..0e962390 100644
--- a/ui/res/values/styles.xml
+++ b/ui/src/main/res/values/styles.xml
@@ -30,7 +30,7 @@
@@ -57,7 +57,7 @@
@@ -79,7 +79,7 @@
@@ -116,7 +116,7 @@
@@ -131,7 +131,7 @@
@@ -171,7 +171,7 @@
- @drawable/gradient_light_grey
- center_vertical
- 45dp
- - fill_parent
+ - match_parent