diff --git a/CHANGELOG.md b/CHANGELOG.md index f8c9b0a0..7981a04d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Change Log ========== +Version 2.0.0 *(in development)* +-------------------------------- + * .. + + Version 1.0.10 *(2014-11-28)* ----------------------------- * Fix: RxJava now defers to IO thread. diff --git a/README.md b/README.md index a20856f3..35346eae 100644 --- a/README.md +++ b/README.md @@ -16,12 +16,12 @@ Grab via Maven: com.contentful.java java-sdk - 1.0.10 + 2.0.0 ``` or Gradle: ```groovy -compile 'com.contentful.java:java-sdk:1.0.10' +compile 'com.contentful.java:java-sdk:2.0.0' ``` The SDK requires at minimum Java 6 or Android 2.3. @@ -40,8 +40,8 @@ You can also specify a custom client to be used, refer to the [official document -dontwarn rx.** -dontwarn retrofit.** -keep class retrofit.** { *; } --keep class com.contentful.java.** { *; } --keep class * extends com.contentful.java.model.** { *; } +-keep class com.contentful.java.cda.** { *; } +-keep class * extends com.contentful.java.cda.model.** { *; } -keep class com.google.gson.** { *; } -keep class sun.misc.Unsafe { *; } ``` @@ -52,33 +52,59 @@ Usage The `CDAClient` manages all your interaction with the Contentful Delivery API. ```java CDAClient client = new CDAClient.Builder() - .setSpaceKey("space-key-goes-here") - .setAccessToken("access-token-goes-here") - .build(); + .setSpaceKey("space-key-goes-here") + .setAccessToken("access-token-goes-here") + .build(); ``` -Items can be fetched synchronously: +A client can perform various operations on different types of resources (Assets, Content Types, Entries and Spaces). Every type of resource is represented by a module in the `CDAClient` class, for example: + +```java +client.assets() // returns the Assets module +client.contentTypes() // returns the Content Types module +client.entries() // returns the Entries module +client.spaces() // returns the Spaces module +client.sync() // returns the Synchronization module +``` + +Each module contains a set of methods which can be used to perform various operations on the specified resource type. Every method has a corresponding asynchronous extension which can be accessed through the `async()` method of the module, for example: + +Retrieving all entries (synchronously): + ```java try { - CDAArray array = client.fetchEntriesBlocking(); - // success + CDAArray result = client.entries().fetchAll(); + // success } catch (RetrofitError e) { - // failure + // failure } ``` -Or asynchronously: +or asynchronously: + +```java +client.entries().async().fetchAll(new CDACallback() { + @Override protected void onSuccess(CDAArray result) { + // success + } + + @Override protected void onFailure(RetrofitError error) { + // failure + } +}); +``` + +or with RxJava: + ```java -client.fetchEntries(new CDACallback() { - @Override - protected void onSuccess(CDAArray array, Response response) { - // success - } - - @Override - protected void onFailure(RetrofitError retrofitError) { - // failure - } +client.entries().rx().fetchAll().subscribe(new Action1() { + @Override public void call(CDAArray result) { + // success + } +}, new Action1() { + @Override public void call(Throwable throwable) { + // failure + } }); ``` @@ -91,32 +117,38 @@ client.fetchEntries(cb = new CDACallback() { ... }); -cb.cancel(); // onSuccess and onFailure will not be invoked. +cb.cancel(); // onSuccess and onFailure will not be invoked ``` ### Default Ordering -Bear in mind that there is no default ordering included for any method which returns a `CDAArray` instance. This means that if you plan to page through more than 100 results with multiple requests, there is no guarantee that you will cover all entries. It is however possible to specify ordering for a query with any of the `fetch*Matching*` methods, for instance: +Bear in mind that there is no default ordering included for any method which returns a `CDAArray` instance. This means that if you plan to page through more than 100 results with multiple requests, there is no guarantee that you will cover all entries. It is however possible to specify ordering for a query using the `fetchAll()` methods that take a query parameter, for instance: ```java -client.fetchEntriesMatching(new HashMap() {{ - put("order", "-sys.createdAt"); +client.entries().async().fetchAll(new HashMap() {{ + put("order", "-sys.createdAt"); }}, new CDACallback() { - @Override - protected void onSuccess(CDAArray array, Response response) { - // ... - } -}); + @Override protected void onSuccess(CDAArray result) { + // ... + } +}); ``` -The above snippet will fetch all Entries, ordered by newest-to-oldest. Another important thing is that if you use the `fetchArrayNextPage()` method with a `CDAArray` instance which was fetched with specific ordering, the original request parameters will be used, hence that specified ordering will be preserved. +The above snippet will fetch all Entries, ordered by newest-to-oldest. ### Using Custom Entry Classes -You might want to subclass `CDAEntry` to store additional data alongside Entries or to decouple the rest of your app from the Contentful SDK's API. For this purpose, it is possible to register your own custom classes for specific Content Types, like this: +You might want to subclass `CDAEntry` to store additional data alongside Entries or to decouple the rest of your app from the Contentful SDK's API. For this purpose, it is possible to register your own custom classes for specific Content Types, when creating a client: ```java -client.registerCustomClass("content-type-id-goes-here", CustomEntry.class); +HashMap> classMap = new HashMap>(); +classMap.put("content-type-id", CustomEntry.class); + +CDAClient client = new Builder() + .setSpaceKey("space-key-goes-here") + .setAccessToken("access-token-goes-here") + .setCustomClasses(classMap) + .build(); ``` Each time, the receiver needs to create a new Entry object of the given Content Type, it will create instances of `CustomEntry`. Make sure that the class inherits from `CDAEntry`. @@ -137,6 +169,7 @@ CDAResource resource = ResourceUtils.readResourceFromFile(new File("/path/to/res ``` Note that in case you attempt to restore a previously saved Resource, if the original class does not exist the `readResourceFromFile()` method will throw a `ClassNotFoundException`. +Another important thing to note is that this method is not the most efficient in terms of performance, as it relies heavily on reflection. If you need to persist large objects consider alternate storage solutions. ### Preview Mode @@ -144,10 +177,10 @@ The Content Delivery API only returns published Entries. However, you might want ```java CDAClient client = new CDAClient.Builder() - .setSpaceKey("space-key-goes-here") - .setAccessToken("access-token-goes-here") - .preview() - .build(); + .setSpaceKey("space-key-goes-here") + .setAccessToken("access-token-goes-here") + .preview() + .build(); ``` Apart from the configuration option, you can use the SDK without modifications with one exception: you need to obtain a preview access token, which you can get in the "API" tab of the Contentful app. In preview mode, data can be invalid, because no validation is performed on unpublished entries. Your app needs to deal with that. Be aware that the access token is read-write and should in no case be shipped with a production app. @@ -164,7 +197,7 @@ Copyright (c) 2014 Contentful GmbH. See [LICENSE.txt][6] for further details. [1]: https://www.contentful.com - [2]: https://oss.sonatype.org/service/local/repositories/releases/content/com/contentful/java/java-sdk/1.0.10/java-sdk-1.0.10.jar + [2]: https://oss.sonatype.org/service/local/repositories/releases/content/com/contentful/java/java-sdk/2.0.0/java-sdk-2.0.0.jar [3]: https://contentful.github.io/contentful.java/ [4]: https://www.contentful.com/developers/documentation/content-delivery-api/ [5]: https://square.github.io/okhttp/ diff --git a/pom.xml b/pom.xml index 95561de2..a83255a2 100644 --- a/pom.xml +++ b/pom.xml @@ -1,223 +1,305 @@ - + + 4.0.0 - 4.0.0 + com.contentful.java + java-sdk + 2.0.0-SNAPSHOT + jar - com.contentful.java - java-sdk - jar - 1.0.11-SNAPSHOT + ${project.groupId}:${project.artifactId} + Java SDK for Contentful's Content Delivery API. + http://github.com/contentful/contentful.java - ${project.groupId}:${project.artifactId} - Java SDK for Contentful's Content Delivery API. + + org.sonatype.oss + oss-parent + 7 + + + http://github.com/contentful/contentful.java + scm:git:git://github.com/contentful/contentful.java.git + scm:git:ssh://git@github.com/contentful/contentful.java.git + + + + GitHub Issues + http://github.com/contentful/contentful.java/issues + + + + + Apache 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + Contentful, GmbH. + http://contentful.com + + + + UTF-8 + UTF-8 + + + 1.6 + + + 1.8.0 + + + 2.4 + 4.11 + 0.9.206 + 2.0.0 + 2.0.0 + 2.0.0 + 1.0.0 + 1.10.8 + 4.1.1.4 + 16 + 2.4 + + + + + com.google.android + android + ${android.version} + true + + + + com.squareup.retrofit + retrofit + ${retrofit.version} + + + + io.reactivex + rxjava + ${rxjava.version} + + + + org.jetbrains.kotlin + kotlin-stdlib + ${kotlin-stdlib.version} + test + + + + commons-io + commons-io + ${commonsio.version} + test + + + + junit + junit + ${junit.version} + test + + + + com.squareup.okhttp + mockwebserver + ${mockwebserver.version} + test + + + + com.squareup.okhttp + okhttp + ${okhttp.version} + test + + + + com.squareup.okhttp + okhttp-urlconnection + ${okhttp-urlconnection.version} + test + + + + org.mockito + mockito-all + ${mockito.version} + test + + + + org.robolectric + robolectric + ${robolectric.version} + test + + + + + + + src/main/resources + true + + + ${project.basedir}/src/test/kotlin + + + kotlin-maven-plugin + org.jetbrains.kotlin + 0.9.976 + + + + compile + process-sources + + compile + + + + + test-compile + process-test-sources + + test-compile + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18 + + + **/*Tests.class + + + + + + org.eluder.coveralls + coveralls-maven-plugin + 3.0.1 + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.5.2 + + xml + 256m + + true + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.9.1 + + true + checkstyle.xml + true + + + + verify + + checkstyle + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + true + + + + + sign-artifacts + verify + + sign + + + + + + + + + + jetbrains-all + http://repository.jetbrains.com/all + + + sonatype.oss.snapshots + Sonatype OSS Snapshot Repository + http://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + - - UTF-8 - UTF-8 - - - 1.6 - - - 1.8.0 - 1.0.0 - 4.1.1.4 - 16 - - - 2.4 - 4.11 - - - - http://github.com/contentful/contentful.java - scm:git:git://github.com/contentful/contentful.java.git - scm:git:ssh://git@github.com:contentful/contentful.java.git - - - - GitHub Issues - http://github.com/contentful/contentful.java/issues - - - - - Apache 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - - Contentful, GmbH. - http://contentful.com - - - - - Tom Reznik - tom@contentful.com - https://github.com/tomxor - tomxor - - - - - - com.google.android - android - ${android.version} - true - - - - com.squareup.retrofit - retrofit - ${retrofit.version} - - - - io.reactivex - rxjava - ${rxjava.version} - - - - commons-io - commons-io - ${commonsio.version} - test - - - - junit - junit - ${junit.version} - test - - - - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - - - - - src/main/resources - true - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 2.9.1 - - true - checkstyle.xml - true - - - - verify - - checkstyle - - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.2 - true - - ossrh - https://oss.sonatype.org/ - true - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.0 - - ${java.version} - ${java.version} - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - attach-javadocs - - jar - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - true - - - - - sign-artifacts - verify - - sign - - - - - - - org.eluder.coveralls - coveralls-maven-plugin - 3.0.1 - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.6 - - xml - 256m - - true - - - - + + + sonatype.oss.snapshots + Sonatype OSS Snapshot Repository + http://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + diff --git a/src/main/java/com/contentful/java/api/ArrayResourceTypeAdapter.java b/src/main/java/com/contentful/java/api/ArrayResourceTypeAdapter.java deleted file mode 100644 index 4504f9fa..00000000 --- a/src/main/java/com/contentful/java/api/ArrayResourceTypeAdapter.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.api; - -import com.contentful.java.model.ArrayResource; -import com.contentful.java.model.CDAArray; -import com.contentful.java.model.CDASyncedSpace; -import com.google.gson.Gson; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Type; - -/** - * Custom type adapter for de-serializing array resources. - */ -class ArrayResourceTypeAdapter implements JsonDeserializer { - private final CDAClient client; - private final Gson gson; - - ArrayResourceTypeAdapter(CDAClient client, Gson gson) { - this.client = client; - this.gson = gson; - } - - @Override public ArrayResource deserialize(JsonElement jsonElement, Type type, - JsonDeserializationContext context) throws JsonParseException { - ArrayResource result = gson.fromJson(jsonElement, type); - - if (CDAArray.class.equals(type)) { - try { - result = parseArray((CDAArray) result); - } catch (Exception e) { - throw new JsonParseException(e); - } - } else if (CDASyncedSpace.class.equals(type)) { - CDASyncedSpace syncedSpace = (CDASyncedSpace) result; - - String nextSyncUrl = syncedSpace.getNextSyncUrl(); - if (nextSyncUrl != null) { - try { - syncedSpace.setSyncToken(Utils.getQueryParamFromUrl(nextSyncUrl, "sync_token")); - } catch (UnsupportedEncodingException e) { - throw new JsonParseException("Unable to retrieve sync token."); - } - } - } - - return result; - } - - /** - * Executes an {@code ArrayParser} with the given {@code source}, inferring the class type. - * - * @param source array instance to be parsed - * @param type of result object expected to be returned - * @return result of the {@code ArrayParser} execution - * @throws Exception in case of an error - */ - T parseArray(T source) throws Exception { - return new ArrayParser(source, client.getSpace()).call(); - } -} diff --git a/src/main/java/com/contentful/java/api/ArrayResponse.java b/src/main/java/com/contentful/java/api/ArrayResponse.java deleted file mode 100644 index cf9b897d..00000000 --- a/src/main/java/com/contentful/java/api/ArrayResponse.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.api; - -import com.contentful.java.model.CDAArray; -import retrofit.RetrofitError; -import retrofit.client.Response; - -/** - * Callback wrapper for requests returning array results. - */ -class ArrayResponse extends CDACallback { - private final CDACallback wrappedCallback; - - public ArrayResponse(CDACallback wrappedCallback) { - this.wrappedCallback = wrappedCallback; - } - - @Override protected void onSuccess(CDAArray result, Response response) { - prepareResponse(result, response); - - if (!wrappedCallback.isCancelled()) { - wrappedCallback.onSuccess(result, response); - } - } - - @Override protected void onFailure(RetrofitError retrofitError) { - super.onFailure(retrofitError); - - if (!wrappedCallback.isCancelled()) { - wrappedCallback.onFailure(retrofitError); - } - } - - /** - * Sets any additional values on the result, whilst having the {@code Response} context. - * - * @param result array result object of the original request - * @param response {@code Response} object as returned by the wrapped callback - */ - static void prepareResponse(CDAArray result, Response response) { - result.setOriginalUrl(response.getUrl()); - } -} diff --git a/src/main/java/com/contentful/java/api/CDACallback.java b/src/main/java/com/contentful/java/api/CDACallback.java deleted file mode 100644 index d7da096d..00000000 --- a/src/main/java/com/contentful/java/api/CDACallback.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.api; - -import retrofit.Callback; -import retrofit.RetrofitError; -import retrofit.client.Response; - -/** - * Callback to be used when making asynchronous requests by a {@code CDAClient}. - * - * Implement the {@link #onSuccess} method for cases where the request was successful, the result - * object should be delivered as a parameter. - * - * It is also possible, but not mandatory to override {@link #onFailure} and provide an - * implementation for handling errors. - * - * @param The type of object to be expected as a result. For methods that return a collection - * of CDA resources it is required to use {@code CDAArray} as the type. - */ -@SuppressWarnings("UnusedDeclaration") -public abstract class CDACallback implements Callback { - private boolean cancelled; - - @Override public final void success(T t, Response response) { - if (cancelled) { - return; - } - - onSuccess(t, response); - } - - @Override public final void failure(RetrofitError retrofitError) { - if (cancelled) { - return; - } - - onFailure(retrofitError); - } - - /** - * Callback to be invoked in case the request was successful. - * - * @param t result object - * that return multiple items - * @param response {@code retrofit.client.Response} instance - */ - protected abstract void onSuccess(T t, Response response); - - /** - * Callback to be invoked in case the request was unsuccessful. - * - * @param retrofitError {@link retrofit.RetrofitError} instance - */ - protected void onFailure(RetrofitError retrofitError) { - // Do nothing. - } - - /** - * Cancels the callback. Calling this method will result in any of the callbacks methods ({@link - * #onSuccess} / {@link #onFailure} not being called, this action cannot be reversed. - */ - public synchronized void cancel() { - this.cancelled = true; - } - - /** - * Check if this callback instance was cancelled using the {@link #cancel} method. - * - * @return boolean indicating whether or not the callback is cancelled - */ - public synchronized boolean isCancelled() { - return cancelled; - } -} diff --git a/src/main/java/com/contentful/java/api/CDAClient.java b/src/main/java/com/contentful/java/api/CDAClient.java deleted file mode 100644 index 57a3b5c0..00000000 --- a/src/main/java/com/contentful/java/api/CDAClient.java +++ /dev/null @@ -1,956 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.api; - -import com.contentful.java.lib.Constants; -import com.contentful.java.lib.ResourceUtils; -import com.contentful.java.model.CDAArray; -import com.contentful.java.model.CDAAsset; -import com.contentful.java.model.CDAContentType; -import com.contentful.java.model.CDAEntry; -import com.contentful.java.model.CDAResource; -import com.contentful.java.model.CDASpace; -import com.contentful.java.model.CDASyncedSpace; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import retrofit.ErrorHandler; -import retrofit.RequestInterceptor; -import retrofit.RestAdapter; -import retrofit.RetrofitError; -import retrofit.client.Client; -import retrofit.client.Response; -import retrofit.converter.GsonConverter; - -import static com.contentful.java.lib.Constants.CDAResourceType; -import static com.contentful.java.lib.Constants.HTTP_HEADER_AUTH; -import static com.contentful.java.lib.Constants.HTTP_HEADER_USER_AGENT; -import static com.contentful.java.lib.Constants.HTTP_OAUTH_PATTERN; -import static com.contentful.java.lib.Constants.IDLE_THREAD_NAME; -import static com.contentful.java.lib.Constants.PATH_ASSETS; -import static com.contentful.java.lib.Constants.PATH_ENTRIES; - -/** - * Client to be used when requesting information from the Delivery API. Every client is associated - * with exactly one Space, but there is no limit to the concurrent number of clients existing at - * any one time. Avoid creating multiple clients for the same Space. - * - * @see Builder for instructions of how to create a client - */ -@SuppressWarnings("UnusedDeclaration") -public class CDAClient { - // SDK properties - static String sVersionName; - static String sUserAgent; - - // Configuration - private String httpScheme; - private String accessToken; - private String spaceKey; - private Client.Provider clientProvider; - private HashMap> customTypesMap; - - // Retrofit service - private CDAService service; - - // Space - private CDASpace space; - - // Gson - private Gson gson; - - // Executors - ExecutorService executorService; - - private CDAClient() { - } - - /** - * Initialization method - should be called once all configuration properties are set. - */ - private void init(Builder builder) { - // Initialize members - this.customTypesMap = new HashMap>(); - this.spaceKey = builder.spaceKey; - this.accessToken = builder.accessToken; - - // Initialize Gson - initGson(); - - // Create a RestAdapter - RestAdapter.Builder restBuilder = - new RestAdapter.Builder().setConverter(new GsonConverter(gson)) - .setRequestInterceptor(getRequestInterceptor()); - - String endpoint; - if (builder.previewMode) { - endpoint = Constants.ENDPOINT_PREVIEW; - } else { - endpoint = Constants.ENDPOINT_CDA; - } - - // SSL - if (builder.dontUseSSL) { - httpScheme = Constants.SCHEME_HTTP; - } else { - httpScheme = Constants.SCHEME_HTTPS; - } - - restBuilder.setEndpoint(String.format("%s://%s", - httpScheme, endpoint)); - - // Client provider - if (builder.clientProvider != null) { - restBuilder.setClient(builder.clientProvider); - } - - // Error handler - if (builder.errorHandler != null) { - restBuilder.setErrorHandler(builder.errorHandler); - } - - // Log level - if (builder.logLevel != null) { - restBuilder.setLogLevel(builder.logLevel); - } - - // Create a Retrofit service - service = restBuilder.build().create(CDAService.class); - - // Init ExecutorService (will be used for parsing of array results and spaces synchronization). - executorService = Executors.newCachedThreadPool(new ThreadFactory() { - @SuppressWarnings("NullableProblems") - @Override - public Thread newThread(final Runnable r) { - return new Thread(new Runnable() { - @SuppressWarnings("NullableProblems") - @Override - public void run() { - Thread.currentThread().setPriority(Thread.MIN_PRIORITY); - r.run(); - } - }, IDLE_THREAD_NAME); - } - }); - } - - /** - * Initialize {@link com.google.gson.Gson} instances. - */ - private void initGson() { - Gson arrayGson = setBaseTypeAdapters(new GsonBuilder(), this).create(); - - gson = setBaseTypeAdapters(new GsonBuilder(), this) - .registerTypeAdapter(CDAArray.class, - new ArrayResourceTypeAdapter(CDAClient.this, arrayGson)) - .registerTypeAdapter(CDASyncedSpace.class, - new ArrayResourceTypeAdapter(CDAClient.this, arrayGson)) - .create(); - } - - /** - * Registers all type adapters required for CDA resource serialization on a given {@code - * GsonBuilder} instance. - */ - static GsonBuilder setBaseTypeAdapters(GsonBuilder gsonBuilder, CDAClient client) { - ResourceTypeAdapter rta = new ResourceTypeAdapter(client); - - return gsonBuilder.registerTypeAdapter(CDAResource.class, rta) - .registerTypeAdapter(CDAEntry.class, rta) - .registerTypeAdapter(CDAAsset.class, rta) - .registerTypeAdapter(CDAContentType.class, rta) - .registerTypeAdapter(CDASpace.class, rta); - } - - /** - * Creates a {@code RequestInterceptor}. The result interceptor will be used to attach - * any additional headers to a request prior to it's execution. - * - * This makes sure all requests carry a proper {@code "Authorization"} header with - * an access token following the standardized OAuth 2.0 Bearer Token Specification as per the - * Content Delivery API and also sets the {@code "User-Agent"} header on the request. - */ - private RequestInterceptor getRequestInterceptor() { - return new RequestInterceptor() { - @Override - public void intercept(RequestFacade requestFacade) { - if (accessToken != null && !accessToken.isEmpty()) { - requestFacade.addHeader(HTTP_HEADER_AUTH, String.format(HTTP_OAUTH_PATTERN, accessToken)); - } - - requestFacade.addHeader(HTTP_HEADER_USER_AGENT, getUserAgent()); - } - }; - } - - /** - * Use this method in order to register custom {@code CDAEntry} subclasses to be instantiated by - * the client when Entries of the given Content Type are retrieved from the server. - * - * Note: in case custom fields are declared in the custom class those should either be {@link - * java.io.Serializable} or denoted by the {@code transient} modifier in order to skip - * serialization, otherwise whenever trying to use - * {@link ResourceUtils#saveResourceToFile} an exception will be thrown. - * - * @param contentTypeIdentifier string representing a specific Content Type unique id - * @param clazz class type to instantiate when creating objects of the given - * Content Type (i.e. "SomeCustomEntry.class"). Note this has to be a subclass - * of {@code CDAEntry} - */ - public void registerCustomClass(String contentTypeIdentifier, Class clazz) { - customTypesMap.put(contentTypeIdentifier, clazz); - } - - /** - * Returns a mapping of Content Type unique ids to custom class types as registered using - * {@link #registerCustomClass}. - */ - HashMap> getCustomTypesMap() { - return customTypesMap; - } - - /** - * Fetch the next page of an array. - * - * This method extracts the {@code skip} and {@code limit} parameters of the original request - * that was used to fetch the given array and attempts to fetch the next page from the API. - * - * In case of the calculated offset exceeding the {@code total} attribute of the existing array, - * request will still be executed, since the data may have changed in the server. - * - * @param array previously fetched array - * @param callback callback to attach to the request - */ - public void fetchArrayNextPage(final CDAArray array, final CDACallback callback) { - if (array == null) { - throw new IllegalArgumentException("Array may not be empty."); - } - - String nextPageType = Utils.getNextPageType(array); - HashMap query = Utils.getNextBatchQueryMapForArray(array); - fetchArrayWithType(nextPageType, query, callback); - } - - /** - * Synchronous version of {@link #fetchArrayNextPage}. - * - * @param array previously fetched array - * @return {@code CDAArray} result object - */ - public CDAArray fetchArrayNextPageBlocking(CDAArray array) throws RetrofitError { - if (array == null) { - throw new IllegalArgumentException("Array may not be empty."); - } - - String nextPageType = Utils.getNextPageType(array); - HashMap query = Utils.getNextBatchQueryMapForArray(array); - - return fetchArrayWithTypeBlocking(nextPageType, query); - } - - /** - * Fetches an array of entities with type defined at run-time. - * - * @param type string representing the resource type - * @param query optional query - * @param callback callback to attach to the request - */ - private void fetchArrayWithType(final String type, final Map query, - final CDACallback callback) { - - ensureSpace(new EnsureSpaceCallback(this, callback) { - @Override void onSpaceReady() { - service.fetchArrayWithType(CDAClient.this.spaceKey, type, query, - new ArrayResponse(callback)); - } - }); - } - - /** - * Synchronous version of {@link #fetchArrayWithType}. - * - * @param type type of array - * @param query optional query - * @return {@code CDAArray} result object - */ - private CDAArray fetchArrayWithTypeBlocking(String type, Map query) - throws RetrofitError { - ensureSpaceBlocking(false); - Response response = service.fetchArrayWithTypeBlocking(spaceKey, type, query); - - CDAArray result; - - try { - result = gson.fromJson(new InputStreamReader(response.getBody().in()), CDAArray.class); - ArrayResponse.prepareResponse(result, response); - } catch (IOException e) { - throw RetrofitError.unexpectedError(response.getUrl(), e); - } - - return result; - } - - /** - * Fetch Assets. - * - * @param callback callback to attach to the request - */ - public void fetchAssets(CDACallback callback) { - fetchArrayWithType(PATH_ASSETS, null, callback); - } - - /** - * Synchronous version of {@link #fetchAssets}. - * - * @return {@code CDAArray} result object - */ - public CDAArray fetchAssetsBlocking() throws RetrofitError { - return fetchArrayWithTypeBlocking(PATH_ASSETS, null); - } - - /** - * Fetch Assets matching a specific query. - * - * @param query map representing the query - * @param callback callback to attach to the request - */ - public void fetchAssetsMatching(Map query, CDACallback callback) { - fetchArrayWithType(PATH_ASSETS, query, callback); - } - - /** - * Synchronous version of {@link #fetchAssetsMatching}. - * - * @param query map representing the query - * @return {@code CDAArray} result object - */ - public CDAArray fetchAssetsMatchingBlocking(Map query) throws RetrofitError { - return fetchArrayWithTypeBlocking(PATH_ASSETS, query); - } - - /** - * Fetch a single Asset with an identifier. - * - * @param identifier string representing the asset unique id - * @param callback callback to attach to the request - */ - public void fetchAssetWithIdentifier(final String identifier, - final CDACallback callback) { - ensureSpace(new EnsureSpaceCallback(this, callback) { - @Override void onSpaceReady() { - service.fetchAssetWithIdentifier(CDAClient.this.spaceKey, identifier, callback); - } - }); - } - - /** - * Synchronous version of {@link #fetchAssetWithIdentifier}. - * - * @param identifier string representing the asset unique id - * @return {@code CDAArray} result object - */ - public CDAAsset fetchAssetWithIdentifierBlocking(String identifier) throws RetrofitError { - ensureSpaceBlocking(false); - return service.fetchAssetWithIdentifierBlocking(spaceKey, identifier); - } - - /** - * Fetch all Content Types from a Space. - * - * @param callback callback to attach to the request - */ - public void fetchContentTypes(final CDACallback callback) { - ensureSpace(new EnsureSpaceCallback(this, callback) { - @Override void onSpaceReady() { - service.fetchContentTypes(CDAClient.this.spaceKey, callback); - } - }); - } - - /** - * Synchronous version of {@link #fetchContentTypes}. - * - * @return {@code CDAArray} result object - */ - public CDAArray fetchContentTypesBlocking() throws RetrofitError { - ensureSpaceBlocking(false); - return service.fetchContentTypesBlocking(spaceKey); - } - - /** - * Fetch a single Content Type with an identifier. - * - * @param identifier string representing the content type unique id - * @param callback callback to attach to the request - */ - public void fetchContentTypeWithIdentifier(final String identifier, - final CDACallback callback) { - ensureSpace(new EnsureSpaceCallback(this, callback) { - @Override void onSpaceReady() { - service.fetchContentTypeWithIdentifier(CDAClient.this.spaceKey, identifier, callback); - } - }); - } - - /** - * Synchronous version of {@link #fetchContentTypeWithIdentifier}. - * - * @param identifier string representing the content type unique id - * @return {@code CDAContentType} result object - */ - public CDAContentType fetchContentTypeWithIdentifierBlocking(String identifier) - throws RetrofitError { - ensureSpaceBlocking(false); - return service.fetchContentTypeWithIdentifierBlocking(spaceKey, identifier); - } - - /** - * Fetch Entries. - * - * @param callback callback to attach to the request - */ - public void fetchEntries(CDACallback callback) { - fetchArrayWithType(PATH_ENTRIES, null, callback); - } - - /** - * Synchronous version of {@link #fetchEntries}. - * - * @return {@code CDAArray} result object - */ - public CDAArray fetchEntriesBlocking() throws RetrofitError { - return fetchArrayWithTypeBlocking(PATH_ENTRIES, null); - } - - /** - * Fetch Entries matching a specific query. - * - * @param query map representing the query - * @param callback callback to attach to the request - */ - public void fetchEntriesMatching(Map query, CDACallback callback) { - fetchArrayWithType(PATH_ENTRIES, query, callback); - } - - /** - * Synchronous version of {@link #fetchEntriesMatching}. - * - * @param query map representing the query - * @return {@code CDAArray} result object - */ - public CDAArray fetchEntriesMatchingBlocking(Map query) throws RetrofitError { - return fetchArrayWithTypeBlocking(PATH_ENTRIES, query); - } - - /** - * Fetch a single Entry with identifier. - * - * When expecting result of a custom type which was previously registered using the {@link - * #registerCustomClass} method, the type of the expected object can also be specified as the - * generic type of the {@link CDACallback} instance (i.e. {@code new - * CDACallback(){...}}). - * - * @param identifier string representing the entry unique id - * @param callback callback to attach to the request - */ - public void fetchEntryWithIdentifier(final String identifier, - final CDACallback callback) { - ensureSpace(new EnsureSpaceCallback(this, callback) { - @Override void onSpaceReady() { - service.fetchEntryWithIdentifier(CDAClient.this.spaceKey, identifier, callback); - } - }); - } - - /** - * Synchronous version of {@link #fetchEntryWithIdentifier}. - * - * @param identifier string representing the entry unique id - * @return {@code CDAEntry} or a subclass of it - * @see #fetchEntryWithIdentifier(String, CDACallback) - */ - @SuppressWarnings("unchecked") - public CDAEntry fetchEntryWithIdentifierBlocking(String identifier) throws RetrofitError { - ensureSpaceBlocking(false); - return service.fetchEntryWithIdentifierBlocking(spaceKey, identifier); - } - - /** - * Fetch any kind of Resource from the server. This method can be used in cases where the actual - * type of Resource to be fetched is determined at runtime. - * - * Allowed Resource types are: - *
    - *
  • {@link com.contentful.java.lib.Constants.CDAResourceType#Asset}
  • - *
  • {@link com.contentful.java.lib.Constants.CDAResourceType#ContentType}
  • - *
  • {@link com.contentful.java.lib.Constants.CDAResourceType#Entry}
  • - *
- * - * Note: This method will throw an {@link java.lang.IllegalArgumentException} in cases - * where an invalid resource type is specified. - * - * @param resourceType type of resource to be fetched - * @param callback callback to attach to the request - */ - public void fetchResourcesOfType(CDAResourceType resourceType, CDACallback callback) { - if (CDAResourceType.Asset.equals(resourceType)) { - fetchAssets(callback); - } else if (CDAResourceType.ContentType.equals(resourceType)) { - fetchContentTypes(callback); - } else if (CDAResourceType.Entry.equals(resourceType)) { - fetchEntries(callback); - } else { - throw new IllegalArgumentException( - "Invalid resource type, allowed types are: Asset, ContentType, Entry."); - } - } - - /** - * An extension of {@link #fetchResourcesOfType} method. Allowed Resource types are: - *
    - *
  • {@link com.contentful.java.lib.Constants.CDAResourceType#Asset}
  • - *
  • {@link com.contentful.java.lib.Constants.CDAResourceType#Entry}
  • - *
- * - * Note: This method will throw an {@link java.lang.IllegalArgumentException} in cases - * where an invalid resource type is specified. - * - * @param resourceType type of resource to be fetched - * @param query map representing the query - * @param callback callback to attach to the request - */ - public void fetchResourcesOfTypeMatching(CDAResourceType resourceType, Map query, - CDACallback callback) { - - if (CDAResourceType.Asset.equals(resourceType)) { - fetchAssetsMatching(query, callback); - } else if (CDAResourceType.Entry.equals(resourceType)) { - fetchEntriesMatching(query, callback); - } else { - throw new IllegalArgumentException("Invalid resource type, allowed types are: Asset, Entry."); - } - } - - /** - * Fetch a single Space. - * - * @param callback callback to attach to the request - */ - public void fetchSpace(CDACallback callback) { - service.fetchSpace(this.spaceKey, callback); - } - - /** - * Synchronous version of {@link #fetchSpace}. - * - * @return {@code CDASpace} result object - */ - public CDASpace fetchSpaceBlocking() throws RetrofitError { - return service.fetchSpaceBlocking(this.spaceKey); - } - - /** - * Initial sync for a Space. - * - * @param callback callback to attach to the request - */ - public void performInitialSynchronization(final CDACallback callback) { - RxExtensions.defer(new RxExtensions.DefFunc() { - @Override CDASyncedSpace method() { - return performInitialSynchronizationBlocking(); - } - }, callback); - } - - /** - * Synchronous version of {@link #performInitialSynchronization}. - * - * @return {@link CDASyncedSpace} result object - */ - public CDASyncedSpace performInitialSynchronizationBlocking() throws RetrofitError { - ensureSpaceBlocking(true); - Response response = service.performSynchronizationBlocking(spaceKey, true, null); - CDASyncedSpace result; - - try { - result = gson.fromJson(new InputStreamReader( - response.getBody().in()), CDASyncedSpace.class); - - result = iterateSpace(new SpaceMerger(null, result, null, null, getSpace()).call()); - } catch (Exception e) { - throw RetrofitError.unexpectedError(response.getUrl(), e); - } - - return result; - } - - private CDASyncedSpace iterateSpace(CDASyncedSpace space) throws Exception { - String nextPageUrl = space.getNextPageUrl(); - while (nextPageUrl != null) { - String syncToken = Utils.getQueryParamFromUrl(nextPageUrl, "sync_token"); - if (syncToken == null) { - break; - } - - CDASyncedSpace nextPage = performSynchronization(syncToken, false); - space = new SpaceMerger(space, nextPage, null, null, getSpace()).call(); - nextPageUrl = nextPage.getNextPageUrl(); - } - return space; - } - - /** - * Sync an existing Space. - * - * @param existingSpace existing space to sync - * @param callback callback to attach to the request - */ - public void performSynchronization(final CDASyncedSpace existingSpace, - final CDACallback callback) { - if (existingSpace == null) { - throw new IllegalArgumentException("Existing space may not be null."); - } - - RxExtensions.defer(new RxExtensions.DefFunc() { - @Override CDASyncedSpace method() { - return performSynchronizationBlocking(existingSpace); - } - }, callback); - } - - /** - * Synchronous version of {@link #performSynchronization(CDASyncedSpace, CDACallback)}. - * - * @param existingSpace existing space to sync - * @return {@code CDASyncedSpace} result object - */ - public CDASyncedSpace performSynchronizationBlocking(CDASyncedSpace existingSpace) - throws RetrofitError { - if (existingSpace == null) { - throw new IllegalArgumentException("Existing space may not be null."); - } - - ensureSpaceBlocking(true); - Response response = - service.performSynchronizationBlocking(spaceKey, null, existingSpace.getSyncToken()); - CDASyncedSpace result; - - try { - CDASyncedSpace updatedSpace = - gson.fromJson(new InputStreamReader(response.getBody().in()), CDASyncedSpace.class); - - result = iterateSpace( - new SpaceMerger(existingSpace, updatedSpace, null, response, getSpace()).call()); - } catch (Exception e) { - throw RetrofitError.unexpectedError(response.getUrl(), e); - } - - return result; - } - - /** - * Sync an existing Space, given only a {@code syncToken}. - * - * @param syncToken string representing a previously persisted sync token - * @param callback callback to attach to the request - */ - public void performSynchronization(final String syncToken, - final CDACallback callback) { - RxExtensions.defer(new RxExtensions.DefFunc() { - @Override CDASyncedSpace method() { - return performSynchronization(syncToken); - } - }, callback); - } - - /** - * Synchronous version of {@link #performSynchronization(CDASyncedSpace, CDACallback)}. - * - * @param syncToken string representing a previously persisted sync token - * @return {@code CDASyncedSpace} result object - */ - public CDASyncedSpace performSynchronization(String syncToken) throws RetrofitError { - return performSynchronization(syncToken, true); - } - - private CDASyncedSpace performSynchronization(String syncToken, boolean iterate) - throws RetrofitError { - if (syncToken == null) { - throw new IllegalArgumentException("Sync token may not be null."); - } - - ensureSpaceBlocking(true); - Response response = service.performSynchronizationBlocking(spaceKey, null, syncToken); - CDASyncedSpace result; - - try { - result = gson.fromJson(new InputStreamReader(response.getBody().in()), CDASyncedSpace.class); - result = new SpaceMerger(null, result, null, null, getSpace()).call(); - - if (iterate) { - result = iterateSpace(result); - } - } catch (Exception e) { - throw RetrofitError.unexpectedError(response.getUrl(), e); - } - - return result; - } - - /** - * Returns the {@code CDASpace} object associated with this client. Note that a Space is attached - * to a client only after it's first request was successfully executed. - * - * @return {@code CDASpace} instance, null if it was not yet retrieved - */ - public CDASpace getSpace() { - return this.space; - } - - /** - * Callback to be invoked internally via {@link EnsureSpaceCallback} to update the current Space - * attached to this client. - * - * @param space {@code CDASpace} result object - */ - void onSpaceReady(CDASpace space) { - if (space != null && this.space != space) { - this.space = space; - } - } - - /** - * Gets the HTTP scheme configured for this client. - * - * @return string representing the http scheme to be used for all requests. This can be either - * {@code HTTP} or {@code HTTPS}. - */ - public String getHttpScheme() { - return httpScheme; - } - - /** - * Calls {@link #ensureSpace(boolean, EnsureSpaceCallback)} with default values. - * - * @param callback {@link EnsureSpaceCallback} instance wrapping the original callback to be used - */ - private void ensureSpace(EnsureSpaceCallback callback) { - ensureSpace(false, callback); - } - - /** - * Helper method to ensure a client has a Space associated with it prior to executing any other - * requests that depend on that. - * - * If a Space is already attached to the client, no extra request will be executed, unless {@code - * invalidate} is set to true. - * - * @param invalidate boolean indicating whether to force-fetch the Space metadata even if it - * already exists - * @param callback {@link EnsureSpaceCallback} instance wrapping the original callback to be - * used - */ - private void ensureSpace(boolean invalidate, final EnsureSpaceCallback callback) { - if (invalidate || space == null) { - fetchSpace(callback); - } else { - callback.onSuccess(space, null); - } - } - - /** - * Synchronous version of {@link #ensureSpace(boolean, EnsureSpaceCallback)}. - * - * @param invalidate boolean indicating whether to force-fetch the Space metadata even if it - * already exist. - */ - private void ensureSpaceBlocking(boolean invalidate) throws RetrofitError { - if (invalidate || space == null) { - space = fetchSpaceBlocking(); - } - } - - /** - * Sets the value for {@code userAgent} variable from properties (if needed) and returns it. - */ - private String getUserAgent() { - if (sUserAgent == null) { - try { - sVersionName = Utils.getFromProperties(Utils.PROP_VERSION_NAME); - sUserAgent = String.format("contentful.java/%s", sVersionName); - } catch (IOException e) { - throw new RuntimeException("Unable to retrieve version name", e); - } - } - - return sUserAgent; - } - - /** - * Client builder. - * - * Calling the following methods is required before calling {@link #build}: - *
    - *
  • {@link #setSpaceKey(String)}
  • - *
  • {@link #setAccessToken(String)}
  • - *
- */ - public static class Builder { - // Configuration - private String accessToken; - - private String spaceKey; - private Client.Provider clientProvider; - private ErrorHandler errorHandler; - private boolean dontUseSSL = false; - private RestAdapter.LogLevel logLevel; - private boolean previewMode = false; - - /** - * Sets the access token to be used with this client. - * - * @param accessToken string representing access token to be used when authenticating against - * the delivery api - * @return this {@code Builder} instance - */ - public Builder setAccessToken(String accessToken) { - if (accessToken == null) { - throw new NullPointerException("Access token may not be null."); - } - - this.accessToken = accessToken; - return this; - } - - /** - * Sets a custom client to be used for making HTTP requests. - * - * @param client {@link retrofit.client.Client} instance - * @return this {@code Builder} instance - */ - public Builder setClient(final Client client) { - if (client == null) { - throw new NullPointerException("Client may not be null."); - } - - return setClient(new Client.Provider() { - @Override - public Client get() { - return client; - } - }); - } - - /** - * Sets a provider of clients to be used for making HTTP requests. - * - * @param clientProvider {@link retrofit.client.Client.Provider} instance - * @return this {@code Builder} instance - */ - public Builder setClient(Client.Provider clientProvider) { - if (clientProvider == null) { - throw new NullPointerException("Client provider may not be null."); - } - - this.clientProvider = clientProvider; - return this; - } - - /** - * The error handler allows you to customize the type of exception thrown for errors of request - * executions. - * - * @param errorHandler error handler to set - * @return this {@code Builder} instance - */ - public Builder setErrorHandler(ErrorHandler errorHandler) { - if (errorHandler == null) { - throw new NullPointerException("Error handler may not be null."); - } - - this.errorHandler = errorHandler; - return this; - } - - /** - * Change the log level. - * - * @param logLevel {@link retrofit.RestAdapter.LogLevel} value - * @return this {@code Builder} instance - */ - public Builder setLogLevel(RestAdapter.LogLevel logLevel) { - if (logLevel == null) { - throw new NullPointerException("LogLevel may not be null."); - } - - this.logLevel = logLevel; - return this; - } - - /** - * Sets the space key to be used with this client. - * - * @param spaceKey string representing the space key - * @return this {@code Builder} instance - */ - public Builder setSpaceKey(String spaceKey) { - if (spaceKey == null) { - throw new NullPointerException("Space key may not be null."); - } - - this.spaceKey = spaceKey; - return this; - } - - /** - * Makes the client execute all requests via HTTP instead of HTTPS - use with caution. - * - * @return this {@code Builder} instance - */ - public Builder noSSL() { - this.dontUseSSL = true; - return this; - } - - /** - * Sets this client to use the Preview API endpoint. - * @return this {@code Builder} instance - */ - public Builder preview() { - this.previewMode = true; - return this; - } - - /** - * Builds and returns a {@link CDAClient} - * - * @return Client instance - */ - public CDAClient build() { - CDAClient client = new CDAClient(); - client.init(this); - - return client; - } - } -} \ No newline at end of file diff --git a/src/main/java/com/contentful/java/api/CDAService.java b/src/main/java/com/contentful/java/api/CDAService.java deleted file mode 100644 index cbe18fdc..00000000 --- a/src/main/java/com/contentful/java/api/CDAService.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.api; - -import com.contentful.java.model.CDAArray; -import com.contentful.java.model.CDAAsset; -import com.contentful.java.model.CDAContentType; -import com.contentful.java.model.CDAEntry; -import com.contentful.java.model.CDASpace; -import java.util.Map; -import retrofit.client.Response; -import retrofit.http.GET; -import retrofit.http.Path; -import retrofit.http.Query; -import retrofit.http.QueryMap; - -/** - * An interface being used internally to create a Retrofit Service via {@link - * retrofit.RestAdapter#create}. - */ -interface CDAService { - /** - * Fetch any type of resource from a Space. This can be useful for when the type of resource to - * be fetched is determined at runtime. - * - * @param space space key - * @param type type of resource to be fetched (i.e. "entries", "assets", ...). - * @param query map representing the query - * @param response {@link ArrayResponse} instance to be used - */ - @GET("/spaces/{space}/{type}") void fetchArrayWithType( - @Path("space") String space, - @Path("type") String type, - @QueryMap Map query, ArrayResponse response); - - /** - * Synchronous version of {@link #fetchArrayWithType(String, String, java.util.Map, - * ArrayResponse)}. - */ - @GET("/spaces/{space}/{type}") Response fetchArrayWithTypeBlocking( - @Path("space") String space, - @Path("type") String type, - @QueryMap Map query); - - /** - * Asset endpoint with unique id. - * - * @param space space key - * @param identifier asset unique id - * @param callback callback to attach to the request - */ - @GET("/spaces/{space}/assets/{identifier}") void fetchAssetWithIdentifier( - @Path("space") String space, - @Path("identifier") String identifier, - CDACallback callback); - - /** - * Synchronous version of {@link #fetchAssetWithIdentifier(String, String, CDACallback)}. - */ - @GET("/spaces/{space}/assets/{identifier}") CDAAsset fetchAssetWithIdentifierBlocking( - @Path("space") String space, - @Path("identifier") String identifier); - - /** - * Content Types endpoint. - * - * @param space space key - * @param callback callback to attach to the request - */ - @GET("/spaces/{space}/content_types") void fetchContentTypes( - @Path("space") String space, - CDACallback callback); - - /** - * Synchronous version of {@link #fetchContentTypes(String, CDACallback)} - */ - @GET("/spaces/{space}/content_types") CDAArray fetchContentTypesBlocking( - @Path("space") String space); - - /** - * Content Type endpoint with unique id. - * - * @param space space key - * @param identifier content type unique id - * @param callback callback to attach to the request - */ - @GET("/spaces/{space}/content_types/{identifier}") void fetchContentTypeWithIdentifier( - @Path("space") String space, - @Path("identifier") String identifier, - CDACallback callback); - - /** - * Synchronous version of {@link #fetchContentTypes(String, CDACallback)} - */ - @GET("/spaces/{space}/content_types/{identifier}") - CDAContentType fetchContentTypeWithIdentifierBlocking( - @Path("space") String space, - @Path("identifier") String identifier); - - /** - * Entry endpoint with unique id. - * - * @param space space key - * @param identifier entry unique id - * @param callback callback to attach to the request - */ - @GET("/spaces/{space}/entries/{identifier}") void fetchEntryWithIdentifier( - @Path("space") String space, - @Path("identifier") String identifier, - CDACallback callback); - - /** - * Synchronous version of {@link #fetchEntryWithIdentifier(String, String, CDACallback)} - */ - @GET("/spaces/{space}/entries/{identifier}") CDAEntry fetchEntryWithIdentifierBlocking( - @Path("space") String space, - @Path("identifier") String identifier); - - /** - * Space endpoint. - * - * @param space space key - * @param callback callback to attach to the request - */ - @GET("/spaces/{space}") void fetchSpace( - @Path("space") String space, - CDACallback callback); - - /** - * Synchronous version of {@link #fetchSpace(String, CDACallback)} - */ - @GET("/spaces/{space}") CDASpace fetchSpaceBlocking( - @Path("space") String space); - - /** - * Space Sync endpoint. - * - * @param space space key - * @param initial boolean indicating whether to invoke an initial sync request - * @param syncToken sync token. - * @param callback callback to attach to the request - */ - @GET("/spaces/{space}/sync") void performSynchronization( - @Path("space") String space, - @Query("initial") Boolean initial, - @Query("sync_token") String syncToken, - SyncSpaceCallback callback); - - /** - * Synchronous version of {@link #performSynchronization(String, Boolean, String, - * SyncSpaceCallback)} - */ - @GET("/spaces/{space}/sync") Response performSynchronizationBlocking( - @Path("space") String space, - @Query("initial") Boolean initial, - @Query("sync_token") String syncToken); -} diff --git a/src/main/java/com/contentful/java/api/EnsureSpaceCallback.java b/src/main/java/com/contentful/java/api/EnsureSpaceCallback.java deleted file mode 100644 index 8a75abdd..00000000 --- a/src/main/java/com/contentful/java/api/EnsureSpaceCallback.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.api; - -import com.contentful.java.model.CDASpace; -import retrofit.RetrofitError; -import retrofit.client.Response; - -/** - * Custom callback used internally to ensure a {@link CDASpace} instance is available before making - * certain requests that depend on it. - * - * This is mostly used when making requests that return multiple items as a result, since the Space - * metadata is essential for preparing array result objects. - */ -abstract class EnsureSpaceCallback extends CDACallback { - private final CDAClient client; - private final CDACallback wrappedCallback; - - EnsureSpaceCallback(CDAClient client, CDACallback wrappedCallback) { - this.client = client; - this.wrappedCallback = wrappedCallback; - } - - @Override protected final void onSuccess(CDASpace space, Response response) { - client.onSpaceReady(space); - - if (!wrappedCallback.isCancelled()) { - onSpaceReady(); - } - } - - @Override protected final void onFailure(RetrofitError retrofitError) { - super.onFailure(retrofitError); - - if (!wrappedCallback.isCancelled()) { - wrappedCallback.onFailure(retrofitError); - } - } - - /** - * Abstract method to implement, will be called when the Space metadata is available. - */ - abstract void onSpaceReady(); -} diff --git a/src/main/java/com/contentful/java/api/SyncSpaceCallback.java b/src/main/java/com/contentful/java/api/SyncSpaceCallback.java deleted file mode 100644 index 495a2dfb..00000000 --- a/src/main/java/com/contentful/java/api/SyncSpaceCallback.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.api; - -import com.contentful.java.model.CDASyncedSpace; -import retrofit.RetrofitError; -import retrofit.client.Response; - -/** - * Convenience callback wrapper which creates and executes a {@code SpaceMerger} Callable. - */ -class SyncSpaceCallback extends CDACallback { - private final CDASyncedSpace originalSpace; - private final CDAClient client; - private final CDACallback wrappedCallback; - - public SyncSpaceCallback(CDASyncedSpace originalSpace, CDAClient client, - CDACallback wrappedCallback) { - this.originalSpace = originalSpace; - this.client = client; - this.wrappedCallback = wrappedCallback; - } - - @Override protected void onSuccess(CDASyncedSpace updatedSpace, Response response) { - if (!wrappedCallback.isCancelled()) { - client.executorService.submit( - new SpaceMerger(originalSpace, updatedSpace, wrappedCallback, response, - client.getSpace())); - } - } - - @Override protected void onFailure(RetrofitError retrofitError) { - super.onFailure(retrofitError); - - if (!wrappedCallback.isCancelled()) { - wrappedCallback.onFailure(retrofitError); - } - } -} diff --git a/src/main/java/com/contentful/java/api/Utils.java b/src/main/java/com/contentful/java/api/Utils.java deleted file mode 100644 index fc1887ac..00000000 --- a/src/main/java/com/contentful/java/api/Utils.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.api; - -import com.contentful.java.model.CDAArray; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLDecoder; -import java.util.HashMap; -import java.util.Properties; -import java.util.concurrent.Executor; - -/** - * SDK utilities - */ -class Utils { - private Utils() { - } - - static final String SDK_PROPERTIES = "contentful_cda.properties"; - static final String PROP_VERSION_NAME = "version.name"; - - /** - * Returns the last path segment of the original URL which was used to fetch the given array. - */ - static String getNextPageType(CDAArray array) { - String url = assertArray(array); - String result = null; - - try { - URI uri = new URI(url); - String[] split = uri.getPath().split("/"); - result = split[split.length - 1]; - } catch (URISyntaxException e) { - e.printStackTrace(); - } - - return result; - } - - /** - * Ensures an array has it's original URL associated with it, otherwise throws an exception. - * - * @param array {@code CDAArray} instance - * @return string representing the original url - */ - private static String assertArray(CDAArray array) { - String url = array.getOriginalUrl(); - - if (url == null) { - throw new IllegalArgumentException( - "Invalid array instance! (empty or unsuccessful response)"); - } - - return url; - } - - /** - * Prepares a query map to be used for fetching the next page of an array - * - * @param array existing, previously fetched array - * @return map containing original query string parameters and updated pagination parameters for - * the next request (skip/limit) - */ - static HashMap getNextBatchQueryMapForArray(CDAArray array) { - assertArray(array); - - // extract pagination parameters - int skip = array.getSkip(); - int limit = array.getLimit(); - - // calculate next offset - int nextOffset = skip + limit; - - return prepareQueryMap(URI.create(array.getOriginalUrl()), nextOffset, limit); - } - - /** - * Helper method for {@link #getNextBatchQueryMapForArray} that actually creates the query map. - * - * @param uri Original request URL. - * @param nextOffset {@code skip} value to be used. - * @param limit {@code limit} value to be used. - * @return Map representing the query. - */ - private static HashMap prepareQueryMap(URI uri, int nextOffset, int limit) { - // Prepare the new map - HashMap queryMap = new HashMap(); - String query = uri.getQuery(); - - if (query != null) { - // Iterate through all the query string parameters from the original request and add them - // to the new map, while stripping any pagination related arguments from it as those will - // be specified next. - String[] params = query.split("&"); - - for (String p : params) { - String[] kv = p.split("="); - - if ("skip".equalsIgnoreCase(kv[0]) || "limit".equalsIgnoreCase(kv[0])) { - - continue; - } - - queryMap.put(kv[0], kv[1]); - } - } - - // Set new pagination parameters - queryMap.put("skip", Integer.toString(nextOffset)); - queryMap.put("limit", Integer.toString(limit)); - - return queryMap; - } - - static String getFromProperties(String field) throws IOException { - Properties properties = new Properties(); - properties.load(Utils.class.getClassLoader().getResourceAsStream(SDK_PROPERTIES)); - return properties.getProperty(field); - } - - static String getQueryParamFromUrl(String url, String param) throws UnsupportedEncodingException { - URI uri = URI.create(url); - String query = uri.getQuery(); - - if (query == null) { - return null; - } - - String[] pairs = query.split("&"); - for (String pair : pairs) { - String[] split = pair.split("="); - if (split.length != 2) { - continue; - } - - if (param.equalsIgnoreCase(split[0])) { - return URLDecoder.decode(split[1], "UTF-8"); - } - } - - return null; - } - - static class SynchronousExecutor implements Executor { - @Override public void execute(Runnable runnable) { - runnable.run(); - } - } -} - diff --git a/src/main/java/com/contentful/java/api/package-info.java b/src/main/java/com/contentful/java/api/package-info.java deleted file mode 100644 index 6c6dcab5..00000000 --- a/src/main/java/com/contentful/java/api/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Set of tools for communicating with the Content Delivery API. - */ -package com.contentful.java.api; \ No newline at end of file diff --git a/src/main/java/com/contentful/java/cda/AbsModule.java b/src/main/java/com/contentful/java/cda/AbsModule.java new file mode 100644 index 00000000..503cad5d --- /dev/null +++ b/src/main/java/com/contentful/java/cda/AbsModule.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import com.contentful.java.cda.model.CDASpace; + +/** + * AbsModule. + */ +abstract class AbsModule { + final ClientContext context; + final A extAsync; + final R extRxJava; + + AbsModule(ClientContext context) { + this.context = context; + this.extAsync = createAsyncExtension(); + this.extRxJava = createRxJavaExtension(); + } + + abstract A createAsyncExtension(); + + abstract R createRxJavaExtension(); + + /** + * Returns the asynchronous extension of this module. + */ + public abstract A async(); + + /** + * Returns the RxJava extension of this module. + */ + public abstract R rx(); + + class Async { + } + + class Rx { + } + + void ensureSpace() { + ensureSpace(false); + } + + void ensureSpace(boolean invalidate) { + if (invalidate || context.spaceWrapper.get() == null) { + CDASpace space = context.service.fetchSpace(context.spaceId); + context.spaceWrapper.set(space); + } + } +} diff --git a/src/main/java/com/contentful/java/api/ArrayParser.java b/src/main/java/com/contentful/java/cda/ArrayParser.java similarity index 85% rename from src/main/java/com/contentful/java/api/ArrayParser.java rename to src/main/java/com/contentful/java/cda/ArrayParser.java index 735caeb7..595fd82e 100644 --- a/src/main/java/com/contentful/java/api/ArrayParser.java +++ b/src/main/java/com/contentful/java/cda/ArrayParser.java @@ -14,24 +14,23 @@ * limitations under the License. */ -package com.contentful.java.api; - -import com.contentful.java.model.ArrayResource; -import com.contentful.java.model.CDAArray; -import com.contentful.java.model.CDAAsset; -import com.contentful.java.model.CDAEntry; -import com.contentful.java.model.CDAResource; -import com.contentful.java.model.CDASpace; -import com.contentful.java.model.CDASyncedSpace; -import com.contentful.java.model.Locale; -import com.contentful.java.model.ResourceWithMap; +package com.contentful.java.cda; + +import com.contentful.java.cda.model.ArrayResource; +import com.contentful.java.cda.model.CDAArray; +import com.contentful.java.cda.model.CDAAsset; +import com.contentful.java.cda.model.CDAEntry; +import com.contentful.java.cda.model.CDALocale; +import com.contentful.java.cda.model.CDAResource; +import com.contentful.java.cda.model.CDASyncedSpace; +import com.contentful.java.cda.model.ResourceWithMap; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; -import static com.contentful.java.lib.Constants.CDAResourceType; +import static com.contentful.java.cda.Constants.CDAResourceType; /** * Custom {@code Callable} used internally for preparing array result objects. This attempts to @@ -40,11 +39,11 @@ */ class ArrayParser implements Callable { private final T source; - private final CDASpace space; + private final ClientContext context; - public ArrayParser(T source, CDASpace space) { + public ArrayParser(T source, ClientContext context) { this.source = source; - this.space = space; + this.context = context; } @Override public T call() throws Exception { @@ -78,7 +77,7 @@ public ArrayParser(T source, CDASpace space) { } } } else { - throw new IllegalArgumentException("Invalid result item."); + throw new IllegalArgumentException("Invalid input."); } for (CDAResource item : items) { @@ -111,11 +110,11 @@ private void setLocalizedFields(ResourceWithMap res) { HashMap localizedFieldsMap = res.getLocalizedFieldsMap(); // Create a map for every locale - for (Locale locale : space.getLocales()) { + for (CDALocale locale : context.spaceWrapper.get().getLocales()) { HashMap map = new HashMap(); for (Object key : rawFields.keySet()) { - String code = locale.code; + String code = locale.getCode(); Map item = (Map) rawFields.get(key); Object value = item.get(code); @@ -136,8 +135,8 @@ private void setLocalizedFields(ResourceWithMap res) { * @param entries map of entries by ids */ @SuppressWarnings("unchecked") - private void resolveResourceLinks(CDAResource resource, HashMap assets, - HashMap entries) { + private void resolveResourceLinks(CDAResource resource, + HashMap assets, HashMap entries) { ResourceWithMap res = (ResourceWithMap) resource; HashMap localizedFields = res.getLocalizedFieldsMap(); @@ -196,8 +195,6 @@ private CDAResource getMatchForField(Map map, HashMap asset result = assets.get(id); } else if (CDAResourceType.Entry.equals(linkType)) { result = entries.get(id); - } else if (CDAResourceType.Space.equals(linkType)) { - result = space; } } } diff --git a/src/main/java/com/contentful/java/cda/BaseModule.java b/src/main/java/com/contentful/java/cda/BaseModule.java new file mode 100644 index 00000000..3347168a --- /dev/null +++ b/src/main/java/com/contentful/java/cda/BaseModule.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import com.contentful.java.cda.model.CDAArray; +import com.contentful.java.cda.model.CDAResource; +import java.io.InputStreamReader; +import java.util.Map; +import retrofit.RetrofitError; +import retrofit.client.Response; +import rx.Observable; + +import static com.contentful.java.cda.RxExtensions.DefFunc; +import static com.contentful.java.cda.RxExtensions.defer; +import static com.contentful.java.cda.RxExtensions.subscribe; + +/** + * BaseModule. + */ +abstract class BaseModule + extends AbsModule { + public BaseModule(ClientContext context) { + super(context); + } + + /** + * Returns the remote path for the type of resource associated with this module. + */ + abstract String getResourcePath(); + + /** + * Creates and returns a {@code CDAResource} instance from the given {@code inputStreamReader}. + */ + abstract T createCdaResource(InputStreamReader inputStreamReader); + + @Override ExtAsync createAsyncExtension() { + return new ExtAsync(); + } + + @Override ExtRxJava createRxJavaExtension() { + return new ExtRxJava(); + } + + /** + * Fetch all resources of the type associated with this module. + * + * @return array result instance + */ + public CDAArray fetchAll() { + return fetchAll(null); + } + + /** + * Fetch all resources of the type associated with this module, filtered by a query. + * + * @param query Map representing the query + * @return array result instance + */ + public CDAArray fetchAll(Map query) { + ensureSpace(); + return fetchArray(getResourcePath(), query); + } + + /** + * Fetch a single resource with an identifier. + * + * @param identifier resource id + * @return resource result instance + */ + public T fetchOne(String identifier) { + ensureSpace(); + Utils.assertNotNull(identifier, "identifier"); + Response response = + context.service.fetchResource(context.spaceId, getResourcePath(), identifier); + + try { + return prepare(createCdaResource(new InputStreamReader(response.getBody().in()))); + } catch (Exception e) { + throw RetrofitError.unexpectedError(response.getUrl(), e); + } + } + + CDAArray fetchArray(String type, Map query) { + Utils.assertNotNull(type, "type"); + ensureSpace(); + Response response = context.service.fetchArray(context.spaceId, type, query); + + try { + CDAArray array = + context.gson.fromJson(new InputStreamReader(response.getBody().in()), CDAArray.class); + + array.setOriginalUrl(response.getUrl()); + + return prepare(new ArrayParser(array, context).call()); + } catch (Exception e) { + throw RetrofitError.unexpectedError(response.getUrl(), e); + } + } + + E prepare(E resource) { + return resource; + } + + /** + * Base Async extension. + */ + public class ExtAsync extends AbsModule.Async { + /** + * Fetch all resources of the type associated with this module. + * + * @param callback callback + * @return the given {@code callback} instance + */ + @SuppressWarnings("unchecked") public CDACallback fetchAll( + final CDACallback callback) { + return subscribe(rx().fetchAll(), callback, context); + } + + /** + * Fetch all resources of the type associated with this module, filtered by a query. + * + * @param query Map representing the query + * @param callback callback + * @return the given {@code callback} instance + */ + @SuppressWarnings("unchecked") public CDACallback fetchAll(Map query, + CDACallback callback) { + return subscribe(rx().fetchAll(query), callback, context); + } + + /** + * Fetch a single resource with an identifier. + * + * @param identifier resource id + * @param callback callback + * @return the given {@code callback} instance + */ + @SuppressWarnings("unchecked") + public CDACallback fetchOne(String identifier, CDACallback callback) { + return subscribe(rx().fetchOne(identifier), callback, context); + } + } + + /** + * Base RxJava extension. + */ + public class ExtRxJava extends AbsModule.Rx { + /** + * Get an {@code Observable} that fetches all resources of the type associated with this + * module. + * + * @return the given {@code callback} instance + */ + public Observable fetchAll() { + return fetchAll(null); + } + + /** + * Get an {@code Observable} that fetches all resources of the type associated with + * this module, filtered by a query. + * + * @param query Map representing the query + * @return {@code Observable} instance + */ + public Observable fetchAll(final Map query) { + return defer(new DefFunc() { + @Override CDAArray method() { + return BaseModule.this.fetchAll(query); + } + }); + } + + /** + * Get an {@code Observable} that fetches a single resource with an identifier. + * + * @param identifier resource id + * @return {@code Observable} instance + */ + public Observable fetchOne(final String identifier) { + return defer(new DefFunc() { + @Override T method() { + return BaseModule.this.fetchOne(identifier); + } + }); + } + } +} diff --git a/src/main/java/com/contentful/java/cda/CDACallback.java b/src/main/java/com/contentful/java/cda/CDACallback.java new file mode 100644 index 00000000..ed88726b --- /dev/null +++ b/src/main/java/com/contentful/java/cda/CDACallback.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import retrofit.RetrofitError; + +/** + * Callback to use with any of the asynchronous client methods. + * + * Implement the {@link #onSuccess} method for cases where the request is successful, the result + * object should be delivered as a parameter. + * + * It is also encouraged, but still optional to override {@link #onFailure} and provide an + * implementation for handling errors. + * + * @param the type of object to be expected as a result. + * + * Callback can be cancelled at any point using the {@link #cancel()} method, that will prevent + * any future calls to {@link #onSuccess} and {@link #onFailure(RetrofitError)}. + */ +public abstract class CDACallback { + private boolean cancelled; + + /** + * Callback to be invoked in case the request was successful. + * + * @param result result object + */ + protected abstract void onSuccess(T result); + + /** + * Callback to be invoked in case the request was unsuccessful. + * + * @param retrofitError {@link retrofit.RetrofitError} instance + */ + protected void onFailure(RetrofitError retrofitError) { + // Do nothing. + } + + /** + * Cancels this callback. This will prevent any future calls to {@link #onSuccess(Object)} and + * {@link #onFailure(RetrofitError)} methods. This action cannot be reversed. + */ + public synchronized void cancel() { + this.cancelled = true; + } + + /** + * Returns true in case this callback instance was previously cancelled. + */ + public synchronized boolean isCancelled() { + return cancelled; + } +} diff --git a/src/main/java/com/contentful/java/cda/CDAClient.java b/src/main/java/com/contentful/java/cda/CDAClient.java new file mode 100644 index 00000000..97892a36 --- /dev/null +++ b/src/main/java/com/contentful/java/cda/CDAClient.java @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import com.contentful.java.cda.model.CDAAsset; +import com.contentful.java.cda.model.CDAContentType; +import com.contentful.java.cda.model.CDAEntry; +import com.contentful.java.cda.model.CDAResource; +import com.contentful.java.cda.model.CDASpace; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executor; +import retrofit.RequestInterceptor; +import retrofit.RestAdapter; +import retrofit.client.Client; +import retrofit.converter.GsonConverter; + +import static com.contentful.java.cda.Constants.HTTP_HEADER_AUTH; +import static com.contentful.java.cda.Constants.HTTP_HEADER_USER_AGENT; +import static com.contentful.java.cda.Constants.HTTP_OAUTH_PATTERN; + +/** + * Client to be used when requesting information from the Delivery API. Every client is associated + * with exactly one Space, but there is no limit to the concurrent number of clients existing at + * any one time. Avoid creating multiple clients for the same Space. Use the {@link Builder} + * class to create a client. + */ +public class CDAClient { + // SDK properties + static String sUserAgent; + + // Configuration + final String accessToken; + final String spaceKey; + final String httpScheme; + final Map> classMap; + final PropertiesReader propertiesReader; + final CDAService service; + final Gson gson; + final SpaceWrapper spaceWrapper; + final Executor callbackExecutor; + + // Modules + final ModuleAssets moduleAssets; + final ModuleContentTypes moduleContentTypes; + final ModuleEntries moduleEntries; + final ModuleSpaces moduleSpaces; + final ModuleSync moduleSync; + + private CDAClient(Builder builder) { + if (builder.accessToken == null) { + throw new IllegalArgumentException("Access token must be defined."); + } + + if (builder.spaceKey == null) { + throw new IllegalArgumentException("Space ID must be defined."); + } + + this.spaceWrapper = new SpaceWrapper(); + this.propertiesReader = new PropertiesReader(); + this.spaceKey = builder.spaceKey; + this.accessToken = builder.accessToken; + this.classMap = createClassMap(builder); + this.httpScheme = createHttpScheme(builder); + this.callbackExecutor = createCallbackExecutor(builder); + this.gson = createGson(); + this.service = createRetrofitService(builder); + + // Modules + ClientContext context = new ClientContext(service, callbackExecutor, spaceKey, + gson, spaceWrapper, classMap); + + this.moduleAssets = new ModuleAssets(context); + this.moduleContentTypes = new ModuleContentTypes(context); + this.moduleEntries = new ModuleEntries(context); + this.moduleSpaces = new ModuleSpaces(context); + this.moduleSync = new ModuleSync(context); + } + + /** + * Returns the {@code CDASpace} object associated with this client. Note that a Space is attached + * to a client only after it's first request was successfully executed. + * + * @return {@code CDASpace} instance, null if it was not yet retrieved + */ + public CDASpace getSpace() { + return spaceWrapper.get(); + } + + /** + * Gets the HTTP scheme configured for this client. + * + * @return the HTTP scheme configured for this client. This can be + * either {@code HTTP} or {@code HTTPS} + */ + public String getHttpScheme() { + return httpScheme; + } + + /** + * Returns the Assets module. + */ + public ModuleAssets assets() { + return moduleAssets; + } + + /** + * Returns the Content Types module. + */ + public ModuleContentTypes contentTypes() { + return moduleContentTypes; + } + + /** + * Returns the Entries module. + */ + public ModuleEntries entries() { + return moduleEntries; + } + + /** + * Returns the Spaces module. + */ + public ModuleSpaces spaces() { + return moduleSpaces; + } + + /** + * Returns the Synchronization module. + */ + public ModuleSync synchronization() { + return moduleSync; + } + + /** + * Sets the value for {@code sUserAgent} from properties (if needed) and returns it. + */ + String createUserAgent(PropertiesReader reader) { + if (sUserAgent == null) { + try { + String versionName = reader.getField(Constants.PROP_VERSION_NAME); + sUserAgent = String.format("contentful.java/%s", versionName); + } catch (IOException e) { + throw new RuntimeException("Unable to retrieve version name.", e); + } + } + return sUserAgent; + } + + private Executor createCallbackExecutor(Builder builder) { + if (builder.callbackExecutor == null) { + return Platform.get().callbackExecutor(); + } else { + return builder.callbackExecutor; + } + } + + private String createHttpScheme(Builder builder) { + if (builder.secure) { + return Constants.SCHEME_HTTPS; + } else { + return Constants.SCHEME_HTTP; + } + } + + private Map> createClassMap(Builder builder) { + if (builder.classMap == null) { + return new HashMap>(); + } else { + return builder.classMap; + } + } + + private CDAService createRetrofitService(Builder builder) { + RestAdapter.Builder restBuilder = + new RestAdapter.Builder().setConverter(new GsonConverter(gson)) + .setRequestInterceptor(createInterceptor()); + + setEndPoint(builder, restBuilder); + setClientProvider(builder, restBuilder); + setLogLevel(builder, restBuilder); + + return restBuilder.build().create(CDAService.class); + } + + private Gson createGson() { + ResourceTypeAdapter rta = new ResourceTypeAdapter(spaceWrapper, classMap, httpScheme); + + return new GsonBuilder().registerTypeAdapter(CDAResource.class, rta) + .registerTypeAdapter(CDAAsset.class, rta) + .registerTypeAdapter(CDAContentType.class, rta) + .registerTypeAdapter(CDAEntry.class, rta) + .registerTypeAdapter(CDASpace.class, rta) + .create(); + } + + private void setLogLevel(Builder builder, RestAdapter.Builder restBuilder) { + if (builder.logLevel != null) { + restBuilder.setLogLevel(builder.logLevel); + } + } + + private void setClientProvider(Builder builder, RestAdapter.Builder restBuilder) { + if (builder.clientProvider != null) { + restBuilder.setClient(builder.clientProvider); + } + } + + private void setEndPoint(Builder builder, RestAdapter.Builder restBuilder) { + String endpoint; + + if (builder.endpoint == null) { + endpoint = Constants.ENDPOINT_CDA; + } else { + endpoint = builder.endpoint; + } + + restBuilder.setEndpoint(String.format("%s://%s", httpScheme, endpoint)); + } + + private RequestInterceptor createInterceptor() { + return new RequestInterceptor() { + @Override public void intercept(RequestFacade requestFacade) { + if (accessToken != null && !accessToken.isEmpty()) { + requestFacade.addHeader(HTTP_HEADER_AUTH, String.format(HTTP_OAUTH_PATTERN, accessToken)); + } + + requestFacade.addHeader(HTTP_HEADER_USER_AGENT, createUserAgent(propertiesReader)); + } + }; + } + + /** + * Client builder. + * + * Calling the following methods is required before calling {@link #build}: + *
    + *
  • {@link #setSpaceKey(String)}
  • + *
  • {@link #setAccessToken(String)}
  • + *
+ */ + public static class Builder { + // Configuration + String accessToken; + String spaceKey; + Client.Provider clientProvider; + String endpoint; + RestAdapter.LogLevel logLevel; + Executor callbackExecutor; + Map> classMap; + boolean secure; + + public Builder() { + // Defaults + this.secure = true; + } + + /** + * Sets the access token to be used with this client. + * + * @param accessToken string representing the access token to be used when + * authenticating against the delivery api + * @return this {@code Builder} instance + */ + public Builder setAccessToken(String accessToken) { + if (accessToken == null) { + throw new IllegalArgumentException("Cannot call setAccessToken() with null."); + } + + this.accessToken = accessToken; + return this; + } + + /** + * Sets the executor to use when invoking asynchronous callbacks. + * + * @param executor Executor on which any {@link CDACallback} methods will be invoked. This + * defaults to execute on the main thread for Android projects. For non-Android + * projects this defaults to the same thread of the HTTP client. + * @return this {@code Builder} instance + */ + public Builder setCallbackExecutor(Executor executor) { + if (executor == null) { + throw new IllegalArgumentException("Cannot call setCallbackExecutor() with null."); + } + + this.callbackExecutor = executor; + return this; + } + + /** + * Register a mapping between Content Type identifiers and class types. + * Use this method in order to register custom {@code CDAEntry} subclasses to be instantiated + * by the client when Entries of the given Content Type are retrieved from the server. + * + * Note: In case custom fields are declared in the custom class those should either be {@link + * java.io.Serializable} or denoted by the {@code transient} modifier in order to skip + * serialization, otherwise whenever trying to use {@link ResourceUtils#saveResourceToFile} + * an exception will be thrown. + * + * @param classMap mapping of Content Type identifiers to class types + * @return this {@code Builder} instance + */ + public Builder setCustomClasses(Map> classMap) { + if (classMap == null) { + throw new IllegalArgumentException("Cannot call setCustomClasses() with null."); + } + + this.classMap = new HashMap>(); + for (Map.Entry> entry : classMap.entrySet()) { + this.classMap.put(entry.getKey(), entry.getValue()); + } + return this; + } + + /** + * Sets a custom client to be used for making HTTP requests. + * + * @param client {@link retrofit.client.Client} instance + * @return this {@code Builder} instance + */ + public Builder setClient(final Client client) { + if (client == null) { + throw new IllegalArgumentException("Cannot call setClient() with null."); + } + + return setClientProvider(new Client.Provider() { + @Override public Client get() { + return client; + } + }); + } + + /** + * Sets a provider of clients to be used for making HTTP requests. + * + * @param clientProvider {@link retrofit.client.Client.Provider} instance + * @return this {@code Builder} instance + */ + public Builder setClientProvider(Client.Provider clientProvider) { + if (clientProvider == null) { + throw new IllegalArgumentException("Cannot call setClientProvider() with null."); + } + + this.clientProvider = clientProvider; + return this; + } + + /** + * Overrides the default remote address. + * + * @param remoteUrl String representing the remote address + * @return this {@link Builder} instance + */ + public Builder setEndpoint(String remoteUrl) { + if (remoteUrl == null) { + throw new IllegalArgumentException("Cannot call setEndpoint() with null."); + } + this.endpoint = remoteUrl; + return this; + } + + /** + * Change the log level. + * + * @param logLevel {@link retrofit.RestAdapter.LogLevel} value + * @return this {@code Builder} instance + */ + public Builder setLogLevel(RestAdapter.LogLevel logLevel) { + if (logLevel == null) { + throw new IllegalArgumentException("Cannot call setLogLevel() with null."); + } + + this.logLevel = logLevel; + return this; + } + + /** + * Sets the space key to be used with this client. + * + * @param spaceKey string representing the space key + * @return this {@code Builder} instance + */ + public Builder setSpaceKey(String spaceKey) { + if (spaceKey == null) { + throw new IllegalArgumentException("Cannot call setSpaceKey() with null."); + } + + this.spaceKey = spaceKey; + return this; + } + + /** + * Makes the client execute all requests via HTTP instead of HTTPS - use with caution. + * + * @return this {@code Builder} instance + */ + public Builder noSSL() { + this.secure = false; + return this; + } + + /** + * Sets this client to use the Preview API endpoint. + * Note: This is the same as invoking {@code setEndPoint(Constants.ENDPOINT_PREVIEW)} + * + * @return this {@code Builder} instance + */ + public Builder preview() { + return setEndpoint(Constants.ENDPOINT_PREVIEW); + } + + /** + * Builds and returns a {@link CDAClient} + * + * @return Client instance + */ + public CDAClient build() { + return new CDAClient(this); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/contentful/java/cda/CDAService.java b/src/main/java/com/contentful/java/cda/CDAService.java new file mode 100644 index 00000000..a1eeefc7 --- /dev/null +++ b/src/main/java/com/contentful/java/cda/CDAService.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import com.contentful.java.cda.model.CDASpace; +import com.contentful.java.cda.model.CDASyncedSpace; +import java.util.Map; +import retrofit.client.Response; +import retrofit.http.GET; +import retrofit.http.Path; +import retrofit.http.Query; +import retrofit.http.QueryMap; + +/** + * An interface used internally to create a Retrofit Service. + */ +interface CDAService { + @GET("/spaces/{space}") + CDASpace fetchSpace( + @Path("space") String spaceId); + + @GET("/spaces/{space}/{type}") + Response fetchArray( + @Path("space") String spaceId, + @Path("type") String type, + @QueryMap Map query); + + @GET("/spaces/{space}/{type}/{identifier}") + Response fetchResource( + @Path("space") String spaceId, + @Path("type") String resourceType, + @Path("identifier") String identifier); + + @GET("/spaces/{space}/sync") + CDASyncedSpace performSync( + @Path("space") String space, + @Query("initial") Boolean initial, + @Query("sync_token") String syncToken); +} diff --git a/src/main/java/com/contentful/java/cda/ClientContext.java b/src/main/java/com/contentful/java/cda/ClientContext.java new file mode 100644 index 00000000..59f030a2 --- /dev/null +++ b/src/main/java/com/contentful/java/cda/ClientContext.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import com.google.gson.Gson; +import java.util.Map; +import java.util.concurrent.Executor; + +/** + * ClientContext. + */ +final class ClientContext { + final CDAService service; + final Executor callbackExecutor; + final String spaceId; + final Gson gson; + final SpaceWrapper spaceWrapper; + final Map> customTypesMap; + + public ClientContext(CDAService service, Executor callbackExecutor, String spaceId, Gson gson, + SpaceWrapper spaceWrapper, Map> customTypesMap) { + this.service = service; + this.callbackExecutor = callbackExecutor; + this.spaceId = spaceId; + this.gson = gson; + this.spaceWrapper = spaceWrapper; + this.customTypesMap = customTypesMap; + } +} diff --git a/src/main/java/com/contentful/java/lib/Constants.java b/src/main/java/com/contentful/java/cda/Constants.java similarity index 83% rename from src/main/java/com/contentful/java/lib/Constants.java rename to src/main/java/com/contentful/java/cda/Constants.java index 6bd7bda1..f5a7b369 100644 --- a/src/main/java/com/contentful/java/lib/Constants.java +++ b/src/main/java/com/contentful/java/cda/Constants.java @@ -14,16 +14,18 @@ * limitations under the License. */ -package com.contentful.java.lib; +package com.contentful.java.cda; /** * Library constants. */ -public class Constants { +public final class Constants { private Constants() { + throw new UnsupportedOperationException(); } public static enum CDAResourceType { + Array, Asset, ContentType, DeletedAsset, @@ -33,7 +35,6 @@ public static enum CDAResourceType { Space } - @SuppressWarnings("UnusedDeclaration") public static enum CDAFieldType { Array, Boolean, @@ -59,10 +60,12 @@ public static enum CDAFieldType { public static final String ENDPOINT_PREVIEW = "preview.contentful.com"; public static final String DEFAULT_LOCALE = "en-US"; - // Idle thread name - public static final String IDLE_THREAD_NAME = "Contentful-Idle"; - // Resource types public static final String PATH_ASSETS = "assets"; + public static final String PATH_CONTENT_TYPES = "content_types"; public static final String PATH_ENTRIES = "entries"; + + // Properties + static final String SDK_PROPERTIES = "contentful_cda.properties"; + static final String PROP_VERSION_NAME = "version.name"; } diff --git a/src/main/java/com/contentful/java/cda/ModuleAssets.java b/src/main/java/com/contentful/java/cda/ModuleAssets.java new file mode 100644 index 00000000..f77a7f64 --- /dev/null +++ b/src/main/java/com/contentful/java/cda/ModuleAssets.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import com.contentful.java.cda.model.CDAAsset; +import java.io.InputStreamReader; + +/** + * Assets Module. + */ +public final class ModuleAssets extends BaseModule { + public ModuleAssets(ClientContext context) { + super(context); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public ExtAsync async() { + return extAsync; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public ExtRxJava rx() { + return extRxJava; + } + + @Override String getResourcePath() { + return Constants.PATH_ASSETS; + } + + @Override CDAAsset createCdaResource(InputStreamReader inputStreamReader) { + return context.gson.fromJson(inputStreamReader, CDAAsset.class); + } +} diff --git a/src/main/java/com/contentful/java/cda/ModuleContentTypes.java b/src/main/java/com/contentful/java/cda/ModuleContentTypes.java new file mode 100644 index 00000000..51c1fa7e --- /dev/null +++ b/src/main/java/com/contentful/java/cda/ModuleContentTypes.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import com.contentful.java.cda.model.CDAContentType; +import java.io.InputStreamReader; + +/** + * Content Types Module. + */ +public final class ModuleContentTypes extends BaseModule { + public ModuleContentTypes(ClientContext context) { + super(context); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public ExtAsync async() { + return extAsync; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public ExtRxJava rx() { + return extRxJava; + } + + @Override String getResourcePath() { + return Constants.PATH_CONTENT_TYPES; + } + + @Override CDAContentType createCdaResource(InputStreamReader inputStreamReader) { + return context.gson.fromJson(inputStreamReader, CDAContentType.class); + } +} diff --git a/src/main/java/com/contentful/java/cda/ModuleEntries.java b/src/main/java/com/contentful/java/cda/ModuleEntries.java new file mode 100644 index 00000000..dbd439f3 --- /dev/null +++ b/src/main/java/com/contentful/java/cda/ModuleEntries.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import com.contentful.java.cda.model.CDAEntry; +import java.io.InputStreamReader; + +/** + * Entries Module. + */ +public final class ModuleEntries extends BaseModule { + public ModuleEntries(ClientContext context) { + super(context); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public ExtAsync async() { + return extAsync; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public ExtRxJava rx() { + return extRxJava; + } + + @Override String getResourcePath() { + return Constants.PATH_ENTRIES; + } + + @Override CDAEntry createCdaResource(InputStreamReader inputStreamReader) { + return context.gson.fromJson(inputStreamReader, CDAEntry.class); + } +} diff --git a/src/main/java/com/contentful/java/cda/ModuleSpaces.java b/src/main/java/com/contentful/java/cda/ModuleSpaces.java new file mode 100644 index 00000000..82239676 --- /dev/null +++ b/src/main/java/com/contentful/java/cda/ModuleSpaces.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import com.contentful.java.cda.model.CDASpace; +import rx.Observable; + +import static com.contentful.java.cda.RxExtensions.defer; +import static com.contentful.java.cda.RxExtensions.subscribe; + +/** + * Spaces Module. + */ +public class ModuleSpaces extends AbsModule { + public ModuleSpaces(ClientContext context) { + super(context); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public ExtAsync async() { + return extAsync; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public ExtRxJava rx() { + return extRxJava; + } + + @Override ExtAsync createAsyncExtension() { + return new ExtAsync(); + } + + @Override ExtRxJava createRxJavaExtension() { + return new ExtRxJava(); + } + + /** + * Fetches the Space configured for this client. + * Note: upon success this will also refresh the cached result returned + * by {@link CDAClient#getSpace()}. + * + * @return space result instance + */ + public CDASpace fetch() { + ensureSpace(true); + return context.spaceWrapper.get(); + } + + public class ExtAsync extends AbsModule.Async { + /** + * Fetches the Space configured for this client. + * Note: upon success this will also refresh the cached result returned + * by {@link CDAClient#getSpace()}. + * + * @param callback callback + * @return the given {@code callback} instance + */ + public CDACallback fetch(CDACallback callback) { + return subscribe(rx().fetch(), callback, context); + } + } + + public class ExtRxJava extends AbsModule.Rx { + /** + * Get an {@code Observable} that fetches the space configured for this client. + * Note: upon success this will also refresh the cached result returned + * by {@link CDAClient#getSpace()}. + * + * @return {@code Observable} instance + */ + public Observable fetch() { + return defer(new RxExtensions.DefFunc() { + @Override CDASpace method() { + return ModuleSpaces.this.fetch(); + } + }); + } + } +} diff --git a/src/main/java/com/contentful/java/cda/ModuleSync.java b/src/main/java/com/contentful/java/cda/ModuleSync.java new file mode 100644 index 00000000..4a091d55 --- /dev/null +++ b/src/main/java/com/contentful/java/cda/ModuleSync.java @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import com.contentful.java.cda.model.CDASyncedSpace; +import retrofit.RetrofitError; +import rx.Observable; + +import static com.contentful.java.cda.RxExtensions.defer; +import static com.contentful.java.cda.RxExtensions.subscribe; + +/** + * Synchronization Module. + */ +public class ModuleSync extends AbsModule { + public ModuleSync(ClientContext context) { + super(context); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public ExtAsync async() { + return extAsync; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + public ExtRxJava rx() { + return extRxJava; + } + + @Override ExtAsync createAsyncExtension() { + return new ExtAsync(); + } + + @Override ExtRxJava createRxJavaExtension() { + return new ExtRxJava(); + } + + /** + * Performs initial space synchronization. + * + * @return synced space result instance + */ + public CDASyncedSpace performInitial() { + ensureSpaceForSync(); + + try { + return prepare(context.service.performSync(context.spaceId, true, null), true); + } catch (Exception e) { + throw RetrofitError.unexpectedError(null, e); + } + } + + /** + * Performs synchronization for a given {@code CDASyncedSpace}. + * + * @param syncedSpace space + * @return synced space result instance + */ + public CDASyncedSpace performWithSpace(CDASyncedSpace syncedSpace) { + ensureSpaceForSync(); + + String syncToken = syncedSpace.getSyncToken(); + + if (syncToken == null) { + throw new IllegalArgumentException( + "performWithSpace() called for a space with no sync token."); + } + + try { + return prepare(syncedSpace, context.service.performSync(context.spaceId, null, syncToken), + true); + } catch (Exception e) { + throw RetrofitError.unexpectedError(null, e); + } + } + + /** + * Performs synchronization with the given {@code syncToken}. + * + * @param syncToken sync token + * @return synced space result instance + */ + public CDASyncedSpace performWithToken(String syncToken) { + return performWithToken(syncToken, true); + } + + private CDASyncedSpace performWithToken(String syncToken, boolean iterate) { + ensureSpaceForSync(); + Utils.assertNotNull(syncToken, "syncToken"); + + try { + return prepare(context.service.performSync(context.spaceId, null, syncToken), iterate); + } catch (Exception e) { + throw RetrofitError.unexpectedError(null, e); + } + } + + CDASyncedSpace prepare(CDASyncedSpace syncedSpace, boolean iterate) throws Exception { + return prepare(null, syncedSpace, iterate); + } + + CDASyncedSpace prepare(CDASyncedSpace originalSpace, CDASyncedSpace updatedSpace, boolean iterate) + throws Exception { + CDASyncedSpace result = SyncProcessor.newInstance(originalSpace, updatedSpace, context).call(); + + if (iterate) { + result = iterateSpace(result); + } + + return result; + } + + /** + * Async extension for the Synchronization module. + */ + public class ExtAsync extends AbsModule.Async { + /** + * Performs initial space synchronization. + * + * @param callback callback + * @return synced space result instance + */ + public CDACallback performInitial(CDACallback callback) { + return subscribe(rx().performInitial(), callback, context); + } + + /** + * Performs synchronization for a given {@code CDASyncedSpace}. + * + * @param syncedSpace space + * @param callback callback + * @return synced space result instance + */ + public CDACallback performWithSpace(CDASyncedSpace syncedSpace, + CDACallback callback) { + return subscribe(rx().performWithSpace(syncedSpace), callback, context); + } + + /** + * Performs synchronization with the given {@code syncToken}. + * + * @param syncToken sync token + * @param callback callback + * @return synced space result instance + */ + public CDACallback performWithToken(String syncToken, + CDACallback callback) { + return subscribe(rx().performWithToken(syncToken), callback, context); + } + } + + /** + * RxJava extension for the Synchronization module. + */ + public class ExtRxJava extends AbsModule.Rx { + /** + * Get an {@code Observable} that performs initial space synchronization. + * + * @return {@code Observable} instance + */ + public Observable performInitial() { + return defer(new RxExtensions.DefFunc() { + @Override CDASyncedSpace method() { + return ModuleSync.this.performInitial(); + } + }); + } + + /** + * Get an {@code Observable} that performs synchronization for a given {@code CDASyncedSpace}. + * + * @param syncedSpace space + * @return {@code Observable} instance + */ + public Observable performWithSpace(final CDASyncedSpace syncedSpace) { + return defer(new RxExtensions.DefFunc() { + @Override CDASyncedSpace method() { + return ModuleSync.this.performWithSpace(syncedSpace); + } + }); + } + + /** + * Get an {@code Observable} that performs synchronization with the given {@code syncToken}. + * + * @param syncToken sync token + * @return {@code Observable} instance + */ + public Observable performWithToken(final String syncToken) { + return defer(new RxExtensions.DefFunc() { + @Override CDASyncedSpace method() { + return ModuleSync.this.performWithToken(syncToken); + } + }); + } + } + + void ensureSpaceForSync() { + ensureSpace(true); + } + + CDASyncedSpace iterateSpace(CDASyncedSpace syncedSpace) throws Exception { + String nextPageUrl = syncedSpace.getNextPageUrl(); + while (nextPageUrl != null) { + String syncToken = Utils.getQueryParamFromUrl(nextPageUrl, "sync_token"); + CDASyncedSpace nextPage = performWithToken(syncToken, false); + syncedSpace = SyncProcessor.newInstance(syncedSpace, nextPage, context).call(); + nextPageUrl = nextPage.getNextPageUrl(); + } + return syncedSpace; + } +} diff --git a/src/main/java/com/contentful/java/api/Platform.java b/src/main/java/com/contentful/java/cda/Platform.java similarity index 97% rename from src/main/java/com/contentful/java/api/Platform.java rename to src/main/java/com/contentful/java/cda/Platform.java index 50b40149..d0a10f23 100644 --- a/src/main/java/com/contentful/java/api/Platform.java +++ b/src/main/java/com/contentful/java/cda/Platform.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.api; +package com.contentful.java.cda; import android.os.Build; import java.util.concurrent.Executor; diff --git a/src/test/java/com/contentful/java/AbsTestCase.java b/src/main/java/com/contentful/java/cda/PropertiesReader.java similarity index 59% rename from src/test/java/com/contentful/java/AbsTestCase.java rename to src/main/java/com/contentful/java/cda/PropertiesReader.java index 2d25deb5..406fd9e0 100644 --- a/src/test/java/com/contentful/java/AbsTestCase.java +++ b/src/main/java/com/contentful/java/cda/PropertiesReader.java @@ -14,22 +14,22 @@ * limitations under the License. */ -package com.contentful.java; +package com.contentful.java.cda; -import com.contentful.java.lib.TestCallback; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import java.io.IOException; +import java.util.Properties; /** - * Base class for all test cases. + * PropertiesReader. */ -public abstract class AbsTestCase { - void verifyResultNotEmpty(TestCallback result) { - // check that error is empty - assertNull(result.error); +class PropertiesReader { + PropertiesReader() { + } - // check that result is not empty - assertNotNull(result.value); + String getField(String field) throws IOException { + Properties properties = new Properties(); + properties.load(PropertiesReader.class.getClassLoader().getResourceAsStream( + Constants.SDK_PROPERTIES)); + return properties.getProperty(field); } } diff --git a/src/main/java/com/contentful/java/api/ResourceTypeAdapter.java b/src/main/java/com/contentful/java/cda/ResourceTypeAdapter.java similarity index 83% rename from src/main/java/com/contentful/java/api/ResourceTypeAdapter.java rename to src/main/java/com/contentful/java/cda/ResourceTypeAdapter.java index 8e730a92..eb6f7736 100644 --- a/src/main/java/com/contentful/java/api/ResourceTypeAdapter.java +++ b/src/main/java/com/contentful/java/cda/ResourceTypeAdapter.java @@ -14,17 +14,16 @@ * limitations under the License. */ -package com.contentful.java.api; +package com.contentful.java.cda; -import com.contentful.java.lib.Constants; -import com.contentful.java.model.CDAAsset; -import com.contentful.java.model.CDAContentType; -import com.contentful.java.model.CDAEntry; -import com.contentful.java.model.CDAResource; -import com.contentful.java.model.CDASpace; -import com.contentful.java.model.Locale; -import com.contentful.java.model.ResourceWithList; -import com.contentful.java.model.ResourceWithMap; +import com.contentful.java.cda.model.CDAAsset; +import com.contentful.java.cda.model.CDAContentType; +import com.contentful.java.cda.model.CDAEntry; +import com.contentful.java.cda.model.CDALocale; +import com.contentful.java.cda.model.CDAResource; +import com.contentful.java.cda.model.CDASpace; +import com.contentful.java.cda.model.ResourceWithList; +import com.contentful.java.cda.model.ResourceWithMap; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; @@ -41,11 +40,15 @@ * Custom type adapter for de-serializing resources. */ class ResourceTypeAdapter implements JsonDeserializer { - // Client reference - private final CDAClient client; + private final SpaceWrapper spaceWrapper; + private final Map> customTypesMap; + private final String httpScheme; - public ResourceTypeAdapter(CDAClient client) { - this.client = client; + public ResourceTypeAdapter(SpaceWrapper spaceWrapper, Map> customTypesMap, + String httpScheme) { + this.spaceWrapper = spaceWrapper; + this.customTypesMap = customTypesMap; + this.httpScheme = httpScheme; } @Override public CDAResource deserialize(JsonElement jsonElement, Type type, @@ -101,7 +104,7 @@ private CDAAsset deserializeAsset(JsonElement jsonElement, JsonDeserializationCo CDAAsset result = new CDAAsset(); setBaseFields(result, sys, jsonElement, context); Map fileMap = (Map) result.getFields().get("file"); - String defaultLocale = client.getSpace().getDefaultLocale(); + String defaultLocale = spaceWrapper.get().getDefaultLocale(); if (fileMap.containsKey(defaultLocale)) { Object map = fileMap.get(defaultLocale); @@ -111,7 +114,7 @@ private CDAAsset deserializeAsset(JsonElement jsonElement, JsonDeserializationCo } } - result.setUrl(String.format("%s:%s", client.getHttpScheme(), fileMap.get("url"))); + result.setUrl(String.format("%s:%s", httpScheme, fileMap.get("url"))); result.setMimeType((String) fileMap.get("contentType")); return result; @@ -145,7 +148,7 @@ private CDAContentType deserializeContentType(JsonElement jsonElement, /** * De-serialize a resource of type Entry. This method should return a {@code CDAEntry} object or * in case the resource matches a previously registered custom class via {@link - * CDAClient#registerCustomClass}, an object of that custom class type will be created. + * CDAClient.Builder#setCustomClasses(Map)}, an object of that custom class type will be created. * * @param jsonElement the resource in JSON form * @param context gson context @@ -163,7 +166,7 @@ private CDAEntry deserializeEntry(JsonElement jsonElement, JsonDeserializationCo .get("id") .getAsString(); - Class clazz = client.getCustomTypesMap().get(contentTypeId); + Class clazz = customTypesMap.get(contentTypeId); if (clazz == null) { // Create a regular Entry, no custom class was registered. @@ -198,14 +201,14 @@ private CDASpace deserializeSpace(JsonElement jsonElement, JsonDeserializationCo // Locales JsonArray localesArray = jsonElement.getAsJsonObject().get("locales").getAsJsonArray(); - Type t = new TypeToken>() { } .getType(); - ArrayList locales = context.deserialize(localesArray, t); + Type t = new TypeToken>() { } .getType(); + ArrayList locales = context.deserialize(localesArray, t); // Default locale String defaultLocale = Constants.DEFAULT_LOCALE; - for (Locale l : locales) { - if (l.isDefault) { - defaultLocale = l.code; + for (CDALocale l : locales) { + if (l.isDefault()) { + defaultLocale = l.getCode(); break; } } @@ -232,10 +235,12 @@ private CDASpace deserializeSpace(JsonElement jsonElement, JsonDeserializationCo @SuppressWarnings("unchecked") private void setBaseFields(CDAResource target, JsonObject sys, JsonElement jsonElement, JsonDeserializationContext context) { + CDASpace space = spaceWrapper.get(); + // System attributes Map sysMap = context.deserialize(sys, Map.class); if (sysMap.containsKey("space")) { - sysMap.put("space", client.getSpace()); + sysMap.put("space", space); } target.setSys(sysMap); @@ -243,10 +248,10 @@ private void setBaseFields(CDAResource target, JsonObject sys, JsonElement jsonE JsonElement fields = jsonElement.getAsJsonObject().get("fields"); if (target instanceof ResourceWithMap) { ResourceWithMap res = (ResourceWithMap) target; - target.setLocale(client.getSpace().getDefaultLocale()); + target.setLocale(space.getDefaultLocale()); res.setRawFields( context.>deserialize(fields.getAsJsonObject(), Map.class)); - res.getLocalizedFieldsMap().put(client.getSpace().getDefaultLocale(), res.getRawFields()); + res.getLocalizedFieldsMap().put(space.getDefaultLocale(), res.getRawFields()); } else if (target instanceof ResourceWithList) { ResourceWithList res = (ResourceWithList) target; res.setFields(context.>deserialize(fields.getAsJsonArray(), List.class)); diff --git a/src/main/java/com/contentful/java/lib/ResourceUtils.java b/src/main/java/com/contentful/java/cda/ResourceUtils.java similarity index 82% rename from src/main/java/com/contentful/java/lib/ResourceUtils.java rename to src/main/java/com/contentful/java/cda/ResourceUtils.java index a17b45e3..c4d9b38e 100644 --- a/src/main/java/com/contentful/java/lib/ResourceUtils.java +++ b/src/main/java/com/contentful/java/cda/ResourceUtils.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.contentful.java.lib; +package com.contentful.java.cda; -import com.contentful.java.model.CDAResource; +import com.contentful.java.cda.model.CDAResource; +import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -27,8 +28,9 @@ /** * Resource Utilities. */ -public class ResourceUtils { +public final class ResourceUtils { private ResourceUtils() { + throw new UnsupportedOperationException(); } /** @@ -51,19 +53,11 @@ public static void saveResourceToFile(CDAResource resource, File file) throws IO oos.writeObject(resource); } finally { if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - e.printStackTrace(); - } + closeStream(fos); } if (oos != null) { - try { - oos.close(); - } catch (IOException e) { - e.printStackTrace(); - } + closeStream(oos); } } } @@ -92,22 +86,23 @@ public static CDAResource readResourceFromFile(File file) result = (CDAResource) oos.readObject(); } finally { if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - e.printStackTrace(); - } + closeStream(fis); } if (oos != null) { - try { - oos.close(); - } catch (IOException e) { - e.printStackTrace(); - } + closeStream(oos); } } return result; } + + static boolean closeStream(Closeable stream) { + try { + stream.close(); + return true; + } catch (IOException e) { + return false; + } + } } diff --git a/src/main/java/com/contentful/java/api/RxExtensions.java b/src/main/java/com/contentful/java/cda/RxExtensions.java similarity index 56% rename from src/main/java/com/contentful/java/api/RxExtensions.java rename to src/main/java/com/contentful/java/cda/RxExtensions.java index e63795a3..605a2f79 100644 --- a/src/main/java/com/contentful/java/api/RxExtensions.java +++ b/src/main/java/com/contentful/java/cda/RxExtensions.java @@ -14,8 +14,9 @@ * limitations under the License. */ -package com.contentful.java.api; +package com.contentful.java.cda; +import java.util.concurrent.Executor; import retrofit.RetrofitError; import rx.Observable; import rx.functions.Action1; @@ -34,9 +35,11 @@ private RxExtensions() { * Base Action. */ abstract static class AbsAction implements Action1 { + final Executor executor; final CDACallback callback; - public AbsAction(CDACallback callback) { + public AbsAction(Executor executor, CDACallback callback) { + this.executor = executor; this.callback = callback; } } @@ -45,15 +48,15 @@ public AbsAction(CDACallback callback) { * Success Action. */ static class ActionSuccess extends AbsAction { - public ActionSuccess(CDACallback callback) { - super(callback); + public ActionSuccess(Executor executor, CDACallback callback) { + super(executor, callback); } @Override public void call(final T t) { if (!callback.isCancelled()) { - Platform.get().callbackExecutor().execute(new Runnable() { + executor.execute(new Runnable() { @Override public void run() { - callback.onSuccess(t, null); + callback.onSuccess(t); } }); } @@ -65,19 +68,23 @@ public ActionSuccess(CDACallback callback) { */ static class ActionError extends AbsAction { @SuppressWarnings("unchecked") - public ActionError(CDACallback callback) { - super(callback); + public ActionError(Executor executor, CDACallback callback) { + super(executor, callback); } @Override public void call(final Throwable t) { + final RetrofitError retrofitError; + + if (t instanceof RetrofitError) { + retrofitError = (RetrofitError) t; + } else { + retrofitError = RetrofitError.unexpectedError(null, t); + } + if (!callback.isCancelled()) { - Platform.get().callbackExecutor().execute(new Runnable() { + executor.execute(new Runnable() { @Override public void run() { - if (t instanceof RetrofitError) { - callback.onFailure((RetrofitError) t); - } else { - callback.onFailure(RetrofitError.unexpectedError(null, t)); - } + callback.onFailure(retrofitError); } }); } @@ -96,20 +103,19 @@ abstract static class DefFunc implements Func0> { } /** - * Creates an Observable with the given {@code func} function and subscribes to it - * with a set of pre-defined actions. The provided {@code callback} will be passed to these - * actions in order to populate the events. + * Defers the given {@code func} and returns an {@code Observable} from it, by default + * the {@code Observable} is configured to subscribe on an IO-bound worker. */ - static CDACallback defer(DefFunc func, CDACallback callback) { - if (callback == null) { - throw new IllegalArgumentException("callback may not be null."); - } + static Observable defer(RxExtensions.DefFunc func) { + return Observable.defer(func).subscribeOn(Schedulers.io()); + } - Observable.defer(func) - .subscribeOn(Schedulers.io()) - .subscribe( - new ActionSuccess(callback), - new ActionError(callback)); + static CDACallback subscribe(Observable observable, CDACallback callback, + ClientContext context) { + Utils.assertNotNull(callback, "callback"); + observable.subscribe( + new RxExtensions.ActionSuccess(context.callbackExecutor, callback), + new RxExtensions.ActionError(context.callbackExecutor, callback)); return callback; } } diff --git a/src/main/java/com/contentful/java/cda/SpaceWrapper.java b/src/main/java/com/contentful/java/cda/SpaceWrapper.java new file mode 100644 index 00000000..d4ad38bc --- /dev/null +++ b/src/main/java/com/contentful/java/cda/SpaceWrapper.java @@ -0,0 +1,21 @@ +package com.contentful.java.cda; + +import com.contentful.java.cda.model.CDASpace; + +/** + * SpaceWrapper. + */ +final class SpaceWrapper { + private CDASpace space; + + SpaceWrapper() { + } + + synchronized CDASpace get() { + return space; + } + + synchronized void set(CDASpace space) { + this.space = space; + } +} diff --git a/src/main/java/com/contentful/java/api/SpaceMerger.java b/src/main/java/com/contentful/java/cda/SyncProcessor.java similarity index 68% rename from src/main/java/com/contentful/java/api/SpaceMerger.java rename to src/main/java/com/contentful/java/cda/SyncProcessor.java index 44faa1a5..26be74d7 100644 --- a/src/main/java/com/contentful/java/api/SpaceMerger.java +++ b/src/main/java/com/contentful/java/cda/SyncProcessor.java @@ -14,16 +14,14 @@ * limitations under the License. */ -package com.contentful.java.api; +package com.contentful.java.cda; -import com.contentful.java.model.CDAResource; -import com.contentful.java.model.CDASpace; -import com.contentful.java.model.CDASyncedSpace; +import com.contentful.java.cda.model.CDAResource; +import com.contentful.java.cda.model.CDASyncedSpace; import java.util.ArrayList; import java.util.concurrent.Callable; -import retrofit.client.Response; -import static com.contentful.java.lib.Constants.CDAResourceType; +import static com.contentful.java.cda.Constants.CDAResourceType; /** * Custom Callable used internally to prepare array sync result objects. @@ -36,25 +34,24 @@ * This will also create and execute an {@code ArrayParser} before returning the result to resolve * any links after the merge operation. */ -class SpaceMerger implements Callable { +final class SyncProcessor implements Callable { private final CDASyncedSpace originalSpace; private final CDASyncedSpace updatedSpace; - private final CDACallback callback; - private final Response response; - private final CDASpace space; - - public SpaceMerger(CDASyncedSpace originalSpace, CDASyncedSpace updatedSpace, - CDACallback callback, Response response, CDASpace space) { + private final ClientContext context; + private SyncProcessor(CDASyncedSpace originalSpace, CDASyncedSpace updatedSpace, + ClientContext context) { this.originalSpace = originalSpace; this.updatedSpace = updatedSpace; - this.callback = callback; - this.response = response; - this.space = space; + this.context = context; + } + + public static SyncProcessor newInstance(CDASyncedSpace originalSpace, CDASyncedSpace updatedSpace, + ClientContext context) { + return new SyncProcessor(originalSpace, updatedSpace, context); } - @SuppressWarnings("unchecked") - @Override public CDASyncedSpace call() throws Exception { + @SuppressWarnings("unchecked") @Override public CDASyncedSpace call() throws Exception { if (originalSpace != null) { ArrayList originalItems = new ArrayList(originalSpace.getItems()); ArrayList updatedItems = updatedSpace.getItems(); @@ -81,18 +78,11 @@ public SpaceMerger(CDASyncedSpace originalSpace, CDASyncedSpace updatedSpace, updatedItems.addAll(originalItems); } - CDASyncedSpace result = null; - - try { - result = new ArrayParser(updatedSpace, space).call(); - } catch (Exception e) { - e.printStackTrace(); - } - - if (callback != null && !callback.isCancelled()) { - callback.success(result, response); + String nextSyncUrl = updatedSpace.getNextSyncUrl(); + if (nextSyncUrl != null) { + updatedSpace.setSyncToken(Utils.getQueryParamFromUrl(nextSyncUrl, "sync_token")); } - return result; + return new ArrayParser(updatedSpace, context).call(); } } diff --git a/src/main/java/com/contentful/java/cda/Utils.java b/src/main/java/com/contentful/java/cda/Utils.java new file mode 100644 index 00000000..7efbde6f --- /dev/null +++ b/src/main/java/com/contentful/java/cda/Utils.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLDecoder; +import java.util.concurrent.Executor; + +/** + * SDK utilities + */ +class Utils { + static Decoder decoder = new Decoder() { + @Override public String decode(String url) throws UnsupportedEncodingException { + return URLDecoder.decode(url, "UTF-8"); + } + }; + + private Utils() { + throw new UnsupportedOperationException(); + } + + /** + * Asserts that the given {@code object} with name {@code param} is not null, throws + * {@link IllegalArgumentException} otherwise. + */ + static void assertNotNull(Object object, String param) { + if (object == null) { + throw new IllegalArgumentException(String.format( + "%s may not be null.", param)); + } + } + + static String getQueryParamFromUrl(String url, String param) { + return getQueryParamFromUrl(url, param, decoder); + } + + static String getQueryParamFromUrl(String url, String param, Decoder decoder) { + URI uri = URI.create(url); + String query = uri.getQuery(); + + if (query == null) { + return null; + } + + String[] pairs = query.split("&"); + for (String pair : pairs) { + String[] split = pair.split("="); + if (split.length != 2) { + continue; + } + + if (param.equalsIgnoreCase(split[0])) { + try { + return decoder.decode(split[1]); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + } + + return null; + } + + interface Decoder { + String decode(String url) throws UnsupportedEncodingException; + } + + static class SynchronousExecutor implements Executor { + @Override public void execute(Runnable runnable) { + runnable.run(); + } + } +} + diff --git a/src/main/java/com/contentful/java/model/ArrayResource.java b/src/main/java/com/contentful/java/cda/model/ArrayResource.java similarity index 94% rename from src/main/java/com/contentful/java/model/ArrayResource.java rename to src/main/java/com/contentful/java/cda/model/ArrayResource.java index 45a6b9e7..0774b8a9 100644 --- a/src/main/java/com/contentful/java/model/ArrayResource.java +++ b/src/main/java/com/contentful/java/cda/model/ArrayResource.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; /** * Class representing a resource that may hold a collection of CDA resources. diff --git a/src/main/java/com/contentful/java/model/CDAArray.java b/src/main/java/com/contentful/java/cda/model/CDAArray.java similarity index 98% rename from src/main/java/com/contentful/java/model/CDAArray.java rename to src/main/java/com/contentful/java/cda/model/CDAArray.java index 8ef346f7..f9252dc1 100644 --- a/src/main/java/com/contentful/java/model/CDAArray.java +++ b/src/main/java/com/contentful/java/cda/model/CDAArray.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; import com.google.gson.annotations.SerializedName; import java.io.Serializable; diff --git a/src/main/java/com/contentful/java/model/CDAAsset.java b/src/main/java/com/contentful/java/cda/model/CDAAsset.java similarity index 97% rename from src/main/java/com/contentful/java/model/CDAAsset.java rename to src/main/java/com/contentful/java/cda/model/CDAAsset.java index a2670457..766d0023 100644 --- a/src/main/java/com/contentful/java/model/CDAAsset.java +++ b/src/main/java/com/contentful/java/cda/model/CDAAsset.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; /** * Class representing a single Asset resource. diff --git a/src/main/java/com/contentful/java/model/CDAContentType.java b/src/main/java/com/contentful/java/cda/model/CDAContentType.java similarity index 97% rename from src/main/java/com/contentful/java/model/CDAContentType.java rename to src/main/java/com/contentful/java/cda/model/CDAContentType.java index 8ef00d02..5694d0c5 100644 --- a/src/main/java/com/contentful/java/model/CDAContentType.java +++ b/src/main/java/com/contentful/java/cda/model/CDAContentType.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; import com.google.gson.annotations.SerializedName; import java.util.Map; diff --git a/src/main/java/com/contentful/java/model/CDAEntry.java b/src/main/java/com/contentful/java/cda/model/CDAEntry.java similarity index 94% rename from src/main/java/com/contentful/java/model/CDAEntry.java rename to src/main/java/com/contentful/java/cda/model/CDAEntry.java index 157182e5..4cb0268f 100644 --- a/src/main/java/com/contentful/java/model/CDAEntry.java +++ b/src/main/java/com/contentful/java/cda/model/CDAEntry.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; /** * Class representing a single Entry resource. diff --git a/src/main/java/com/contentful/java/model/Locale.java b/src/main/java/com/contentful/java/cda/model/CDALocale.java similarity index 70% rename from src/main/java/com/contentful/java/model/Locale.java rename to src/main/java/com/contentful/java/cda/model/CDALocale.java index f9fa7985..0fdd029f 100644 --- a/src/main/java/com/contentful/java/model/Locale.java +++ b/src/main/java/com/contentful/java/cda/model/CDALocale.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; import com.google.gson.annotations.SerializedName; import java.io.Serializable; @@ -23,19 +23,23 @@ * Class representing a single Locale. */ @SuppressWarnings("UnusedDeclaration") -public class Locale implements Serializable { - public String code; +public class CDALocale implements Serializable { + private String code; @SerializedName("default") - public boolean isDefault; + private boolean isDefault; - public String name; + private String name; - @Override public String toString() { - return "Locale{" - + "code='" + code + '\'' - + ", isDefault=" + isDefault - + ", name='" + name + '\'' - + '}'; + public String getCode() { + return code; + } + + public boolean isDefault() { + return isDefault; + } + + public String getName() { + return name; } } diff --git a/src/main/java/com/contentful/java/model/CDAResource.java b/src/main/java/com/contentful/java/cda/model/CDAResource.java similarity index 98% rename from src/main/java/com/contentful/java/model/CDAResource.java rename to src/main/java/com/contentful/java/cda/model/CDAResource.java index e93c74ae..d9faafbf 100644 --- a/src/main/java/com/contentful/java/model/CDAResource.java +++ b/src/main/java/com/contentful/java/cda/model/CDAResource.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; import java.io.Serializable; import java.util.Map; diff --git a/src/main/java/com/contentful/java/model/CDASpace.java b/src/main/java/com/contentful/java/cda/model/CDASpace.java similarity index 83% rename from src/main/java/com/contentful/java/model/CDASpace.java rename to src/main/java/com/contentful/java/cda/model/CDASpace.java index 20d6f888..aed982be 100644 --- a/src/main/java/com/contentful/java/model/CDASpace.java +++ b/src/main/java/com/contentful/java/cda/model/CDASpace.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; import java.util.ArrayList; @@ -23,10 +23,10 @@ */ public class CDASpace extends CDAResource { private String defaultLocale; - private ArrayList locales; + private ArrayList locales; private String name; - public CDASpace(String defaultLocale, ArrayList locales, String name) { + public CDASpace(String defaultLocale, ArrayList locales, String name) { this.defaultLocale = defaultLocale; this.locales = locales; this.name = name; @@ -36,7 +36,7 @@ public String getDefaultLocale() { return defaultLocale; } - public ArrayList getLocales() { + public ArrayList getLocales() { return locales; } diff --git a/src/main/java/com/contentful/java/model/CDASyncedSpace.java b/src/main/java/com/contentful/java/cda/model/CDASyncedSpace.java similarity index 97% rename from src/main/java/com/contentful/java/model/CDASyncedSpace.java rename to src/main/java/com/contentful/java/cda/model/CDASyncedSpace.java index 0fe7327c..1afde785 100644 --- a/src/main/java/com/contentful/java/model/CDASyncedSpace.java +++ b/src/main/java/com/contentful/java/cda/model/CDASyncedSpace.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; import java.util.ArrayList; diff --git a/src/main/java/com/contentful/java/model/ResourceWithList.java b/src/main/java/com/contentful/java/cda/model/ResourceWithList.java similarity index 96% rename from src/main/java/com/contentful/java/model/ResourceWithList.java rename to src/main/java/com/contentful/java/cda/model/ResourceWithList.java index 9a32465c..36c462cf 100644 --- a/src/main/java/com/contentful/java/model/ResourceWithList.java +++ b/src/main/java/com/contentful/java/cda/model/ResourceWithList.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; import java.util.List; diff --git a/src/main/java/com/contentful/java/model/ResourceWithMap.java b/src/main/java/com/contentful/java/cda/model/ResourceWithMap.java similarity index 98% rename from src/main/java/com/contentful/java/model/ResourceWithMap.java rename to src/main/java/com/contentful/java/cda/model/ResourceWithMap.java index 3ee11c8f..4a6ff878 100644 --- a/src/main/java/com/contentful/java/model/ResourceWithMap.java +++ b/src/main/java/com/contentful/java/cda/model/ResourceWithMap.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.contentful.java.model; +package com.contentful.java.cda.model; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/contentful/java/lib/package-info.java b/src/main/java/com/contentful/java/lib/package-info.java deleted file mode 100644 index 26b3ab45..00000000 --- a/src/main/java/com/contentful/java/lib/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Library definitions, constants and utilities. - */ -package com.contentful.java.lib; \ No newline at end of file diff --git a/src/main/java/com/contentful/java/model/package-info.java b/src/main/java/com/contentful/java/model/package-info.java deleted file mode 100644 index 97ee908e..00000000 --- a/src/main/java/com/contentful/java/model/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Java representations for different types of resources available on the Content Delivery API. - */ -package com.contentful.java.model; \ No newline at end of file diff --git a/src/main/java/com/contentful/java/package-info.java b/src/main/java/com/contentful/java/package-info.java deleted file mode 100644 index 1eb3f3bf..00000000 --- a/src/main/java/com/contentful/java/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Java SDK for Contentful's Content Delivery API. - */ -package com.contentful.java; \ No newline at end of file diff --git a/src/test/java/com/contentful/java/AssetsTest.java b/src/test/java/com/contentful/java/AssetsTest.java deleted file mode 100644 index 475a7079..00000000 --- a/src/test/java/com/contentful/java/AssetsTest.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java; - -import com.contentful.java.api.CDAClient; -import com.contentful.java.lib.MockClient; -import com.contentful.java.lib.TestCallback; -import com.contentful.java.lib.TestClientFactory; -import com.contentful.java.model.CDAArray; -import com.contentful.java.model.CDAAsset; -import com.contentful.java.model.CDAResource; -import java.util.ArrayList; -import java.util.HashMap; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Tests for fetching Asset resources. - */ -public class AssetsTest extends AbsTestCase { - @Test public void testFetchAssets() throws Exception { - TestCallback callback = new TestCallback(); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_assets.json")) - .build(); - - client.fetchAssets(callback); - - callback.await(); - verifyResultNotEmpty(callback); - verifyAssets(callback.value); - } - - @Test public void testFetchAssetsBlocking() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_assets.json")) - .build(); - - CDAArray result = client.fetchAssetsBlocking(); - verifyAssets(result); - } - - @Test public void testFetchAssetsMatching() throws Exception { - TestCallback callback = new TestCallback(); - - HashMap query = new HashMap(); - query.put("sys.id", "jake"); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_assets_matching.json")) - .build(); - - client.fetchAssetsMatching(query, callback); - callback.await(); - - verifyResultNotEmpty(callback); - verifyAssetsMatching(callback.value); - } - - @Test public void testFetchAssetsMatchingBlocking() throws Exception { - HashMap query = new HashMap(); - query.put("sys.id", "jake"); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_assets_matching.json")) - .build(); - - CDAArray result = client.fetchAssetsMatchingBlocking(query); - verifyAssetsMatching(result); - } - - @Test public void testFetchAssetWithIdentifier() throws Exception { - TestCallback callback = new TestCallback(); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_asset_with_identifier.json")) - .build(); - - client.fetchAssetWithIdentifier("fake", callback); - - callback.await(); - verifyResultNotEmpty(callback); - verifyAssetWithIdentifier(callback.value); - } - - @Test public void testFetchAssetWithIdentifierBlocking() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_asset_with_identifier.json")) - .build(); - - CDAAsset result = client.fetchAssetWithIdentifierBlocking("fake"); - verifyAssetWithIdentifier(result); - } - - void verifyAssets(CDAArray result) { - assertNotNull(result); - ArrayList items = result.getItems(); - - assertEquals(2, items.size()); - - CDAAsset item = (CDAAsset) items.get(0); - assertEquals("https://test.url.com/file_1.png", item.getUrl()); - assertEquals("image/png", item.getMimeType()); - - item = (CDAAsset) items.get(1); - assertEquals("https://test.url.com/file_2.png", item.getUrl()); - assertEquals("image/png", item.getMimeType()); - } - - void verifyAssetsMatching(CDAArray result) { - assertNotNull(result); - ArrayList items = result.getItems(); - - assertEquals(1, items.size()); - - CDAAsset asset = (CDAAsset) items.get(0); - - assertEquals( - "https://images.contentful.com/cfexampleapi/4hlteQAXS8iS0YCMU6QMWg/2a4d826144f014109364ccf5c891d2dd/jake.png", - asset.getUrl()); - - assertEquals("image/png", asset.getMimeType()); - } - - void verifyAssetWithIdentifier(CDAAsset result) { - assertNotNull(result); - - assertEquals("https://images.contentful.com/fake.png", result.getUrl()); - assertEquals("image/png", result.getMimeType()); - } -} diff --git a/src/test/java/com/contentful/java/ClientTest.java b/src/test/java/com/contentful/java/ClientTest.java deleted file mode 100644 index 3fe25daf..00000000 --- a/src/test/java/com/contentful/java/ClientTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java; - -import com.contentful.java.api.CDAClient; -import com.contentful.java.lib.Constants; -import com.contentful.java.lib.MockClient; -import com.contentful.java.lib.NyanCat; -import com.contentful.java.lib.TestCallback; -import com.contentful.java.lib.TestClientFactory; -import com.contentful.java.lib.TestException; -import com.contentful.java.model.CDAArray; -import com.contentful.java.model.CDAResource; -import java.io.IOException; -import java.net.URI; -import java.util.ArrayList; -import java.util.Collections; -import org.junit.Test; -import retrofit.ErrorHandler; -import retrofit.RetrofitError; -import retrofit.client.Client; -import retrofit.client.Request; -import retrofit.client.Response; -import retrofit.mime.TypedString; - -import static org.junit.Assert.assertTrue; - -/** - * Tests using custom clients and client providers. - */ -public class ClientTest extends AbsTestCase { - @Test public void testClientProvider() throws Exception { - TestCallback callback = new TestCallback(); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_client_provider.json")) - .build(); - - client.registerCustomClass("cat", NyanCat.class); - - client.fetchEntries(callback); - callback.await(); - verifyResultNotEmpty(callback); - - ArrayList items = callback.value.getItems(); - - assertTrue(items.size() == 1); - NyanCat cat = (NyanCat) items.get(0); - - EntriesTest.verifyNyanCatEntryWithClass(cat); - assertTrue(cat.getBestFriend().getBestFriend() == cat); - } - - @Test(expected = TestException.class) public void testCustomErrorHandler() throws Exception { - TestClientFactory.newInstance().setClient(new Client() { - @Override public Response execute(Request request) throws IOException { - throw new RuntimeException(); - } - }).setErrorHandler(new ErrorHandler() { - @Override public Throwable handleError(RetrofitError retrofitError) { - return new TestException(); - } - }).build().fetchSpaceBlocking(); - } - - @Test(expected = RetrofitError.class) public void testSynchronousException() throws Exception { - CDAClient client = - TestClientFactory.newInstance().setAccessToken("error").setSpaceKey("error").build(); - - client.fetchEntriesBlocking(); - } - - @SuppressWarnings("unchecked") @Test public void testNoSSL() throws Exception { - final Boolean[] res = new Boolean[] { null }; - - CDAClient client = TestClientFactory.newInstance().noSSL().setClient(new Client() { - @Override public Response execute(Request request) throws IOException { - URI uri = URI.create(request.getUrl()); - res[0] = Constants.SCHEME_HTTP.equalsIgnoreCase(uri.getScheme()); - - return new Response(request.getUrl(), 200, "OK", Collections.EMPTY_LIST, - new TypedString("{}")); - } - }).build(); - - client.fetchSpaceBlocking(); - assertTrue(res[0]); - } - - @Test public void testPreview() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setAccessToken("e5e8d4c5c122cf28fc1af3ff77d28bef78a3952957f15067bbc29f2f0dde0b50") - .preview() - .build(); - - client.fetchSpaceBlocking(); - } -} diff --git a/src/test/java/com/contentful/java/ContentTypeTest.java b/src/test/java/com/contentful/java/ContentTypeTest.java deleted file mode 100644 index 04e9176e..00000000 --- a/src/test/java/com/contentful/java/ContentTypeTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java; - -import com.contentful.java.api.CDAClient; -import com.contentful.java.lib.MockClient; -import com.contentful.java.lib.TestCallback; -import com.contentful.java.lib.TestClientFactory; -import com.contentful.java.model.CDAArray; -import com.contentful.java.model.CDAContentType; -import com.contentful.java.model.CDAResource; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Tests for fetching Content Type resources. - */ -public class ContentTypeTest extends AbsTestCase { - @Test public void testFetchContentTypes() throws Exception { - TestCallback callback = new TestCallback(); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_fetch_content_types.json")) - .build(); - - client.fetchContentTypes(callback); - callback.await(); - verifyResultNotEmpty(callback); - verifyContentTypes(callback.value); - } - - @Test public void testFetchContentTypesBlocking() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_fetch_content_types.json")) - .build(); - - CDAArray result = client.fetchContentTypesBlocking(); - verifyContentTypes(result); - } - - @Test public void testFetchContentTypeWithIdentifier() throws Exception { - TestCallback callback = new TestCallback(); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_fetch_content_type_with_id.json")) - .build(); - - client.fetchContentTypeWithIdentifier("MOCK", callback); - callback.await(); - verifyResultNotEmpty(callback); - verifyContentTypeWithIdentifier(callback.value); - } - - @Test public void testFetchContentTypeWithIdentifierBlocking() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_fetch_content_type_with_id.json")) - .build(); - - client.fetchContentTypeWithIdentifierBlocking("MOCK"); - } - - @Test public void testNoDisplayField() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_no_display_field.json")) - .build(); - - client.fetchContentTypesBlocking(); - } - - void verifyContentTypes(CDAArray result) { - assertNotNull(result); - - assertEquals(2, result.getTotal()); - assertEquals(0, result.getSkip()); - assertEquals(100, result.getLimit()); - - ArrayList items = result.getItems(); - assertEquals(2, items.size()); - - // 1st item (City) - CDAContentType item = (CDAContentType) items.get(0); - assertEquals("City", item.getName()); - assertNull(item.getUserDescription()); - assertEquals("name", item.getDisplayField()); - assertEquals("1t9IbcfdCk6m04uISSsaIK", item.getSys().get("id")); - - // field #1 - List fields = item.getFields(); - Map field = fields.get(0); - assertEquals("Name", field.get("name")); - assertEquals("name", field.get("id")); - assertEquals("Text", field.get("type")); - assertTrue((Boolean) field.get("required")); - - // field #2 - field = fields.get(1); - assertEquals("Center", field.get("name")); - assertEquals("center", field.get("id")); - assertEquals("Location", field.get("type")); - assertTrue((Boolean) field.get("required")); - - // 2nd item (Cat) - item = (CDAContentType) items.get(1); - assertEquals("Cat", item.getName()); - assertEquals("Meow!", item.getUserDescription()); - assertEquals("name", item.getDisplayField()); - assertEquals("63k4qdEi9aI8IQUGaYGg4O", item.getSys().get("id")); - - // field #1 - fields = item.getFields(); - field = fields.get(0); - assertEquals("name", field.get("id")); - assertEquals("Name", field.get("name")); - assertEquals("Text", field.get("type")); - assertTrue((Boolean) field.get("required")); - assertFalse((Boolean) field.get("localized")); - } - - void verifyContentTypeWithIdentifier(CDAContentType result) { - assertNotNull(result); - - assertEquals("Cat", result.getName()); - assertEquals("name", result.getDisplayField()); - assertEquals("Meow.", result.getUserDescription()); - assertEquals("cat", result.getSys().get("id")); - - List fields = result.getFields(); - assertEquals(8, fields.size()); - - assertEquals("name", fields.get(0).get("id")); - assertEquals("likes", fields.get(1).get("id")); - assertEquals("color", fields.get(2).get("id")); - assertEquals("bestFriend", fields.get(3).get("id")); - assertEquals("birthday", fields.get(4).get("id")); - assertEquals("lifes", fields.get(5).get("id")); - assertEquals("lives", fields.get(6).get("id")); - assertEquals("image", fields.get(7).get("id")); - } -} diff --git a/src/test/java/com/contentful/java/EntriesTest.java b/src/test/java/com/contentful/java/EntriesTest.java deleted file mode 100644 index 252405f2..00000000 --- a/src/test/java/com/contentful/java/EntriesTest.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java; - -import com.contentful.java.api.CDAClient; -import com.contentful.java.lib.MockClient; -import com.contentful.java.lib.NyanCat; -import com.contentful.java.lib.TestCallback; -import com.contentful.java.lib.TestClientFactory; -import com.contentful.java.model.CDAArray; -import com.contentful.java.model.CDAAsset; -import com.contentful.java.model.CDAEntry; -import com.contentful.java.model.CDAResource; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * Tests for fetching Entry resources. - */ -public class EntriesTest extends AbsTestCase { - @Test public void testFetchEntries() throws Exception { - TestCallback callback = new TestCallback(); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entries.json")) - .build(); - - client.fetchEntries(callback); - - callback.await(); - verifyResultNotEmpty(callback); - verifyEntries(callback.value); - } - - @Test public void testFetchEntriesBlocking() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entries.json")) - .build(); - - CDAArray result = client.fetchEntriesBlocking(); - verifyEntries(result); - } - - @Test public void testFetchEntriesMatching() throws Exception { - TestCallback callback = new TestCallback(); - - HashMap query = new HashMap(); - query.put("sys.id", "nyancat"); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entries_matching.json")) - .build(); - - client.fetchEntriesMatching(query, callback); - callback.await(); - - verifyResultNotEmpty(callback); - verifyEntriesMatching(callback.value); - } - - @Test public void testEntriesMatchingBlocking() throws Exception { - HashMap query = new HashMap(); - query.put("sys.id", "nyancat"); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entries_matching.json")) - .build(); - - CDAArray result = client.fetchEntriesMatchingBlocking(query); - verifyEntriesMatching(result); - } - - @Test public void testFetchEntryWithIdentifier() throws Exception { - TestCallback callback = new TestCallback(); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entry_nyancat.json")) - .build(); - - client.fetchEntryWithIdentifier("nyancat", callback); - callback.await(); - - verifyResultNotEmpty(callback); - verifyNyanCatEntry(callback.value); - } - - @Test public void testFetchEntryWithIdentifierBlocking() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entry_nyancat.json")) - .build(); - - CDAEntry result = client.fetchEntryWithIdentifierBlocking("nyancat"); - verifyNyanCatEntry(result); - } - - @Test public void testFetchEntryOfCustomClass() throws Exception { - TestCallback callback = new TestCallback(); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entry_nyancat.json")) - .build(); - - client.registerCustomClass("cat", NyanCat.class); - - client.fetchEntryWithIdentifier("nyancat", callback); - - callback.await(); - verifyResultNotEmpty(callback); - - verifyNyanCatEntryWithClass(callback.value); - } - - @Test public void testFetchEntryOfCustomClassBlocking() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entry_nyancat.json")) - .build(); - - client.registerCustomClass("cat", NyanCat.class); - - CDAEntry result = client.fetchEntryWithIdentifierBlocking("nyancat"); - verifyNyanCatEntryWithClass(result); - } - - @Test public void testFetchEntriesWithLinks() throws Exception { - TestCallback callback = new TestCallback(); - - // use a new client instance - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entries_with_includes.json")) - .build(); - - // register custom class - client.registerCustomClass("cat", NyanCat.class); - - HashMap query = new HashMap(); - query.put("sys.id", "nyancat"); - query.put("include", "1"); - - client.fetchEntriesMatching(query, callback); - callback.await(); - verifyResultNotEmpty(callback); - - ArrayList items = callback.value.getItems(); - assertTrue(items.size() == 11); - - NyanCat cat = (NyanCat) items.get(2); - NyanCat bestFriend = cat.getBestFriend(); - - assertNotNull(bestFriend); - assertTrue(bestFriend.getBestFriend() == cat); - - CDAEntry jake = (CDAEntry) items.get(9); - - Object value = jake.getFields().get("image"); - assertNotNull(value); - assertTrue(value instanceof CDAAsset); - - assertEquals( - "https://images.contentful.com/cfexampleapi/4hlteQAXS8iS0YCMU6QMWg/2a4d826144f014109364ccf5c891d2dd/jake.png", - ((CDAAsset) value).getUrl()); - - assertEquals("image/png", ((CDAAsset) value).getMimeType()); - } - - @Test public void testFetchEntriesWithNestedLinks() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entries_with_nested_links.json")) - .build(); - - CDAArray result = client.fetchEntriesBlocking(); - assertNotNull(result); - - ArrayList items = result.getItems(); - assertEquals(1, items.size()); - - CDAEntry entry = (CDAEntry) items.get(0); - ArrayList pictures = (ArrayList) entry.getFields().get("pictures"); - assertTrue(pictures.get(0) instanceof CDAAsset); - } - - void verifyEntries(CDAArray result) { - assertNotNull(result); - assertEquals(11, result.getItems().size()); - } - - void verifyEntriesMatching(CDAArray result) { - assertNotNull(result); - - ArrayList items = result.getItems(); - - assertEquals(1, items.size()); - - Object item = items.get(0); - assertTrue(item instanceof CDAEntry); - verifyNyanCatEntry((CDAEntry) item); - } - - @SuppressWarnings("unchecked") - void verifyNyanCatEntry(CDAEntry entry) { - assertNotNull(entry); - - // name - assertTrue("Nyan Cat".equals(entry.getFields().get("name"))); - - // color - assertTrue("rainbow".equals(entry.getFields().get("color"))); - - // lives - assertTrue(Double.valueOf(1337).equals(entry.getFields().get("lives"))); - - // likes - List likes = (List) entry.getFields().get("likes"); - assertNotNull(likes); - assertTrue(likes.size() == 2); - assertEquals("rainbows", likes.get(0)); - assertEquals("fish", likes.get(1)); - - // birthday - assertEquals("2011-04-04T22:00:00+00:00", entry.getFields().get("birthday")); - } - - static void verifyNyanCatEntryWithClass(CDAEntry entry) { - assertNotNull(entry); - assertTrue(entry instanceof NyanCat); - - NyanCat cat = (NyanCat) entry; - - // name - assertTrue("Nyan Cat".equals(cat.getName())); - - // color - assertTrue("rainbow".equals(cat.getColor())); - - // lives - assertTrue(Integer.valueOf(1337).equals(cat.getLives())); - - // likes - List likes = cat.getLikes(); - assertNotNull(likes); - assertTrue(likes.size() == 2); - assertEquals("rainbows", likes.get(0)); - assertEquals("fish", likes.get(1)); - - // birthday - assertEquals("2011-04-04T22:00:00+00:00", cat.getBirthday()); - } -} diff --git a/src/test/java/com/contentful/java/PagingTest.java b/src/test/java/com/contentful/java/PagingTest.java deleted file mode 100644 index 54eb194f..00000000 --- a/src/test/java/com/contentful/java/PagingTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java; - -import com.contentful.java.api.CDAClient; -import com.contentful.java.lib.MockClient; -import com.contentful.java.lib.TestClientFactory; -import com.contentful.java.model.CDAArray; -import java.util.HashMap; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Paging tests. - */ -public class PagingTest extends AbsTestCase { - @Test public void testArrayPaging() throws Exception { - // first request - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_paging_1.json")) - .build(); - - HashMap query = new HashMap(); - query.put("limit", "6"); - CDAArray firstPage = client.fetchEntriesMatchingBlocking(query); - - // second request - client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_paging_2.json")) - .build(); - - CDAArray secondPage = client.fetchArrayNextPageBlocking(firstPage); - assertNotNull(secondPage); - assertEquals(6, secondPage.getSkip()); - assertEquals(5, secondPage.getItems().size()); - - // third request - client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_paging_3.json")) - .build(); - - CDAArray thirdPage = client.fetchArrayNextPageBlocking(secondPage); - assertEquals(0, thirdPage.getItems().size()); - } -} diff --git a/src/test/java/com/contentful/java/ResourcesTest.java b/src/test/java/com/contentful/java/ResourcesTest.java deleted file mode 100644 index 6f312463..00000000 --- a/src/test/java/com/contentful/java/ResourcesTest.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java; - -import com.contentful.java.lib.Constants; -import com.contentful.java.lib.TestCallback; -import com.contentful.java.lib.TestClientFactory; -import com.contentful.java.model.CDAArray; -import com.contentful.java.model.CDAAsset; -import com.contentful.java.model.CDAContentType; -import com.contentful.java.model.CDAEntry; -import com.contentful.java.model.CDAResource; -import java.util.ArrayList; -import java.util.HashMap; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Tests for fetching resources of various types. - */ -public class ResourcesTest extends AbsTestCase { - @Test public void testFetchResourcesOfTypeAsset() throws Exception { - TestCallback callback = new TestCallback(); - - TestClientFactory.newInstance() - .build() - .fetchResourcesOfType(Constants.CDAResourceType.Asset, callback); - - callback.await(); - verifyResultNotEmpty(callback); - - assertTrue(callback.value.getTotal() > 0); - - for (CDAResource item : callback.value.getItems()) { - assertTrue(item instanceof CDAAsset); - assertEquals(Constants.CDAResourceType.Asset.toString(), item.getSys().get("type")); - } - } - - @Test public void testFetchResourcesOfTypeEntry() throws Exception { - TestCallback callback = new TestCallback(); - - TestClientFactory.newInstance() - .build() - .fetchResourcesOfType(Constants.CDAResourceType.Entry, callback); - - callback.await(); - verifyResultNotEmpty(callback); - - assertTrue(callback.value.getTotal() > 0); - - for (CDAResource item : callback.value.getItems()) { - assertTrue(item instanceof CDAEntry); - assertEquals(Constants.CDAResourceType.Entry.toString(), item.getSys().get("type")); - } - } - - @Test public void testFetchResourcesOfTypeContentType() throws Exception { - TestCallback callback = new TestCallback(); - - TestClientFactory.newInstance() - .build() - .fetchResourcesOfType(Constants.CDAResourceType.ContentType, callback); - - callback.await(); - verifyResultNotEmpty(callback); - - assertTrue(callback.value.getTotal() > 0); - - for (CDAResource item : callback.value.getItems()) { - assertTrue(item instanceof CDAContentType); - - assertEquals(Constants.CDAResourceType.ContentType.toString(), item.getSys().get("type")); - } - } - - @Test public void testFetchResourcesOfTypeAssetMatching() throws Exception { - TestCallback callback = new TestCallback(); - HashMap query = new HashMap(); - query.put("sys.id", "happycat"); - - TestClientFactory.newInstance() - .build() - .fetchResourcesOfTypeMatching(Constants.CDAResourceType.Asset, query, callback); - - callback.await(); - verifyResultNotEmpty(callback); - - assertEquals(1, callback.value.getTotal()); - - ArrayList items = callback.value.getItems(); - assertEquals(1, items.size()); - - CDAAsset asset = (CDAAsset) items.get(0); - assertEquals(Constants.CDAResourceType.Asset.toString(), asset.getSys().get("type")); - assertEquals("happycat", asset.getSys().get("id")); - assertEquals("Happy Cat", asset.getFields().get("title")); - } - - @Test public void testFetchResourcesOfTypeEntryMatching() throws Exception { - TestCallback callback = new TestCallback(); - - HashMap query = new HashMap(); - query.put("sys.id", "nyancat"); - - TestClientFactory.newInstance() - .build() - .fetchResourcesOfTypeMatching(Constants.CDAResourceType.Entry, query, callback); - - callback.await(); - verifyResultNotEmpty(callback); - - assertEquals(1, callback.value.getTotal()); - - ArrayList items = callback.value.getItems(); - assertEquals(1, items.size()); - - CDAEntry entry = (CDAEntry) items.get(0); - assertEquals(Constants.CDAResourceType.Entry.toString(), entry.getSys().get("type")); - assertEquals("nyancat", entry.getSys().get("id")); - assertEquals("Nyan Cat", entry.getFields().get("name")); - } -} diff --git a/src/test/java/com/contentful/java/SerializationsTest.java b/src/test/java/com/contentful/java/SerializationsTest.java deleted file mode 100644 index dce64452..00000000 --- a/src/test/java/com/contentful/java/SerializationsTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java; - -import com.contentful.java.api.CDAClient; -import com.contentful.java.lib.MockClient; -import com.contentful.java.lib.NyanCat; -import com.contentful.java.lib.ResourceUtils; -import com.contentful.java.lib.TestClientFactory; -import com.contentful.java.model.CDAArray; -import com.contentful.java.model.CDAAsset; -import com.contentful.java.model.CDAResource; -import com.contentful.java.model.CDASpace; -import java.io.File; -import java.util.ArrayList; -import java.util.Map; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * Serialization and persistence tests. - */ -public class SerializationsTest extends AbsTestCase { - @Test public void testSingleResource() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_asset_with_identifier.json")) - .build(); - - CDAAsset asset = client.fetchAssetWithIdentifierBlocking(""); - assertNotNull(asset); - - File f = new File("asset.dat"); - f.deleteOnExit(); - - ResourceUtils.saveResourceToFile(asset, f); - asset = (CDAAsset) ResourceUtils.readResourceFromFile(f); - assertNotNull(asset); - - Map fields = asset.getFields(); - assertNotNull(fields); - - assertEquals("fake", fields.get("title")); - assertEquals("https://images.contentful.com/fake.png", asset.getUrl()); - assertTrue(asset.getSys().get("space") instanceof CDASpace); - } - - @Test public void testArray() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_fetch_entries_with_includes.json")) - .build(); - - client.registerCustomClass("cat", NyanCat.class); - - CDAArray array = client.fetchEntriesBlocking(); - - File f = new File("array.dat"); - f.deleteOnExit(); - - ResourceUtils.saveResourceToFile(array, f); - array = (CDAArray) ResourceUtils.readResourceFromFile(f); - assertNotNull(array); - - ArrayList items = array.getItems(); - assertEquals(11, items.size()); - - CDAResource res = items.get(2); - assertTrue(res instanceof NyanCat); - NyanCat cat = (NyanCat) res; - assertTrue(cat.getBestFriend().getBestFriend() == cat); - - res = items.get(5); - assertTrue(res instanceof NyanCat); - cat = (NyanCat) res; - assertTrue(cat.getBestFriend().getBestFriend() == cat); - } -} diff --git a/src/test/java/com/contentful/java/SpacesTest.java b/src/test/java/com/contentful/java/SpacesTest.java deleted file mode 100644 index 1a1bc14f..00000000 --- a/src/test/java/com/contentful/java/SpacesTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java; - -import com.contentful.java.api.CDAClient; -import com.contentful.java.lib.Constants; -import com.contentful.java.lib.MockClient; -import com.contentful.java.lib.TestCallback; -import com.contentful.java.lib.TestClientFactory; -import com.contentful.java.model.CDASpace; -import com.contentful.java.model.Locale; -import java.util.ArrayList; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * Tests for fetching Space resources. - */ -public class SpacesTest extends AbsTestCase { - @Test public void testFetchSpace() throws Exception { - TestCallback callback = new TestCallback(); - - TestClientFactory.newInstance() - .setClient(new MockClient("result_test_fetch_space.json")) - .build() - .fetchSpace(callback); - - callback.await(); - - verifyResultNotEmpty(callback); - verifySpace(callback.value); - } - - @Test public void testFetchSpaceBlocking() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_fetch_space.json")) - .build(); - - CDASpace result = client.fetchSpaceBlocking(); - verifySpace(result); - } - - void verifySpace(CDASpace space) { - assertNotNull(space); - assertEquals("Contentful Example API", space.getName()); - assertEquals("Space", space.getSys().get("type")); - assertEquals("cfexampleapi", space.getSys().get("id")); - - ArrayList locales = space.getLocales(); - assertEquals(2, locales.size()); - - // English - Locale locale = locales.get(0); - assertEquals(Constants.DEFAULT_LOCALE, locale.code); - assertEquals("English", locale.name); - assertTrue(locale.isDefault); - - // Klingon - locale = locales.get(1); - assertEquals("tlh", locale.code); - assertEquals("Klingon", locale.name); - assertFalse(locale.isDefault); - } -} diff --git a/src/test/java/com/contentful/java/SynchronizationTest.java b/src/test/java/com/contentful/java/SynchronizationTest.java deleted file mode 100644 index 87780982..00000000 --- a/src/test/java/com/contentful/java/SynchronizationTest.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java; - -import com.contentful.java.api.CDAClient; -import com.contentful.java.lib.MockClient; -import com.contentful.java.lib.TestCallback; -import com.contentful.java.lib.TestClientFactory; -import com.contentful.java.model.CDAAsset; -import com.contentful.java.model.CDAEntry; -import com.contentful.java.model.CDAResource; -import com.contentful.java.model.CDASyncedSpace; -import java.util.ArrayList; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -/** - * Tests for consuming the Sync API. - */ -public class SynchronizationTest extends AbsTestCase { - @SuppressWarnings("UnnecessaryBoxing") - @Test - public void testSynchronization() throws Exception { - TestCallback callback = new TestCallback(); - - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_sync_initial.json")) - .build(); - - // #1 - perform initial synchronization - client.performInitialSynchronization(callback); - callback.await(); - verifyResultNotEmpty(callback); - CDASyncedSpace firstResult = callback.value; - verifySynchronizationFirst(firstResult); - - // #2 - get delta update - callback = new TestCallback(); - - client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_sync_update.json")) - .build(); - - client.performSynchronization(firstResult, callback); - callback.await(); - verifyResultNotEmpty(callback); - CDASyncedSpace secondResult = callback.value; - verifySynchronizationSecond(secondResult); - - // #3 - empty update - callback = new TestCallback(); - - client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_sync_update_empty.json")) - .build(); - - client.performSynchronization(secondResult, callback); - callback.await(); - verifyResultNotEmpty(callback); - CDASyncedSpace thirdResult = callback.value; - verifySynchronizationThird(thirdResult); - } - - @Test public void testSynchronizationBlocking() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_sync_initial.json")) - .build(); - - // #1 - perform initial synchronization - CDASyncedSpace firstResult = client.performInitialSynchronizationBlocking(); - verifySynchronizationFirst(firstResult); - - // #2 - get delta update - client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_sync_update.json")) - .build(); - - CDASyncedSpace secondResult = client.performSynchronizationBlocking(firstResult); - verifySynchronizationSecond(secondResult); - - // #3 - empty update - client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_sync_update_empty.json")) - .build(); - - CDASyncedSpace thirdResult = client.performSynchronizationBlocking(secondResult); - verifySynchronizationThird(thirdResult); - } - - @Test public void testSynchronizationByToken() throws Exception { - CDAClient client = TestClientFactory.newInstance().build(); - - CDASyncedSpace result = client.performInitialSynchronizationBlocking(); - assertNotNull(result); - - String syncToken = result.getSyncToken(); - assertNotNull(syncToken); - - result = client.performSynchronization(syncToken); - assertNotNull(result); - } - - @Test public void testRemoteSynchronization() throws Exception { - CDAClient client = TestClientFactory.newInstance().build(); - - CDASyncedSpace syncedSpace = client.performInitialSynchronizationBlocking(); - client.performSynchronizationBlocking(syncedSpace); - - TestCallback cb; - client.performInitialSynchronization(cb = new TestCallback()); - cb.await(); - assertNull(cb.error); - assertNotNull(cb.value); - - syncedSpace = cb.value; - client.performSynchronization(syncedSpace, cb = new TestCallback()); - cb.await(); - assertNull(cb.error); - assertNotNull(cb.value); - } - - @Test public void testSyncWithLocalizedAsset() throws Exception { - CDAClient client = TestClientFactory.newInstance() - .setClient(new MockClient("result_test_sync_localized_asset.json")) - .build(); - - CDASyncedSpace syncedSpace = client.performInitialSynchronizationBlocking(); - assertNotNull(syncedSpace); - CDAAsset asset = (CDAAsset) syncedSpace.getItems().get(0); - assertEquals("https://whatever.com/abc.gif", asset.getUrl()); - assertEquals("image/gif", asset.getMimeType()); - assertEquals("english", asset.getFields().get("description")); - assertEquals("english", asset.getFields().get("title")); - asset.setLocale("tlh"); - assertEquals("tlh", asset.getFields().get("description")); - assertEquals("tlh", asset.getFields().get("title")); - } - - - @SuppressWarnings("UnnecessaryBoxing") - void verifySynchronizationFirst(CDASyncedSpace result) { - assertNotNull(result); - - ArrayList items = result.getItems(); - assertEquals(3, items.size()); - - CDAEntry entry = (CDAEntry) items.get(0); - assertEquals("Yiltiquoar", entry.getFields().get("name")); - assertEquals(Double.valueOf(9999), entry.getFields().get("age")); - - entry = (CDAEntry) items.get(1); - assertEquals("Tzayclibbon", entry.getFields().get("name")); - assertEquals(Double.valueOf(2405), entry.getFields().get("age")); - - entry = (CDAEntry) items.get(2); - assertEquals("Za'ha'zah", entry.getFields().get("name")); - assertEquals(Double.valueOf(2789), entry.getFields().get("age")); - - assertEquals("FAKE", result.getSyncToken()); - } - - @SuppressWarnings("UnnecessaryBoxing") - void verifySynchronizationSecond(CDASyncedSpace result) { - assertNotNull(result); - - ArrayList items = result.getItems(); - assertEquals(3, items.size()); - - CDAEntry entry = (CDAEntry) items.get(0); - assertEquals("Ooctaiphus", entry.getFields().get("name")); - assertEquals(Double.valueOf(2), entry.getFields().get("age")); - - entry = (CDAEntry) items.get(1); - assertEquals("Yiltiquoar", entry.getFields().get("name")); - assertEquals(Double.valueOf(666666), entry.getFields().get("age")); - - entry = (CDAEntry) items.get(2); - assertEquals("Za'ha'zah", entry.getFields().get("name")); - assertEquals(Double.valueOf(2789), entry.getFields().get("age")); - - assertEquals("FAKE", result.getSyncToken()); - } - - void verifySynchronizationThird(CDASyncedSpace result) { - assertNotNull(result); - - assertEquals(3, result.getItems().size()); - assertEquals("FAKE", result.getSyncToken()); - } -} diff --git a/src/test/java/com/contentful/java/lib/MockClient.java b/src/test/java/com/contentful/java/lib/MockClient.java deleted file mode 100644 index a03725dc..00000000 --- a/src/test/java/com/contentful/java/lib/MockClient.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.lib; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.util.Collections; -import java.util.regex.Pattern; -import org.apache.commons.io.IOUtils; -import retrofit.client.Client; -import retrofit.client.Request; -import retrofit.client.Response; -import retrofit.mime.TypedByteArray; - -/** - * Mock client class that returns a successful response with a response body - * read from a file within resources folder. - */ -public class MockClient implements Client { - private static final Pattern PATTERN_SPACE = Pattern.compile("^/spaces/([a-zA-Z0-9\\-]+)/?$"); - - private final String resourceFileName; - private final String spaceFileName; - - public MockClient(String resourceFileName) { - this(resourceFileName, "space.json"); - } - - public MockClient(String resourceFileName, String spaceFileName) { - this.resourceFileName = resourceFileName; - this.spaceFileName = spaceFileName; - } - - @SuppressWarnings("unchecked") - @Override public Response execute(Request request) throws IOException { - InputStream is = null; - String responseString = ""; - - try { - boolean isSpace = PATTERN_SPACE.matcher(URI.create(request.getUrl()).getPath()).matches(); - String filename; - - if (isSpace) { - filename = spaceFileName; - } else { - filename = resourceFileName; - } - - is = MockClient.class.getResourceAsStream(File.separator + filename); - responseString = IOUtils.toString(is); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException ignore) { - } - } - } - - return new Response(request.getUrl(), 200, "OK", Collections.EMPTY_LIST, - new TypedByteArray("application/json", responseString.getBytes())); - } -} diff --git a/src/test/java/com/contentful/java/lib/NyanCat.java b/src/test/java/com/contentful/java/lib/NyanCat.java deleted file mode 100644 index 9a43aaee..00000000 --- a/src/test/java/com/contentful/java/lib/NyanCat.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.lib; - -import com.contentful.java.model.CDAEntry; -import java.util.List; - -/** - * Sample model class for CDA Entry. - */ -public class NyanCat extends CDAEntry { - public String getName() { - return (String) getFields().get("name"); - } - - @SuppressWarnings("unchecked") public List getLikes() { - return (List) getFields().get("likes"); - } - - public String getColor() { - return (String) getFields().get("color"); - } - - public String getBirthday() { - return (String) getFields().get("birthday"); - } - - public Integer getLives() { - return ((Double) getFields().get("lives")).intValue(); - } - - public NyanCat getBestFriend() { - return (NyanCat) getFields().get("bestFriend"); - } -} diff --git a/src/test/java/com/contentful/java/lib/TestCallback.java b/src/test/java/com/contentful/java/lib/TestCallback.java deleted file mode 100644 index 3b71d7d6..00000000 --- a/src/test/java/com/contentful/java/lib/TestCallback.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.lib; - -import com.contentful.java.api.CDACallback; -import java.util.concurrent.CountDownLatch; -import retrofit.RetrofitError; -import retrofit.client.Response; - -/** - * Callback to be used in unit tests. - */ -public class TestCallback extends CDACallback { - public T value; - public RetrofitError error; - private final CountDownLatch cdl; - - public TestCallback() { - this.cdl = new CountDownLatch(1); - } - - @Override protected void onSuccess(T t, Response response) { - this.value = t; - this.cdl.countDown(); - } - - @Override protected void onFailure(RetrofitError retrofitError) { - this.error = retrofitError; - this.cdl.countDown(); - } - - public void await() throws InterruptedException { - this.cdl.await(); - } -} diff --git a/src/test/java/com/contentful/java/lib/TestClientFactory.java b/src/test/java/com/contentful/java/lib/TestClientFactory.java deleted file mode 100644 index 8127d905..00000000 --- a/src/test/java/com/contentful/java/lib/TestClientFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.lib; - -import com.contentful.java.api.CDAClient; - -/** - * Factory for creating {@link com.contentful.java.api.CDAClient} instances for unit tests. - */ -public class TestClientFactory { - public static CDAClient.Builder newInstance() { - return new CDAClient.Builder().setSpaceKey("cfexampleapi").setAccessToken("b4c0n73n7fu1"); - } -} diff --git a/src/test/java/com/contentful/java/lib/TestException.java b/src/test/java/com/contentful/java/lib/TestException.java deleted file mode 100644 index 38f2786c..00000000 --- a/src/test/java/com/contentful/java/lib/TestException.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2014 Contentful GmbH - * - * 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.contentful.java.lib; - -/** - * Test Exception. - */ -public class TestException extends RuntimeException { -} diff --git a/src/test/kotlin/com/contentful/java/cda/AndroidTests.kt b/src/test/kotlin/com/contentful/java/cda/AndroidTests.kt new file mode 100644 index 00000000..77f2b73d --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/AndroidTests.kt @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import org.robolectric.Robolectric +import android.content.Intent +import kotlin.test.assertEquals +import android.app.Activity +import android.os.Looper +import android.os.Bundle +import retrofit.RestAdapter +import com.contentful.java.cda.model.CDAArray +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.junit.runner.RunWith +import org.junit.Test as test +import retrofit.RetrofitError + +/** + * Android Tests. + */ +[RunWith(javaClass())] +[Config(manifest=Config.NONE)] +class AndroidTests : BaseTest() { + test fun testCallbackExecutesOnMainThread() { + enqueue("space_fetch_response.json") + enqueue("asset_fetch_all_response.json") + + val activity = Robolectric.buildActivity(javaClass()) + .withIntent(Intent().putExtra("EXTRA_URL", getServerUrl())) + .create() + .get() + + while (activity.callbackLooper == null) { + Thread.sleep(1000) + } + + assertEquals(activity.mainThreadLooper, activity.callbackLooper) + } + + class TestActivity : Activity() { + val mainThreadLooper = Looper.getMainLooper() + var callbackLooper: Looper? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val cb = object : CDACallback() { + override fun onSuccess(result: CDAArray?) { + callbackLooper = Looper.myLooper() + } + + override fun onFailure(retrofitError: RetrofitError?) { + super.onFailure(retrofitError) + retrofitError!!.printStackTrace() + } + } + + val androidClient = CDAClient.Builder() + .setSpaceKey("space") + .setAccessToken("token") + .setEndpoint(getIntent().getStringExtra("EXTRA_URL")) + .setLogLevel(RestAdapter.LogLevel.FULL) + .noSSL() + .build() + + androidClient.assets().async().fetchAll(cb) + } + } +} diff --git a/src/test/kotlin/com/contentful/java/cda/AssetTests.kt b/src/test/kotlin/com/contentful/java/cda/AssetTests.kt new file mode 100644 index 00000000..61c272d5 --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/AssetTests.kt @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.contentful.java.cda.model.CDAAsset +import com.contentful.java.cda.lib.TestCallback +import org.junit.Test as test + +/** + * Asset Tests. + */ +class AssetTests : BaseTest() { + test fun testFetchAll() { + enqueue("asset_fetch_all_response.json") + + val result = assertTestCallback( + client!!.assets().async().fetchAll(TestCallback())) + + assertEquals(1, result.getTotal()) + assertEquals(1, result.getItems().size) + + assertTrue(result.getItems()[0] is CDAAsset) + val jake = result.getItems()[0] as CDAAsset + assertEquals("Jake", jake.getFields().get("title")) + assertEquals("image/png", jake.getMimeType()) + + val file = jake.getFields().get("file") as Map<*, *> + assertEquals("jake.png", file.get("fileName")) + assertEquals("image/png", file.get("contentType")) + + val details = file.get("details") as Map<*, *> + assertEquals(20480.toDouble(), details.get("size")) + + val image = details.get("image") as Map<*, *> + assertEquals(100.toDouble(), image.get("width")) + assertEquals(161.toDouble(), image.get("height")) + assertEquals("//images.contentful.com/cfexampleapi/a/b/jake.png", file.get("url")) + assertEquals( + "${client!!.getHttpScheme()}://images.contentful.com/cfexampleapi/a/b/jake.png", + jake.getUrl()) + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("GET", recordedRequest.getMethod()) + assertEquals("/spaces/spaceid/assets", recordedRequest.getPath()) + } + + test fun testFetchAllWithQuery() { + enqueue("asset_fetch_all_response.json") + + assertTestCallback(client!!.assets().async().fetchAll(linkedMapOf( + Pair("sys.id[ne]", "whatever"), + Pair("content_type", "cat")), + TestCallback())) + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("GET", recordedRequest.getMethod()) + assertEquals("/spaces/spaceid/assets?sys.id[ne]=whatever&content_type=cat", + recordedRequest.getPath()) + } + + test fun testFetchOne() { + enqueue("asset_fetch_one_response.json") + + val result = assertTestCallback( + client!!.assets().async().fetchOne( + "nyancat", TestCallback())) as CDAAsset + + val fields = result.getFields() + + assertEquals("Nyan Cat", fields.get("title")) + + val file = fields.get("file") as Map<*, *> + assertEquals("Nyan_cat_250px_frame.png", file.get("fileName")) + assertEquals("image/png", file.get("contentType")) + + val details = file.get("details") as Map<*, *> + assertEquals(12273.toDouble(), details.get("size")) + + val image = details.get("image") as Map<*, *> + assertEquals(1.toDouble(), image.get("width")) + assertEquals(2.toDouble(), image.get("height")) + assertEquals("//images.contentful.com/cfexampleapi/a/b/Nyan_cat_250px_frame.png", + file.get("url")) + + val scheme = client!!.getHttpScheme() + assertEquals("${scheme}://images.contentful.com/cfexampleapi/a/b/Nyan_cat_250px_frame.png", + result.getUrl()) + + assertEquals("image/png", result.getMimeType()) + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("GET", recordedRequest.getMethod()) + assertEquals("/spaces/spaceid/assets/nyancat", recordedRequest.getPath()) + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/contentful/java/cda/BaseTest.kt b/src/test/kotlin/com/contentful/java/cda/BaseTest.kt new file mode 100644 index 00000000..3ad7e193 --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/BaseTest.kt @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import com.squareup.okhttp.mockwebserver.MockWebServer +import retrofit.RestAdapter +import org.junit.Before as before +import org.junit.After as after +import kotlin.test.assertNull +import kotlin.test.assertNotNull +import com.contentful.java.cda.lib.TestCallback +import com.squareup.okhttp.mockwebserver.MockResponse +import com.contentful.java.cda.lib.TestUtils + +/** + * BaseTest. + */ +open class BaseTest { + var server: MockWebServer? = null + var client: CDAClient? = null + + before fun setUp() { + // MockWebServer + server = MockWebServer() + server!!.play() + + // Client + client = CDAClient.Builder() + .setAccessToken("token") + .setSpaceKey("spaceid") + .setEndpoint(getServerUrl()) + .setLogLevel(RestAdapter.LogLevel.FULL) + .noSSL() + .build() + + enqueue("space_fetch_response.json") + client!!.assets().ensureSpace(true) + server!!.takeRequest() + } + + after fun tearDown() { + server!!.shutdown() + } + + fun assertTestCallback(cb: CDACallback): T { + if (cb !is TestCallback) { + throw IllegalArgumentException("callback should be an instance of TestCallback.") + } + cb.await() + assertNull(cb.error) + if (cb.allowEmpty) { + return null + } + assertNotNull(cb.value) + return cb.value!! + } + + fun enqueue(fileName: String) { + server!!.enqueue(MockResponse() + .setResponseCode(200) + .setBody(TestUtils.fileToString(fileName))) + } + + fun getServerUrl(): String { + val url = server!!.getUrl("/") + return url.toString().substring(url.getProtocol().length + 3) + } +} diff --git a/src/test/kotlin/com/contentful/java/cda/ClientTests.kt b/src/test/kotlin/com/contentful/java/cda/ClientTests.kt new file mode 100644 index 00000000..dc45839d --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/ClientTests.kt @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import kotlin.test.assertEquals +import com.contentful.java.cda.lib.TestCallback +import retrofit.RetrofitError +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import com.squareup.okhttp.mockwebserver.MockResponse +import kotlin.test.assertFalse +import java.io.IOException +import kotlin.test.assertNotNull +import kotlin.test.assertTrue +import rx.Observable +import org.junit.Test as test +import com.contentful.java.cda.model.CDASpace +import org.mockito.Mockito + +/** + * Client Tests. + */ +class ClientTests : BaseTest() { + test fun testCancelledCallback() { + enqueue("space_fetch_response.json") + + val cdl = CountDownLatch(1) + var called = false + + val cb = object : CDACallback() { + override fun onSuccess(result: CDASpace?) { + called = true + cdl.countDown() + } + + override fun onFailure(retrofitError: RetrofitError?) { + called = true + cdl.countDown() + } + } + + cb.cancel() + client!!.spaces().async().fetch(cb) + cdl.await(3, TimeUnit.SECONDS) + + assertFalse(called) + } + + test fun testCallbackRetrofitError() { + val badClient = CDAClient.Builder() + .setSpaceKey("space") + .setAccessToken("token") + .setCallbackExecutor { it.run() } + .setClient { cli -> + throw RetrofitError.unexpectedError(cli.getUrl(), IOException()) } + .build() + + val cb = TestCallback() + badClient.spaces().async().fetch(cb) + cb.await() + assertNotNull(cb.error) + } + + test fun testCallbackGeneralError() { + var error: Throwable? = null + + val cb = object : CDACallback() { + override fun onSuccess(result: CDASpace?) { + } + + override fun onFailure(retrofitError: RetrofitError?) { + super.onFailure(retrofitError) + error = retrofitError + } + } + + Observable.defer { + Observable.just(CDASpace(null, null, null)) + }.doOnEach { + throw RuntimeException() + }.subscribe( + RxExtensions.ActionSuccess(client!!.callbackExecutor, cb), + RxExtensions.ActionError(client!!.callbackExecutor, cb)) + + assertTrue(error is RetrofitError) + } + + test fun testPreview() { + val cli = CDAClient.Builder() + .setSpaceKey("cfexampleapi") + .setAccessToken("e5e8d4c5c122cf28fc1af3ff77d28bef78a3952957f15067bbc29f2f0dde0b50") + .preview() + .build() + + cli.spaces().fetch() + } + + test fun testAccessToken() { + server!!.enqueue(MockResponse().setResponseCode(200)) + client!!.spaces().fetch() + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("Bearer token", recordedRequest.getHeader("Authorization")) + } + + test fun testUserAgent() { + server!!.enqueue(MockResponse().setResponseCode(200)) + client!!.spaces().fetch() + + val prefix = "contentful.java/" + val versionName = PropertiesReader().getField(Constants.PROP_VERSION_NAME) + + // Request + val recordedRequest = server!!.takeRequest() + + assertEquals("${prefix}${versionName}", recordedRequest.getHeader("User-Agent")) + } + + test(expected = javaClass()) + fun testUserAgentThrowsRuntimeExceptionOnFailure() { + try { + val reader = Mockito.mock(javaClass()) + + Mockito.`when`(reader.getField(Constants.PROP_VERSION_NAME)) + .thenThrow(javaClass()) + + CDAClient.sUserAgent = null + client!!.createUserAgent(reader) + } catch(e: RuntimeException) { + assertEquals("Unable to retrieve version name.", e.getMessage()) + throw e + } + } + + test(expected = javaClass()) + fun failsNoAccessToken() { + try { + CDAClient.Builder().build() + } catch (e: IllegalArgumentException) { + assertEquals("Access token must be defined.", e.getMessage()) + throw e + } + } + + test(expected = javaClass()) + fun failsNoSpace() { + try { + CDAClient.Builder().setAccessToken("token").build() + } catch (e: IllegalArgumentException) { + assertEquals("Space ID must be defined.", e.getMessage()) + throw e + } + } + + test(expected = javaClass()) + fun failsSetNullAccessToken() { + try { + CDAClient.Builder().setAccessToken(null) + } catch (e: IllegalArgumentException) { + assertEquals("Cannot call setAccessToken() with null.", e.getMessage()) + throw e + } + } + + test(expected = javaClass()) + fun failsSetSpaceKey() { + try { + CDAClient.Builder().setSpaceKey(null) + } catch (e: IllegalArgumentException) { + assertEquals("Cannot call setSpaceKey() with null.", e.getMessage()) + throw e + } + } + + test(expected = javaClass()) + fun failsSetNullCallbackExecutor() { + try { + CDAClient.Builder().setCallbackExecutor(null) + } catch (e: IllegalArgumentException) { + assertEquals("Cannot call setCallbackExecutor() with null.", e.getMessage()) + throw e + } + } + + test(expected = javaClass()) + fun failsSetNullCustomClasses() { + try { + CDAClient.Builder().setCustomClasses(null) + } catch (e: IllegalArgumentException) { + assertEquals("Cannot call setCustomClasses() with null.", e.getMessage()) + throw e + } + } + + test(expected = javaClass()) + fun failsSetNullClient() { + try { + CDAClient.Builder().setClient(null) + } catch (e: IllegalArgumentException) { + assertEquals("Cannot call setClient() with null.", e.getMessage()) + throw e + } + } + + test(expected = javaClass()) + fun failsSetNullLogLevel() { + try { + CDAClient.Builder().setLogLevel(null) + } catch (e: IllegalArgumentException) { + assertEquals("Cannot call setLogLevel() with null.", e.getMessage()) + throw e + } + } + + test(expected = javaClass()) + fun failsSetNullClientProvider() { + try { + CDAClient.Builder().setClientProvider(null) + } catch (e: IllegalArgumentException) { + assertEquals("Cannot call setClientProvider() with null.", e.getMessage()) + throw e + } + } + + test(expected = javaClass()) + fun failsSetNullEndPoint() { + try { + CDAClient.Builder().setEndpoint(null) + } catch (e: IllegalArgumentException) { + assertEquals("Cannot call setEndpoint() with null.", e.getMessage()) + throw e + } + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/contentful/java/cda/ContentTypeTests.kt b/src/test/kotlin/com/contentful/java/cda/ContentTypeTests.kt new file mode 100644 index 00000000..7331853e --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/ContentTypeTests.kt @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import com.contentful.java.cda.lib.TestCallback +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.contentful.java.cda.model.CDAContentType +import org.junit.Test as test +import com.contentful.java.cda.Constants.CDAFieldType + +/** + * Content Type Tests. + */ +class ContentTypeTests : BaseTest() { + test fun testFetchAll() { + enqueue("content_type_fetch_all_response.json") + + val result = assertTestCallback( + client!!.contentTypes().async().fetchAll(TestCallback())) + + assertEquals(1, result.getTotal()) + assertEquals(1, result.getItems().size) + + assertTrue(result.getItems()[0] is CDAContentType) + val city = result.getItems()[0] as CDAContentType + + assertEquals("City", city.getName()) + assertEquals("name", city.getDisplayField()) + + // Fields + val fields = city.getFields() + assertEquals(2, fields.size) + + // Field: Name + assertEquals("Name", fields[0].get("name")) + assertEquals("name", fields[0].get("id")) + assertEquals("Text", fields[0].get("type")) + assertEquals(true, fields[0].get("required")) + + // Field: Center + assertEquals("Center", fields[1].get("name")) + assertEquals("center", fields[1].get("id")) + assertEquals("Location", fields[1].get("type")) + assertEquals(true, fields[1].get("required")) + + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("GET", recordedRequest.getMethod()) + assertEquals("/spaces/spaceid/content_types", recordedRequest.getPath()) + } + + test fun testFetchAllWithQuery() { + enqueue("content_type_fetch_all_response.json") + + assertTestCallback(client!!.contentTypes().async().fetchAll(linkedMapOf( + Pair("sys.id[ne]", "whatever"), + Pair("content_type", "city")), TestCallback())) + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("GET", recordedRequest.getMethod()) + assertEquals("/spaces/spaceid/content_types?sys.id[ne]=whatever&content_type=city", + recordedRequest.getPath()) + } + + test fun testFetchOne() { + enqueue("content_type_fetch_one_response.json") + + val result = assertTestCallback(client!!.contentTypes().async().fetchOne( + "ct", TestCallback())) as CDAContentType + + assertEquals("ctname", result.getName()) + assertEquals("ctdesc", result.getUserDescription()) + assertEquals("t", result.getDisplayField()) + + // Fields + val fields = result.getFields() + assertEquals(10, fields.size) + + val fieldTypes = listOf( + CDAFieldType.Text, + CDAFieldType.Symbol, + CDAFieldType.Integer, + CDAFieldType.Number, + CDAFieldType.Boolean, + CDAFieldType.Date, + CDAFieldType.Location, + CDAFieldType.Link, + CDAFieldType.Object, + CDAFieldType.Array) + + fieldTypes.withIndices().forEach { + val field = fields[it.first] + assertEquals("id${it.first}", field["id"]) + assertEquals("name${it.first}", field["name"]) + it.second.assertFrom(field["type"]!!) + } + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("GET", recordedRequest.getMethod()) + assertEquals("/spaces/spaceid/content_types/ct", recordedRequest.getPath()) + } + + fun Constants.CDAFieldType.assertFrom(obj: Any) { + assertTrue(equals(Constants.CDAFieldType.valueOf(obj.toString()))) + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/contentful/java/cda/EntryTests.kt b/src/test/kotlin/com/contentful/java/cda/EntryTests.kt new file mode 100644 index 00000000..e711e5aa --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/EntryTests.kt @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import com.contentful.java.cda.lib.TestCallback +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.junit.Test as test +import com.contentful.java.cda.model.CDAEntry +import com.contentful.java.cda.model.CDAAsset +import com.contentful.java.cda.model.CDAArray +import kotlin.test.assertNotNull + +/** + * Entry Tests. + */ +class EntryTests : BaseTest() { + test fun testCustomClass() { + val cli = CDAClient.Builder() + .setAccessToken("token") + .setSpaceKey("space") + .setEndpoint(getServerUrl()) + .noSSL() + .setCustomClasses(hashMapOf( + Pair("dog", javaClass()))) + .build() + + enqueue("space_fetch_response.json") + enqueue("entry_fetch_one_response.json") + + val entry = cli.entries().fetchOne("dog") + assertTrue(entry is Dog) + val result = entry as Dog + assertEquals("Doge", result.name) + assertNotNull(result.image) + assertEquals("Asset", (result.image!!["sys"] as Map<*, *>)["linkType"]) + } + + test fun testFetchAll() { + enqueue("entry_fetch_all_response.json") + + val result = assertTestCallback( + client!!.entries().async().fetchAll(TestCallback())) + + verifyFetchAll(result, client!!) + + val path = "/spaces/spaceid/entries" + assertEquals("${server!!.getUrl(path)}", result.getOriginalUrl()) + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("GET", recordedRequest.getMethod()) + assertEquals(path, recordedRequest.getPath()) + } + + test fun testFetchAllWithQuery() { + enqueue("entry_fetch_all_response.json") + + assertTestCallback(client!!.entries().async().fetchAll(linkedMapOf( + Pair("sys.id[ne]", "whatever"), + Pair("content_type", "cat")), + TestCallback())) + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("GET", recordedRequest.getMethod()) + assertEquals("/spaces/spaceid/entries?sys.id[ne]=whatever&content_type=cat", + recordedRequest.getPath()) + } + + test fun testFetchOne() { + enqueue("entry_fetch_one_response.json") + + val result = assertTestCallback( + client!!.entries().async().fetchOne( + "jake", TestCallback())) as CDAEntry + + assertEquals("en-US", result.getLocale()) + + val fields = result.getFields() + assertEquals("Doge", fields.get("name")) + assertEquals("such json\nwow", fields.get("description")) + + // image + assertTrue(fields.get("image") is Map<*, *>) + val imageSys = (fields.get("image") as Map<*, *>).get("sys") as Map<*, *> + assertEquals("Link", imageSys.get("type")) + assertEquals("Asset", imageSys.get("linkType")) + assertEquals("1x0xpXu4pSGS4OukSyWGUK", imageSys.get("id")) + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("GET", recordedRequest.getMethod()) + assertEquals("/spaces/spaceid/entries/jake", recordedRequest.getPath()) + } + + class object { + fun verifyFetchAll(result: CDAArray, client: CDAClient) { + assertEquals(2, result.getTotal()) + assertEquals(0, result.getSkip()) + assertEquals(100, result.getLimit()) + assertEquals(2, result.getItems().size) + + assertTrue(result.getItems()[0] is CDAEntry) + val jake = result.getItems()[0] as CDAEntry + val fields = jake.getFields() + assertEquals("Jake", fields.get("name")) + assertEquals("Bacon pancakes, makin' bacon pancakes!", fields.get("description")) + + // Asset Link + assertTrue(fields.get("image") is CDAAsset) + val image = fields.get("image") as CDAAsset + assertEquals( + "${client.getHttpScheme()}://images.contentful.com/cfexampleapi/a/b/jake.png", + image.getUrl()) + assertEquals("image/png", image.getMimeType()) + assertEquals("Jake", image.getFields().get("title")) + assertEquals(4, (image.getFields().get("file") as Map<*, *>).size) + + // Entry Link + assertTrue(fields.get("entry") is CDAEntry) + val entry = fields.get("entry") as CDAEntry + assertEquals("Doge", entry.getFields()["name"]) + assertEquals("such json\nwow", entry.getFields()["description"]) + } + } + + class Dog() : CDAEntry() { + var name: String? = null + get() = getField("name") + + var image: Map<*, *>? = null + get() = getField("image") + + [suppress("UNCHECKED_CAST")] + private fun getField(name: String) = getFields()?.let { it[name] as T } + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/contentful/java/cda/GeneralTests.kt b/src/test/kotlin/com/contentful/java/cda/GeneralTests.kt new file mode 100644 index 00000000..9627a7d6 --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/GeneralTests.kt @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import org.junit.Test as test +import com.contentful.java.cda.model.ArrayResource +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertTrue +import java.lang.reflect.InvocationTargetException +import java.io.UnsupportedEncodingException +import kotlin.test.assertNull +import org.mockito.Mockito +import java.io.Closeable +import java.io.IOException +import kotlin.test.assertFalse + +/** + * General Tests. + */ +class GeneralTests : BaseTest() { + test(expected = javaClass()) + fun testAssertNotNull() { + val param = "param" + + try { + Utils.assertNotNull(null, param) + } catch(e: IllegalArgumentException) { + assertEquals("${param} may not be null.", e.getMessage()) + throw e + } + } + test(expected = javaClass()) + fun testQueryParamThrowsRuntimeException() { + val message = "message" + + try { + Utils.getQueryParamFromUrl("http://a.com/b?c=d", "c", { + throw UnsupportedEncodingException(message) + }) + } catch (e: RuntimeException) { + assertTrue(e.getCause() is UnsupportedEncodingException) + assertEquals("java.io.UnsupportedEncodingException: ${message}", e.getMessage()) + throw e + } + } + + test fun testQueryParam() { + assertNull(Utils.getQueryParamFromUrl("http://a.com/b?c=d=e=f", "c")) + assertNull(Utils.getQueryParamFromUrl("http://a.com/b?", "c")) + assertNull(Utils.getQueryParamFromUrl("http://a.com/b", "c")) + } + + test(expected = javaClass()) + fun testArrayParserThrowsOnInvalidInput() { + class InvalidInput : ArrayResource() { } + + try { + ArrayParser(InvalidInput(), null).call() + } catch(e: IllegalArgumentException) { + assertEquals("Invalid input.", e.getMessage()) + throw e + } + } + + test fun testConstantsThrowsUnsupportedException() { + assertPrivateConstructor(javaClass()) + } + + test fun testRxExtensionsThrowsUnsupportedException() { + assertPrivateConstructor(javaClass()) + } + + test fun testUtilsThrowsUnsupportedException() { + assertPrivateConstructor(javaClass()) + } + + test fun testResourceUtilsThrowsUnsupportedException() { + assertPrivateConstructor(javaClass()) + } + + test fun testCloseStream() { + val closable = Mockito.mock(javaClass()) + Mockito.`when`(closable.close()).thenThrow(javaClass()) + assertFalse(ResourceUtils.closeStream(closable)) + } + + fun assertPrivateConstructor(clazz: Class) { + var ctor = clazz.getDeclaredConstructor() + ctor.setAccessible(true) + var exception = try { + ctor.newInstance() + } catch(e: Exception) { + e + } + + assertNotNull(exception) + assertTrue(exception is InvocationTargetException) + assertTrue((exception as InvocationTargetException).getCause() is + UnsupportedOperationException) + } +} diff --git a/src/test/kotlin/com/contentful/java/cda/ModuleTests.kt b/src/test/kotlin/com/contentful/java/cda/ModuleTests.kt new file mode 100644 index 00000000..450e8c0e --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/ModuleTests.kt @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import org.junit.Test as test +import retrofit.RetrofitError +import com.contentful.java.cda.model.CDASyncedSpace +import kotlin.test.assertTrue +import kotlin.test.assertEquals +import com.contentful.java.cda.model.CDAResource +import java.io.InputStreamReader + +/** + * Module Tests. + */ +class ModuleTests : BaseTest() { + test fun testSyncThrowsRetrofitErrorOnFailure() { + val module = object : ModuleSync(client!!.synchronization().context) { + override fun prepare(originalSpace: CDASyncedSpace?, updatedSpace: CDASyncedSpace?, + iterate: Boolean): CDASyncedSpace? { + throw UnsupportedOperationException() + } + } + + val methods = setOf( + Runnable { module.performInitial() }, + Runnable { module.performWithToken("token") }, + Runnable { + val syncedSpace = CDASyncedSpace() + syncedSpace.setSyncToken("token") + module.performWithSpace(syncedSpace) + }) + + var count = 0 + + methods.forEach { + enqueue("space_fetch_response.json") + enqueue("sync_initial_response.json") + + try { + it.run() + } catch (e: RetrofitError) { + assertTrue(e.getCause() is UnsupportedOperationException) + count++ + } + } + + assertEquals(3, count) + } + + test fun testBaseThrowsRetrofitErrorOnFailure() { + val module = object : BaseModule(client!!.synchronization().context) { + override fun getResourcePath(): String? = "" + override fun createCdaResource(inputStreamReader: InputStreamReader?): CDAResource? = CDAResource() + override fun async(): BaseModule.ExtAsync? = extAsync + override fun rx(): BaseModule.ExtRxJava? = extRxJava + + override fun prepare(resource: R): R { + throw UnsupportedOperationException() + } + } + + val methods = setOf( + Runnable { + enqueue("entry_fetch_all_response.json") + module.fetchAll() + }, + Runnable { + enqueue("entry_fetch_one_response.json") + module.fetchOne("") + }) + + var count = 0 + + methods.forEach { + try { + it.run() + } catch (e: RetrofitError) { + assertTrue(e.getCause() is UnsupportedOperationException) + count++ + } + } + + assertEquals(2, count) + } +} diff --git a/src/test/kotlin/com/contentful/java/cda/SerializationTests.kt b/src/test/kotlin/com/contentful/java/cda/SerializationTests.kt new file mode 100644 index 00000000..548fb819 --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/SerializationTests.kt @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import org.junit.Test as test +import java.io.File +import com.contentful.java.cda.model.CDAArray +import com.contentful.java.cda.model.CDAEntry +import com.contentful.java.cda.lib.TestUtils +import com.contentful.java.cda.model.CDAResource +import com.google.gson.JsonParseException +import kotlin.test.assertTrue + +/** + * Serialization Tests. + */ +class SerializationTests : BaseTest() { + test fun testSerialization() { + enqueue("entry_fetch_all_response.json") + val original = client!!.entries().fetchAll() + val file = File("asset.dat"); + file.createNewFile() + file.deleteOnExit() + + ResourceUtils.saveResourceToFile(original, file) + val result = ResourceUtils.readResourceFromFile(file) as CDAArray + + setOf(original, result).forEach { EntryTests.verifyFetchAll(it, client!!) } + } + + test(expected = javaClass()) + fun testTypeAdapterInstantiationException() { + val cli = CDAClient.Builder() + .setSpaceKey("space") + .setAccessToken("token") + .setCustomClasses(hashMapOf( + Pair("dog", javaClass()) + )).build() + + + try { + cli!!.gson.fromJson(TestUtils.fileToString("entry_fetch_one_response.json"), + javaClass()) + } catch(e: JsonParseException) { + assertTrue(e.getCause() is InstantiationException) + throw e + } + } + + test(expected = javaClass()) + fun testTypeAdapterIllegalAccessException() { + val cli = CDAClient.Builder() + .setSpaceKey("space") + .setAccessToken("token") + .setCustomClasses(hashMapOf( + Pair("dog", javaClass()) + )).build() + + + try { + cli!!.gson.fromJson(TestUtils.fileToString("entry_fetch_one_response.json"), + javaClass()) + } catch(e: JsonParseException) { + assertTrue(e.getCause() is IllegalAccessException) + throw e + } + } + + class BadClass1(val whatever: String) : CDAResource() + class BadClass2() : CDAEntry() { + { + throw IllegalAccessException() + } + } +} diff --git a/src/test/kotlin/com/contentful/java/cda/SpaceTests.kt b/src/test/kotlin/com/contentful/java/cda/SpaceTests.kt new file mode 100644 index 00000000..d700d098 --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/SpaceTests.kt @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import com.contentful.java.cda.lib.TestCallback +import kotlin.test.assertEquals +import org.junit.Test as test +import kotlin.test.assertTrue +import kotlin.test.assertFalse + +/** + * Space Tests. + */ +class SpaceTests : BaseTest() { + test fun testFetch() { + enqueue("space_fetch_response.json") + + val result = assertTestCallback( + client!!.spaces().async().fetch(TestCallback())) + + assertEquals(result, client!!.getSpace()) + + assertEquals("Contentful Example API", result.getName()) + assertEquals("Space", result.getSys()["type"]) + assertEquals("cfexampleapi", result.getSys()["id"]) + assertEquals("en-US", result.getDefaultLocale()) + + val locales = result.getLocales() + assertEquals(2, locales.size) + assertEquals("en-US", locales[0].getCode()) + assertEquals("English", locales[0].getName()) + assertTrue(locales[0].isDefault()) + + assertEquals("tlh", locales[1].getCode()) + assertEquals("Klingon", locales[1].getName()) + assertFalse(locales[1].isDefault()) + + // Request + val recordedRequest = server!!.takeRequest() + assertEquals("GET", recordedRequest.getMethod()) + assertEquals("/spaces/spaceid", recordedRequest.getPath()) + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/contentful/java/cda/SyncTests.kt b/src/test/kotlin/com/contentful/java/cda/SyncTests.kt new file mode 100644 index 00000000..842d3b46 --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/SyncTests.kt @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda + +import org.junit.Test as test +import com.contentful.java.cda.lib.TestCallback +import com.contentful.java.cda.model.CDASyncedSpace +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import com.contentful.java.cda.model.CDAEntry +import com.squareup.okhttp.mockwebserver.RecordedRequest +import com.squareup.okhttp.mockwebserver.MockResponse +import com.contentful.java.cda.model.CDAAsset + +/** + * Sync Tests. + */ +class SyncTests : BaseTest() { + test fun testWithSyncToken() { + enqueue("space_fetch_response.json") + enqueue("sync_initial_response.json") + + assertTestCallback(client!!.synchronization().async().performWithToken( + "token", TestCallback())) + + // Request + server!!.takeRequest() + val request = server!!.takeRequest() + assertEquals("GET", request.getMethod()) + assertEquals("/spaces/spaceid/sync?sync_token=token", request.getPath()) + } + + test fun testRemoteSynchronization() { + val cli = CDAClient.Builder() + .setAccessToken("9caa9b36fbb4250508b8e3322861dbddd7527bc02ba28f44b926c5d99f22d2ab") + .setSpaceKey("hvjkfbzcwrfn") + .build() + + val result = assertTestCallback(cli.synchronization().async().performInitial( + TestCallback())) + + assertTestCallback(cli.synchronization().async().performWithSpace(result, TestCallback())) + } + + test fun testSynchronization() { + // Initial + enqueue("space_fetch_response.json") + enqueue("sync_initial_response.json") + val first = assertTestCallback( + client!!.synchronization().async().performInitial(TestCallback())) + + server!!.takeRequest() + verifySyncFirst(first, server!!.takeRequest()) + + // Update + enqueue("space_fetch_response.json") + enqueue("sync_update_response.json") + val second = assertTestCallback(client!!.synchronization().async().performWithSpace( + first, TestCallback())) + + server!!.takeRequest() + verifySyncSecond(second, server!!.takeRequest()) + } + + fun verifySyncFirst(result: CDASyncedSpace, request: RecordedRequest) { + val items = result.getItems() + assertEquals(4, items.size) + + assertTrue(items[0] is CDAEntry) + assertTrue(items[1] is CDAEntry) + assertTrue(items[2] is CDAEntry) + assertTrue(items[3] is CDAAsset) + + val yiltiquoar = items[0] as CDAEntry + assertEquals("Yiltiquoar", yiltiquoar.getFields()["name"]) + assertEquals(9999.toDouble(), yiltiquoar.getFields()["age"]) + + val tzayclibbon = items[1] as CDAEntry + assertEquals("Tzayclibbon", tzayclibbon.getFields()["name"]) + assertEquals(2405.toDouble(), tzayclibbon.getFields()["age"]) + + val zahazah = items[2] as CDAEntry + assertEquals("Za'ha'zah", zahazah.getFields()["name"]) + assertEquals(2789.toDouble(), zahazah.getFields()["age"]) + + val asset = items[3] as CDAAsset + assertEquals("ab", asset.getFields()["title"]) + assertEquals("image/jpeg", asset.getMimeType()) + assertEquals("${client!!.getHttpScheme()}://images.contentful.com/a/b/c/d.jpg", + asset.getUrl()) + + // Request + assertEquals("GET", request.getMethod()) + assertEquals("/spaces/spaceid/sync?initial=true", request.getPath()) + } + + fun verifySyncSecond(result: CDASyncedSpace, request: RecordedRequest) { + val items = result.getItems() + assertEquals(3, items.size) + + assertTrue(items[0] is CDAEntry) + assertTrue(items[1] is CDAEntry) + assertTrue(items[2] is CDAEntry) + + val ooctaiphus = items[0] as CDAEntry + assertEquals("Ooctaiphus", ooctaiphus.getFields()["name"]) + assertEquals(2.toDouble(), ooctaiphus.getFields()["age"]) + + val yiltiquoar = items[1] as CDAEntry + assertEquals("Yiltiquoar", yiltiquoar.getFields()["name"]) + assertEquals(666666.toDouble(), yiltiquoar.getFields()["age"]) + + val zahazah = items[2] as CDAEntry + assertEquals("Za'ha'zah", zahazah.getFields()["name"]) + assertEquals(2789.toDouble(), zahazah.getFields()["age"]) + + assertEquals("FAKE", result.getSyncToken()) + + // Request + assertEquals("GET", request.getMethod()) + assertEquals("/spaces/spaceid/sync?sync_token=FAKE", request.getPath()) + } + + test(expected = javaClass()) + fun failsPerformWithInvalidSpace() { + server!!.enqueue(MockResponse().setResponseCode(200)) + + try { + client!!.synchronization().performWithSpace(CDASyncedSpace()) + } catch(e: IllegalArgumentException) { + assertEquals("performWithSpace() called for a space with no sync token.", + e.getMessage()) + throw e + } + } +} diff --git a/src/test/kotlin/com/contentful/java/cda/lib/TestCallback.kt b/src/test/kotlin/com/contentful/java/cda/lib/TestCallback.kt new file mode 100644 index 00000000..f1b79146 --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/lib/TestCallback.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2014 Contentful GmbH + * + * 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.contentful.java.cda.lib + +import java.util.concurrent.CountDownLatch +import retrofit.RetrofitError +import com.contentful.java.cda.CDACallback + +/** + * TestCallback. + */ +class TestCallback(val allowEmpty: Boolean = false) : CDACallback() { + val cdl: CountDownLatch + var value: T = null + var error: RetrofitError? = null + + { + cdl = CountDownLatch(1) + } + + override fun onSuccess(result: T) { + value = result + cdl.countDown() + } + + override fun onFailure(retrofitError: RetrofitError?) { + super.onFailure(retrofitError) + error = retrofitError + cdl.countDown() + } + + throws(javaClass()) + public fun await() { + cdl.await() + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/contentful/java/cda/lib/TestUtils.kt b/src/test/kotlin/com/contentful/java/cda/lib/TestUtils.kt new file mode 100644 index 00000000..6caaf236 --- /dev/null +++ b/src/test/kotlin/com/contentful/java/cda/lib/TestUtils.kt @@ -0,0 +1,18 @@ +package com.contentful.java.cda.lib + +import org.apache.commons.io.FileUtils +import java.io.File +import com.squareup.okhttp.mockwebserver.RecordedRequest +import org.apache.commons.io.IOUtils + +/** + * Utils. + */ +class TestUtils { + class object { + fun fileToString(fileName: String): String = + FileUtils.readFileToString(File("src/test/resources/${fileName}"), "UTF-8") + } +} + +fun RecordedRequest.getBodyAsString() = IOUtils.toString(getBody(), "UTF-8") \ No newline at end of file diff --git a/src/test/resources/result_fetch_assets_matching.json b/src/test/resources/asset_fetch_all_response.json similarity index 86% rename from src/test/resources/result_fetch_assets_matching.json rename to src/test/resources/asset_fetch_all_response.json index 42b7d84e..fd5326d7 100644 --- a/src/test/resources/result_fetch_assets_matching.json +++ b/src/test/resources/asset_fetch_all_response.json @@ -19,7 +19,7 @@ }, "size": 20480 }, - "url": "//images.contentful.com/cfexampleapi/4hlteQAXS8iS0YCMU6QMWg/2a4d826144f014109364ccf5c891d2dd/jake.png" + "url": "//images.contentful.com/cfexampleapi/a/b/jake.png" } }, "sys": { diff --git a/src/test/resources/result_fetch_asset_with_identifier.json b/src/test/resources/asset_fetch_one_response.json similarity index 67% rename from src/test/resources/result_fetch_asset_with_identifier.json rename to src/test/resources/asset_fetch_one_response.json index 9eb7cfcf..5329e434 100644 --- a/src/test/resources/result_fetch_asset_with_identifier.json +++ b/src/test/resources/asset_fetch_one_response.json @@ -1,17 +1,17 @@ { "fields": { - "title": "fake", + "title": "Nyan Cat", "file": { - "fileName": "fake.png", + "fileName": "Nyan_cat_250px_frame.png", "contentType": "image/png", "details": { "image": { - "width": 250, - "height": 250 + "width": 1, + "height": 2 }, "size": 12273 }, - "url": "//images.contentful.com/fake.png" + "url": "//images.contentful.com/cfexampleapi/a/b/Nyan_cat_250px_frame.png" } }, "sys": { @@ -23,7 +23,7 @@ } }, "type": "Asset", - "id": "fake", + "id": "nyancat", "revision": 1, "createdAt": "2013-09-02T14:56:34.240Z", "updatedAt": "2013-09-02T14:56:34.240Z", diff --git a/src/test/resources/result_test_fetch_content_types.json b/src/test/resources/content_type_fetch_all_response.json similarity index 54% rename from src/test/resources/result_test_fetch_content_types.json rename to src/test/resources/content_type_fetch_all_response.json index 7e8ce79e..e3159772 100644 --- a/src/test/resources/result_test_fetch_content_types.json +++ b/src/test/resources/content_type_fetch_all_response.json @@ -2,7 +2,7 @@ "sys": { "type": "Array" }, - "total": 2, + "total": 1, "skip": 0, "limit": 100, "items": [ @@ -37,34 +37,6 @@ "updatedAt": "2014-02-21T13:42:33.009Z" }, "displayField": "name" - }, - { - "fields": [ - { - "id": "name", - "name": "Name", - "type": "Text", - "required": true, - "localized": false - } - ], - "name": "Cat", - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "ContentType", - "id": "63k4qdEi9aI8IQUGaYGg4O", - "revision": 1, - "createdAt": "2013-06-23T19:06:29.976Z", - "updatedAt": "2013-06-23T19:06:29.976Z" - }, - "description": "Meow!", - "displayField": "name" } ] } diff --git a/src/test/resources/content_type_fetch_one_response.json b/src/test/resources/content_type_fetch_one_response.json new file mode 100644 index 00000000..7ae1a9d6 --- /dev/null +++ b/src/test/resources/content_type_fetch_one_response.json @@ -0,0 +1,76 @@ +{ + "fields": [ + { + "name": "name0", + "id": "id0", + "type": "Text" + }, + { + "name": "name1", + "id": "id1", + "type": "Symbol" + }, + { + "name": "name2", + "id": "id2", + "type": "Integer" + }, + { + "name": "name3", + "id": "id3", + "type": "Number" + }, + { + "name": "name4", + "id": "id4", + "type": "Boolean" + }, + { + "name": "name5", + "id": "id5", + "type": "Date" + }, + { + "name": "name6", + "id": "id6", + "type": "Location" + }, + { + "name": "name7", + "id": "id7", + "type": "Link", + "linkType": "Entry" + }, + { + "name": "name8", + "id": "id8", + "type": "Object" + }, + { + "name": "name9", + "id": "id9", + "type": "Array", + "items": { + "type": "Link", + "linkType": "Entry" + } + } + ], + "name": "ctname", + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "spaceid" + } + }, + "type": "ContentType", + "id": "ct", + "revision": 1, + "createdAt": "2014-12-04T09:33:26.154Z", + "updatedAt": "2014-12-04T09:33:26.154Z" + }, + "description": "ctdesc", + "displayField": "t" +} diff --git a/src/test/resources/entry_fetch_all_response.json b/src/test/resources/entry_fetch_all_response.json new file mode 100644 index 00000000..65817c80 --- /dev/null +++ b/src/test/resources/entry_fetch_all_response.json @@ -0,0 +1,161 @@ +{ + "sys": { + "type": "Array" + }, + "total": 2, + "skip": 0, + "limit": 100, + "items": [ + { + "fields": { + "name": "Jake", + "description": "Bacon pancakes, makin' bacon pancakes!", + "image": { + "sys": { + "type": "Link", + "linkType": "Asset", + "id": "jake" + } + }, + "entry": { + "sys": { + "type": "Link", + "linkType": "Entry", + "id": "doge" + } + } + }, + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "cfexampleapi" + } + }, + "type": "Entry", + "contentType": { + "sys": { + "type": "Link", + "linkType": "ContentType", + "id": "dog" + } + }, + "id": "jake", + "revision": 5, + "createdAt": "2013-06-27T22:46:22.096Z", + "updatedAt": "2013-12-18T13:10:26.212Z", + "locale": "en-US" + } + }, + { + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "cfexampleapi" + } + }, + "type": "Entry", + "contentType": { + "sys": { + "type": "Link", + "linkType": "ContentType", + "id": "xx" + } + }, + "id": "5e9hw302IMsEisEuqCgOk6", + "revision": 1, + "createdAt": "2014-12-03T16:56:47.813Z", + "updatedAt": "2014-12-03T16:56:47.813Z", + "locale": "en-US" + }, + "fields": { + "aaa": "b", + "sss": [ + { + "sys": { + "type": "Link", + "linkType": "Entry", + "id": "doge" + } + } + ] + } + } + ], + "includes": { + "Asset": [ + { + "fields": { + "title": "Jake", + "file": { + "fileName": "jake.png", + "contentType": "image/png", + "details": { + "image": { + "width": 100, + "height": 161 + }, + "size": 20480 + }, + "url": "//images.contentful.com/cfexampleapi/a/b/jake.png" + } + }, + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "cfexampleapi" + } + }, + "type": "Asset", + "id": "jake", + "revision": 2, + "createdAt": "2013-09-02T14:56:34.260Z", + "updatedAt": "2013-09-02T15:22:39.466Z", + "locale": "en-US" + } + } + ], + "Entry": [ + { + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "cfexampleapi" + } + }, + "type": "Entry", + "contentType": { + "sys": { + "type": "Link", + "linkType": "ContentType", + "id": "dog" + } + }, + "id": "doge", + "revision": 2, + "createdAt": "2013-11-06T09:45:27.475Z", + "updatedAt": "2013-11-18T09:13:37.808Z", + "locale": "en-US" + }, + "fields": { + "name": "Doge", + "image": { + "sys": { + "type": "Link", + "linkType": "Asset", + "id": "1x0xpXu4pSGS4OukSyWGUK" + } + }, + "description": "such json\nwow" + } + } + ] + } +} diff --git a/src/test/resources/entry_fetch_one_response.json b/src/test/resources/entry_fetch_one_response.json new file mode 100644 index 00000000..a0afe2b6 --- /dev/null +++ b/src/test/resources/entry_fetch_one_response.json @@ -0,0 +1,35 @@ +{ + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "cfexampleapi" + } + }, + "type": "Entry", + "contentType": { + "sys": { + "type": "Link", + "linkType": "ContentType", + "id": "dog" + } + }, + "id": "jake", + "revision": 2, + "createdAt": "2013-11-06T09:45:27.475Z", + "updatedAt": "2013-11-18T09:13:37.808Z", + "locale": "en-US" + }, + "fields": { + "name": "Doge", + "image": { + "sys": { + "type": "Link", + "linkType": "Asset", + "id": "1x0xpXu4pSGS4OukSyWGUK" + } + }, + "description": "such json\nwow" + } +} diff --git a/src/test/resources/result_fetch_assets.json b/src/test/resources/result_fetch_assets.json deleted file mode 100644 index 4c92bec9..00000000 --- a/src/test/resources/result_fetch_assets.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "total": 4, - "skip": 0, - "limit": 100, - "items": [ - { - "fields": { - "title": "Jake", - "file": { - "fileName": "file_1.png", - "contentType": "image/png", - "details": { - "image": { - "width": 100, - "height": 161 - }, - "size": 20480 - }, - "url": "//test.url.com/file_1.png" - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "jake", - "revision": 2, - "createdAt": "2013-09-02T14:56:34.260Z", - "updatedAt": "2013-09-02T15:22:39.466Z", - "locale": "en-US" - } - }, - { - "fields": { - "title": "Nyan Cat", - "file": { - "fileName": "file_2.png", - "contentType": "image/png", - "details": { - "image": { - "width": 250, - "height": 250 - }, - "size": 12273 - }, - "url": "//test.url.com/file_2.png" - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "nyancat", - "revision": 1, - "createdAt": "2013-09-02T14:56:34.240Z", - "updatedAt": "2013-09-02T14:56:34.240Z", - "locale": "en-US" - } - } - ] -} diff --git a/src/test/resources/result_fetch_entries.json b/src/test/resources/result_fetch_entries.json deleted file mode 100644 index 1fa55a2b..00000000 --- a/src/test/resources/result_fetch_entries.json +++ /dev/null @@ -1,524 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "total": 11, - "skip": 0, - "limit": 100, - "items": [ - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "dog" - } - }, - "id": "6KntaYXaHSyIw8M6eo26OK", - "revision": 2, - "createdAt": "2013-11-06T09:45:27.475Z", - "updatedAt": "2013-11-18T09:13:37.808Z", - "locale": "en-US" - }, - "fields": { - "name": "Doge", - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "1x0xpXu4pSGS4OukSyWGUK" - } - }, - "description": "such json\nwow" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "4MU1s3potiUEM2G4okYOqw", - "revision": 1, - "createdAt": "2014-02-21T13:42:45.926Z", - "updatedAt": "2014-02-21T13:42:45.926Z", - "locale": "en-US" - }, - "fields": { - "name": "Berlin", - "center": { - "lat": 52.52000659999999, - "lon": 13.404953999999975 - } - } - }, - { - "fields": { - "name": "Happy Cat", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "nyancat" - } - }, - "likes": [ - "cheezburger" - ], - "color": "gray", - "birthday": "2003-10-28T23:00:00+00:00", - "lives": 1, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "happycat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "happycat", - "revision": 8, - "createdAt": "2013-06-27T22:46:20.171Z", - "updatedAt": "2013-11-18T15:58:02.018Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "63k4qdEi9aI8IQUGaYGg4O" - } - }, - "id": "CVebBDcQsSsu6yKKIayy", - "revision": 1, - "createdAt": "2013-06-23T19:06:46.224Z", - "updatedAt": "2013-06-23T19:06:46.224Z", - "locale": "en-US" - }, - "fields": { - "name": "Nyancat" - } - }, - { - "fields": { - "name": "Garfield", - "likes": [ - "lasagna" - ], - "color": "orange", - "lifes": null, - "lives": 9, - "birthday": "1979-06-18T23:00:00+00:00" - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "garfield", - "revision": 2, - "createdAt": "2013-06-27T22:46:20.821Z", - "updatedAt": "2013-08-27T10:09:07.929Z", - "locale": "en-US" - } - }, - { - "fields": { - "name": "Nyan Cat", - "likes": [ - "rainbows", - "fish" - ], - "color": "rainbow", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "happycat" - } - }, - "birthday": "2011-04-04T22:00:00+00:00", - "lives": 1337, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "nyancat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "nyancat", - "revision": 5, - "createdAt": "2013-06-27T22:46:19.513Z", - "updatedAt": "2013-09-04T09:19:39.027Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "7qVBlCjpWE86Oseo40gAEY", - "revision": 2, - "createdAt": "2014-02-21T13:43:38.258Z", - "updatedAt": "2014-04-15T08:22:22.010Z", - "locale": "en-US" - }, - "fields": { - "name": "San Francisco", - "center": { - "lat": 37.7749295, - "lon": -122.41941550000001 - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "5ETMRzkl9KM4omyMwKAOki", - "revision": 2, - "createdAt": "2014-02-21T13:42:57.752Z", - "updatedAt": "2014-04-16T12:44:02.691Z", - "locale": "en-US" - }, - "fields": { - "name": "London", - "center": { - "lat": 51.508515, - "lon": -0.12548719999995228 - } - } - }, - { - "fields": { - "name": "Finn", - "description": "Fearless adventurer! Defender of pancakes.", - "likes": [ - "adventure" - ] - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "human" - } - }, - "id": "finn", - "revision": 6, - "createdAt": "2013-06-27T22:46:21.450Z", - "updatedAt": "2013-09-09T16:15:01.297Z", - "locale": "en-US" - } - }, - { - "fields": { - "name": "Jake", - "description": "Bacon pancakes, makin' bacon pancakes!", - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "jake" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "dog" - } - }, - "id": "jake", - "revision": 5, - "createdAt": "2013-06-27T22:46:22.096Z", - "updatedAt": "2013-12-18T13:10:26.212Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "ge1xHyH3QOWucKWCCAgIG", - "revision": 1, - "createdAt": "2014-02-21T13:43:23.210Z", - "updatedAt": "2014-02-21T13:43:23.210Z", - "locale": "en-US" - }, - "fields": { - "name": "Paris", - "center": { - "lat": 48.856614, - "lon": 2.3522219000000177 - } - } - } - ], - "includes": { - "Asset": [ - { - "fields": { - "title": "Jake", - "file": { - "fileName": "jake.png", - "contentType": "image/png", - "details": { - "image": { - "width": 100, - "height": 161 - }, - "size": 20480 - }, - "url": "//images.contentful.com/cfexampleapi/4hlteQAXS8iS0YCMU6QMWg/2a4d826144f014109364ccf5c891d2dd/jake.png" - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "jake", - "revision": 2, - "createdAt": "2013-09-02T14:56:34.260Z", - "updatedAt": "2013-09-02T15:22:39.466Z", - "locale": "en-US" - } - }, - { - "fields": { - "title": "Nyan Cat", - "file": { - "fileName": "Nyan_cat_250px_frame.png", - "contentType": "image/png", - "details": { - "image": { - "width": 250, - "height": 250 - }, - "size": 12273 - }, - "url": "//images.contentful.com/cfexampleapi/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png" - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "nyancat", - "revision": 1, - "createdAt": "2013-09-02T14:56:34.240Z", - "updatedAt": "2013-09-02T14:56:34.240Z", - "locale": "en-US" - } - }, - { - "fields": { - "file": { - "fileName": "happycatw.jpg", - "contentType": "image/jpeg", - "details": { - "image": { - "width": 273, - "height": 397 - }, - "size": 59939 - }, - "url": "//images.contentful.com/cfexampleapi/3MZPnjZTIskAIIkuuosCss/382a48dfa2cb16c47aa2c72f7b23bf09/happycatw.jpg" - }, - "title": "Happy Cat" - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "happycat", - "revision": 2, - "createdAt": "2013-09-02T14:56:34.267Z", - "updatedAt": "2013-09-02T15:11:24.361Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "1x0xpXu4pSGS4OukSyWGUK", - "revision": 6, - "createdAt": "2013-11-06T09:45:10.000Z", - "updatedAt": "2013-12-18T13:27:14.917Z", - "locale": "en-US" - }, - "fields": { - "title": "Doge", - "file": { - "fileName": "doge.jpg", - "contentType": "image/jpeg", - "details": { - "image": { - "width": 5800, - "height": 4350 - }, - "size": 522943 - }, - "url": "//images.contentful.com/cfexampleapi/1x0xpXu4pSGS4OukSyWGUK/cc1239c6385428ef26f4180190532818/doge.jpg" - }, - "description": "nice picture" - } - } - ] - } -} diff --git a/src/test/resources/result_fetch_entries_matching.json b/src/test/resources/result_fetch_entries_matching.json deleted file mode 100644 index f94d2377..00000000 --- a/src/test/resources/result_fetch_entries_matching.json +++ /dev/null @@ -1,175 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "total": 1, - "skip": 0, - "limit": 100, - "items": [ - { - "fields": { - "name": "Nyan Cat", - "likes": [ - "rainbows", - "fish" - ], - "color": "rainbow", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "happycat" - } - }, - "birthday": "2011-04-04T22:00:00+00:00", - "lives": 1337, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "nyancat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "nyancat", - "revision": 5, - "createdAt": "2013-06-27T22:46:19.513Z", - "updatedAt": "2013-09-04T09:19:39.027Z", - "locale": "en-US" - } - } - ], - "includes": { - "Entry": [ - { - "fields": { - "name": "Happy Cat", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "nyancat" - } - }, - "likes": [ - "cheezburger" - ], - "color": "gray", - "birthday": "2003-10-28T23:00:00+00:00", - "lives": 1, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "happycat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "happycat", - "revision": 8, - "createdAt": "2013-06-27T22:46:20.171Z", - "updatedAt": "2013-11-18T15:58:02.018Z", - "locale": "en-US" - } - } - ], - "Asset": [ - { - "fields": { - "title": "Nyan Cat", - "file": { - "fileName": "Nyan_cat_250px_frame.png", - "contentType": "image/png", - "details": { - "image": { - "width": 250, - "height": 250 - }, - "size": 12273 - }, - "url": "//images.contentful.com/cfexampleapi/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png" - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "nyancat", - "revision": 1, - "createdAt": "2013-09-02T14:56:34.240Z", - "updatedAt": "2013-09-02T14:56:34.240Z", - "locale": "en-US" - } - }, - { - "fields": { - "file": { - "fileName": "happycatw.jpg", - "contentType": "image/jpeg", - "details": { - "image": { - "width": 273, - "height": 397 - }, - "size": 59939 - }, - "url": "//images.contentful.com/cfexampleapi/3MZPnjZTIskAIIkuuosCss/382a48dfa2cb16c47aa2c72f7b23bf09/happycatw.jpg" - }, - "title": "Happy Cat" - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "happycat", - "revision": 2, - "createdAt": "2013-09-02T14:56:34.267Z", - "updatedAt": "2013-09-02T15:11:24.361Z", - "locale": "en-US" - } - } - ] - } -} diff --git a/src/test/resources/result_fetch_entries_with_includes.json b/src/test/resources/result_fetch_entries_with_includes.json deleted file mode 100644 index 1fa55a2b..00000000 --- a/src/test/resources/result_fetch_entries_with_includes.json +++ /dev/null @@ -1,524 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "total": 11, - "skip": 0, - "limit": 100, - "items": [ - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "dog" - } - }, - "id": "6KntaYXaHSyIw8M6eo26OK", - "revision": 2, - "createdAt": "2013-11-06T09:45:27.475Z", - "updatedAt": "2013-11-18T09:13:37.808Z", - "locale": "en-US" - }, - "fields": { - "name": "Doge", - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "1x0xpXu4pSGS4OukSyWGUK" - } - }, - "description": "such json\nwow" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "4MU1s3potiUEM2G4okYOqw", - "revision": 1, - "createdAt": "2014-02-21T13:42:45.926Z", - "updatedAt": "2014-02-21T13:42:45.926Z", - "locale": "en-US" - }, - "fields": { - "name": "Berlin", - "center": { - "lat": 52.52000659999999, - "lon": 13.404953999999975 - } - } - }, - { - "fields": { - "name": "Happy Cat", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "nyancat" - } - }, - "likes": [ - "cheezburger" - ], - "color": "gray", - "birthday": "2003-10-28T23:00:00+00:00", - "lives": 1, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "happycat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "happycat", - "revision": 8, - "createdAt": "2013-06-27T22:46:20.171Z", - "updatedAt": "2013-11-18T15:58:02.018Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "63k4qdEi9aI8IQUGaYGg4O" - } - }, - "id": "CVebBDcQsSsu6yKKIayy", - "revision": 1, - "createdAt": "2013-06-23T19:06:46.224Z", - "updatedAt": "2013-06-23T19:06:46.224Z", - "locale": "en-US" - }, - "fields": { - "name": "Nyancat" - } - }, - { - "fields": { - "name": "Garfield", - "likes": [ - "lasagna" - ], - "color": "orange", - "lifes": null, - "lives": 9, - "birthday": "1979-06-18T23:00:00+00:00" - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "garfield", - "revision": 2, - "createdAt": "2013-06-27T22:46:20.821Z", - "updatedAt": "2013-08-27T10:09:07.929Z", - "locale": "en-US" - } - }, - { - "fields": { - "name": "Nyan Cat", - "likes": [ - "rainbows", - "fish" - ], - "color": "rainbow", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "happycat" - } - }, - "birthday": "2011-04-04T22:00:00+00:00", - "lives": 1337, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "nyancat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "nyancat", - "revision": 5, - "createdAt": "2013-06-27T22:46:19.513Z", - "updatedAt": "2013-09-04T09:19:39.027Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "7qVBlCjpWE86Oseo40gAEY", - "revision": 2, - "createdAt": "2014-02-21T13:43:38.258Z", - "updatedAt": "2014-04-15T08:22:22.010Z", - "locale": "en-US" - }, - "fields": { - "name": "San Francisco", - "center": { - "lat": 37.7749295, - "lon": -122.41941550000001 - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "5ETMRzkl9KM4omyMwKAOki", - "revision": 2, - "createdAt": "2014-02-21T13:42:57.752Z", - "updatedAt": "2014-04-16T12:44:02.691Z", - "locale": "en-US" - }, - "fields": { - "name": "London", - "center": { - "lat": 51.508515, - "lon": -0.12548719999995228 - } - } - }, - { - "fields": { - "name": "Finn", - "description": "Fearless adventurer! Defender of pancakes.", - "likes": [ - "adventure" - ] - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "human" - } - }, - "id": "finn", - "revision": 6, - "createdAt": "2013-06-27T22:46:21.450Z", - "updatedAt": "2013-09-09T16:15:01.297Z", - "locale": "en-US" - } - }, - { - "fields": { - "name": "Jake", - "description": "Bacon pancakes, makin' bacon pancakes!", - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "jake" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "dog" - } - }, - "id": "jake", - "revision": 5, - "createdAt": "2013-06-27T22:46:22.096Z", - "updatedAt": "2013-12-18T13:10:26.212Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "ge1xHyH3QOWucKWCCAgIG", - "revision": 1, - "createdAt": "2014-02-21T13:43:23.210Z", - "updatedAt": "2014-02-21T13:43:23.210Z", - "locale": "en-US" - }, - "fields": { - "name": "Paris", - "center": { - "lat": 48.856614, - "lon": 2.3522219000000177 - } - } - } - ], - "includes": { - "Asset": [ - { - "fields": { - "title": "Jake", - "file": { - "fileName": "jake.png", - "contentType": "image/png", - "details": { - "image": { - "width": 100, - "height": 161 - }, - "size": 20480 - }, - "url": "//images.contentful.com/cfexampleapi/4hlteQAXS8iS0YCMU6QMWg/2a4d826144f014109364ccf5c891d2dd/jake.png" - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "jake", - "revision": 2, - "createdAt": "2013-09-02T14:56:34.260Z", - "updatedAt": "2013-09-02T15:22:39.466Z", - "locale": "en-US" - } - }, - { - "fields": { - "title": "Nyan Cat", - "file": { - "fileName": "Nyan_cat_250px_frame.png", - "contentType": "image/png", - "details": { - "image": { - "width": 250, - "height": 250 - }, - "size": 12273 - }, - "url": "//images.contentful.com/cfexampleapi/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png" - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "nyancat", - "revision": 1, - "createdAt": "2013-09-02T14:56:34.240Z", - "updatedAt": "2013-09-02T14:56:34.240Z", - "locale": "en-US" - } - }, - { - "fields": { - "file": { - "fileName": "happycatw.jpg", - "contentType": "image/jpeg", - "details": { - "image": { - "width": 273, - "height": 397 - }, - "size": 59939 - }, - "url": "//images.contentful.com/cfexampleapi/3MZPnjZTIskAIIkuuosCss/382a48dfa2cb16c47aa2c72f7b23bf09/happycatw.jpg" - }, - "title": "Happy Cat" - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "happycat", - "revision": 2, - "createdAt": "2013-09-02T14:56:34.267Z", - "updatedAt": "2013-09-02T15:11:24.361Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "1x0xpXu4pSGS4OukSyWGUK", - "revision": 6, - "createdAt": "2013-11-06T09:45:10.000Z", - "updatedAt": "2013-12-18T13:27:14.917Z", - "locale": "en-US" - }, - "fields": { - "title": "Doge", - "file": { - "fileName": "doge.jpg", - "contentType": "image/jpeg", - "details": { - "image": { - "width": 5800, - "height": 4350 - }, - "size": 522943 - }, - "url": "//images.contentful.com/cfexampleapi/1x0xpXu4pSGS4OukSyWGUK/cc1239c6385428ef26f4180190532818/doge.jpg" - }, - "description": "nice picture" - } - } - ] - } -} diff --git a/src/test/resources/result_fetch_entries_with_nested_links.json b/src/test/resources/result_fetch_entries_with_nested_links.json deleted file mode 100644 index f5b1a85d..00000000 --- a/src/test/resources/result_fetch_entries_with_nested_links.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "total": 5, - "skip": 0, - "limit": 100, - "items": [ - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "nhkrrfkqkvcv" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "3hEsRfcKgMGSaiocGQaqCo" - } - }, - "id": "1BW0xmr34cKEQcOym80yci", - "revision": 1, - "createdAt": "2014-03-21T09:13:12.941Z", - "updatedAt": "2014-03-21T09:13:12.941Z", - "locale": "en-US" - }, - "fields": { - "name": "Five Elephant", - "type": "Both", - "description": "Five Elephant, that’s who. On top of having their own roasters, their beans are also direct trade, meaning they deal on a one-to-one basis with the growers. Five Elephant also scores points for its seclusion, at the far end of Reichenberger Straße, which means that most of the customers are from the neighbourhood and it’s never too packed.", - "address": { - "lat": 52.49346999999999, - "lon": 13.438369999999964 - }, - "openingTimes": "M: 08:30 – 19:00\nT: 08:30 – 19:00\nW: 08:30 – 19:00\nT: 08:30 – 19:00\nF: 08:30 – 19:00\nS: 10:00 – 19:00\nS: 10:00 – 19:00", - "url": "http://www.fiveelephant.com/", - "phoneNumber": "03096081527", - "email": "answers@fiveelephant.com", - "rating": 5, - "pictures": [ - { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "4iB0CrqFm0EOmwg4We6GiI" - } - } - ] - } - } - ], - "includes": { - "Asset": [ - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "nhkrrfkqkvcv" - } - }, - "type": "Asset", - "id": "4iB0CrqFm0EOmwg4We6GiI", - "revision": 1, - "createdAt": "2014-03-21T09:07:07.563Z", - "updatedAt": "2014-03-21T09:07:07.563Z", - "locale": "en-US" - }, - "fields": { - "file": { - "fileName": "812826_WlSicbAdOhAtqUl-XZAorTAuTxsAnpNnVhrJ0RpWSSY.jpg", - "contentType": "image/jpeg", - "details": { - "image": { - "width": 720, - "height": 960 - }, - "size": 83870 - }, - "url": "//images.contentful.com/nhkrrfkqkvcv/4iB0CrqFm0EOmwg4We6GiI/e94ee57379968d5bae747501f51586ab/812826_WlSicbAdOhAtqUl-XZAorTAuTxsAnpNnVhrJ0RpWSSY.jpg" - }, - "title": "Five Elephant" - } - } - ] - } -} diff --git a/src/test/resources/result_fetch_entry_nyancat.json b/src/test/resources/result_fetch_entry_nyancat.json deleted file mode 100644 index f435ade4..00000000 --- a/src/test/resources/result_fetch_entry_nyancat.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "fields": { - "name": "Nyan Cat", - "likes": [ - "rainbows", - "fish" - ], - "color": "rainbow", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "happycat" - } - }, - "birthday": "2011-04-04T22:00:00+00:00", - "lives": 1337, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "nyancat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "nyancat", - "revision": 5, - "createdAt": "2013-06-27T22:46:19.513Z", - "updatedAt": "2013-09-04T09:19:39.027Z", - "locale": "en-US" - } -} diff --git a/src/test/resources/result_test_client_provider.json b/src/test/resources/result_test_client_provider.json deleted file mode 100644 index f94d2377..00000000 --- a/src/test/resources/result_test_client_provider.json +++ /dev/null @@ -1,175 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "total": 1, - "skip": 0, - "limit": 100, - "items": [ - { - "fields": { - "name": "Nyan Cat", - "likes": [ - "rainbows", - "fish" - ], - "color": "rainbow", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "happycat" - } - }, - "birthday": "2011-04-04T22:00:00+00:00", - "lives": 1337, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "nyancat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "nyancat", - "revision": 5, - "createdAt": "2013-06-27T22:46:19.513Z", - "updatedAt": "2013-09-04T09:19:39.027Z", - "locale": "en-US" - } - } - ], - "includes": { - "Entry": [ - { - "fields": { - "name": "Happy Cat", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "nyancat" - } - }, - "likes": [ - "cheezburger" - ], - "color": "gray", - "birthday": "2003-10-28T23:00:00+00:00", - "lives": 1, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "happycat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "happycat", - "revision": 8, - "createdAt": "2013-06-27T22:46:20.171Z", - "updatedAt": "2013-11-18T15:58:02.018Z", - "locale": "en-US" - } - } - ], - "Asset": [ - { - "fields": { - "title": "Nyan Cat", - "file": { - "fileName": "Nyan_cat_250px_frame.png", - "contentType": "image/png", - "details": { - "image": { - "width": 250, - "height": 250 - }, - "size": 12273 - }, - "url": "//images.contentful.com/cfexampleapi/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png" - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "nyancat", - "revision": 1, - "createdAt": "2013-09-02T14:56:34.240Z", - "updatedAt": "2013-09-02T14:56:34.240Z", - "locale": "en-US" - } - }, - { - "fields": { - "file": { - "fileName": "happycatw.jpg", - "contentType": "image/jpeg", - "details": { - "image": { - "width": 273, - "height": 397 - }, - "size": 59939 - }, - "url": "//images.contentful.com/cfexampleapi/3MZPnjZTIskAIIkuuosCss/382a48dfa2cb16c47aa2c72f7b23bf09/happycatw.jpg" - }, - "title": "Happy Cat" - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "happycat", - "revision": 2, - "createdAt": "2013-09-02T14:56:34.267Z", - "updatedAt": "2013-09-02T15:11:24.361Z", - "locale": "en-US" - } - } - ] - } -} diff --git a/src/test/resources/result_test_fetch_content_type_with_id.json b/src/test/resources/result_test_fetch_content_type_with_id.json deleted file mode 100644 index ed8d996f..00000000 --- a/src/test/resources/result_test_fetch_content_type_with_id.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "fields": [ - { - "id": "name", - "name": "Name", - "type": "Text", - "required": true, - "localized": true - }, - { - "id": "likes", - "name": "Likes", - "type": "Array", - "required": false, - "localized": false, - "items": { - "type": "Symbol" - } - }, - { - "id": "color", - "name": "Color", - "type": "Symbol", - "required": false, - "localized": false - }, - { - "id": "bestFriend", - "name": "Best Friend", - "type": "Link", - "required": false, - "localized": false, - "linkType": "Entry" - }, - { - "id": "birthday", - "name": "Birthday", - "type": "Date", - "required": false, - "localized": false - }, - { - "id": "lifes", - "name": "Lifes left", - "type": "Integer", - "required": false, - "localized": false, - "disabled": true - }, - { - "id": "lives", - "name": "Lives left", - "type": "Integer", - "required": false, - "localized": false - }, - { - "id": "image", - "name": "Image", - "required": false, - "localized": false, - "type": "Link", - "linkType": "Asset" - } - ], - "name": "Cat", - "displayField": "name", - "description": "Meow.", - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "ContentType", - "id": "cat", - "revision": 2, - "createdAt": "2013-06-27T22:46:12.852Z", - "updatedAt": "2013-09-02T13:14:47.863Z" - } -} diff --git a/src/test/resources/result_test_no_display_field.json b/src/test/resources/result_test_no_display_field.json deleted file mode 100644 index b2d82ab7..00000000 --- a/src/test/resources/result_test_no_display_field.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "total": 1, - "skip": 0, - "limit": 100, - "items": [ - { - "name": "foobar", - "fields": [ - { - "id": "array", - "name": "Array", - "type": "Array" - } - ], - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "whatever" - } - }, - "type": "ContentType", - "id": "kkk", - "revision": 1, - "createdAt": "2014-08-07T09:05:16.848Z", - "updatedAt": "2014-08-07T09:05:16.848Z" - } - } - ] -} diff --git a/src/test/resources/result_test_paging_1.json b/src/test/resources/result_test_paging_1.json deleted file mode 100644 index ea083969..00000000 --- a/src/test/resources/result_test_paging_1.json +++ /dev/null @@ -1,333 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "total": 11, - "skip": 0, - "limit": 6, - "items": [ - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "dog" - } - }, - "id": "6KntaYXaHSyIw8M6eo26OK", - "revision": 2, - "createdAt": "2013-11-06T09:45:27.475Z", - "updatedAt": "2013-11-18T09:13:37.808Z", - "locale": "en-US" - }, - "fields": { - "name": "Doge", - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "1x0xpXu4pSGS4OukSyWGUK" - } - }, - "description": "such json\nwow" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "4MU1s3potiUEM2G4okYOqw", - "revision": 1, - "createdAt": "2014-02-21T13:42:45.926Z", - "updatedAt": "2014-02-21T13:42:45.926Z", - "locale": "en-US" - }, - "fields": { - "name": "Berlin", - "center": { - "lat": 52.52000659999999, - "lon": 13.404953999999975 - } - } - }, - { - "fields": { - "name": "Happy Cat", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "nyancat" - } - }, - "likes": [ - "cheezburger" - ], - "color": "gray", - "birthday": "2003-10-28T23:00:00+00:00", - "lives": 1, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "happycat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "happycat", - "revision": 8, - "createdAt": "2013-06-27T22:46:20.171Z", - "updatedAt": "2013-11-18T15:58:02.018Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "63k4qdEi9aI8IQUGaYGg4O" - } - }, - "id": "CVebBDcQsSsu6yKKIayy", - "revision": 1, - "createdAt": "2013-06-23T19:06:46.224Z", - "updatedAt": "2013-06-23T19:06:46.224Z", - "locale": "en-US" - }, - "fields": { - "name": "Nyancat" - } - }, - { - "fields": { - "name": "Garfield", - "likes": [ - "lasagna" - ], - "color": "orange", - "lifes": null, - "lives": 9, - "birthday": "1979-06-18T23:00:00+00:00" - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "garfield", - "revision": 2, - "createdAt": "2013-06-27T22:46:20.821Z", - "updatedAt": "2013-08-27T10:09:07.929Z", - "locale": "en-US" - } - }, - { - "fields": { - "name": "Nyan Cat", - "likes": [ - "rainbows", - "fish" - ], - "color": "rainbow", - "bestFriend": { - "sys": { - "type": "Link", - "linkType": "Entry", - "id": "happycat" - } - }, - "birthday": "2011-04-04T22:00:00+00:00", - "lives": 1337, - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "nyancat" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "cat" - } - }, - "id": "nyancat", - "revision": 5, - "createdAt": "2013-06-27T22:46:19.513Z", - "updatedAt": "2013-09-04T09:19:39.027Z", - "locale": "en-US" - } - } - ], - "includes": { - "Asset": [ - { - "fields": { - "title": "Nyan Cat", - "file": { - "fileName": "Nyan_cat_250px_frame.png", - "contentType": "image/png", - "details": { - "image": { - "width": 250, - "height": 250 - }, - "size": 12273 - }, - "url": "//images.contentful.com/cfexampleapi/4gp6taAwW4CmSgumq2ekUm/9da0cd1936871b8d72343e895a00d611/Nyan_cat_250px_frame.png" - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "nyancat", - "revision": 1, - "createdAt": "2013-09-02T14:56:34.240Z", - "updatedAt": "2013-09-02T14:56:34.240Z", - "locale": "en-US" - } - }, - { - "fields": { - "file": { - "fileName": "happycatw.jpg", - "contentType": "image/jpeg", - "details": { - "image": { - "width": 273, - "height": 397 - }, - "size": 59939 - }, - "url": "//images.contentful.com/cfexampleapi/3MZPnjZTIskAIIkuuosCss/382a48dfa2cb16c47aa2c72f7b23bf09/happycatw.jpg" - }, - "title": "Happy Cat" - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "happycat", - "revision": 2, - "createdAt": "2013-09-02T14:56:34.267Z", - "updatedAt": "2013-09-02T15:11:24.361Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "1x0xpXu4pSGS4OukSyWGUK", - "revision": 6, - "createdAt": "2013-11-06T09:45:10.000Z", - "updatedAt": "2013-12-18T13:27:14.917Z", - "locale": "en-US" - }, - "fields": { - "title": "Doge", - "file": { - "fileName": "doge.jpg", - "contentType": "image/jpeg", - "details": { - "image": { - "width": 5800, - "height": 4350 - }, - "size": 522943 - }, - "url": "//images.contentful.com/cfexampleapi/1x0xpXu4pSGS4OukSyWGUK/cc1239c6385428ef26f4180190532818/doge.jpg" - }, - "description": "nice picture" - } - } - ] - } -} \ No newline at end of file diff --git a/src/test/resources/result_test_paging_2.json b/src/test/resources/result_test_paging_2.json deleted file mode 100644 index 4f5f3524..00000000 --- a/src/test/resources/result_test_paging_2.json +++ /dev/null @@ -1,205 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "total": 11, - "skip": 6, - "limit": 6, - "items": [ - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "7qVBlCjpWE86Oseo40gAEY", - "revision": 2, - "createdAt": "2014-02-21T13:43:38.258Z", - "updatedAt": "2014-04-15T08:22:22.010Z", - "locale": "en-US" - }, - "fields": { - "name": "San Francisco", - "center": { - "lat": 37.7749295, - "lon": -122.41941550000001 - } - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "5ETMRzkl9KM4omyMwKAOki", - "revision": 2, - "createdAt": "2014-02-21T13:42:57.752Z", - "updatedAt": "2014-04-16T12:44:02.691Z", - "locale": "en-US" - }, - "fields": { - "name": "London", - "center": { - "lat": 51.508515, - "lon": -0.12548719999995228 - } - } - }, - { - "fields": { - "name": "Finn", - "description": "Fearless adventurer! Defender of pancakes.", - "likes": [ - "adventure" - ] - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "human" - } - }, - "id": "finn", - "revision": 6, - "createdAt": "2013-06-27T22:46:21.450Z", - "updatedAt": "2013-09-09T16:15:01.297Z", - "locale": "en-US" - } - }, - { - "fields": { - "name": "Jake", - "description": "Bacon pancakes, makin' bacon pancakes!", - "image": { - "sys": { - "type": "Link", - "linkType": "Asset", - "id": "jake" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "dog" - } - }, - "id": "jake", - "revision": 5, - "createdAt": "2013-06-27T22:46:22.096Z", - "updatedAt": "2013-12-18T13:10:26.212Z", - "locale": "en-US" - } - }, - { - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Entry", - "contentType": { - "sys": { - "type": "Link", - "linkType": "ContentType", - "id": "1t9IbcfdCk6m04uISSsaIK" - } - }, - "id": "ge1xHyH3QOWucKWCCAgIG", - "revision": 1, - "createdAt": "2014-02-21T13:43:23.210Z", - "updatedAt": "2014-02-21T13:43:23.210Z", - "locale": "en-US" - }, - "fields": { - "name": "Paris", - "center": { - "lat": 48.856614, - "lon": 2.3522219000000177 - } - } - } - ], - "includes": { - "Asset": [ - { - "fields": { - "title": "Jake", - "file": { - "fileName": "jake.png", - "contentType": "image/png", - "details": { - "image": { - "width": 100, - "height": 161 - }, - "size": 20480 - }, - "url": "//images.contentful.com/cfexampleapi/4hlteQAXS8iS0YCMU6QMWg/2a4d826144f014109364ccf5c891d2dd/jake.png" - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "cfexampleapi" - } - }, - "type": "Asset", - "id": "jake", - "revision": 2, - "createdAt": "2013-09-02T14:56:34.260Z", - "updatedAt": "2013-09-02T15:22:39.466Z", - "locale": "en-US" - } - } - ] - } -} \ No newline at end of file diff --git a/src/test/resources/result_test_paging_3.json b/src/test/resources/result_test_paging_3.json deleted file mode 100644 index d2bf86f8..00000000 --- a/src/test/resources/result_test_paging_3.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "total": 11, - "skip": 12, - "limit": 6, - "items": [], - "includes": {} -} \ No newline at end of file diff --git a/src/test/resources/result_test_sync_localized_asset.json b/src/test/resources/result_test_sync_localized_asset.json deleted file mode 100644 index c1821dfa..00000000 --- a/src/test/resources/result_test_sync_localized_asset.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "items": [ - { - "fields": { - "title": { - "en-US": "english", - "tlh": "tlh" - }, - "description": { - "en-US": "english", - "tlh": "tlh" - }, - "file": { - "en-US": { - "fileName": "0000000000000000000.gif", - "contentType": "image/gif", - "details": { - "image": { - "width": 700, - "height": 700 - }, - "size": 2012865 - }, - "url": "//whatever.com/abc.gif" - }, - "kk-KK": { - "fileName": "0000000000000000000.gif", - "contentType": "image/gif", - "details": { - "image": { - "width": 700, - "height": 700 - }, - "size": 2012865 - }, - "url": "//whatever.com/def.gif" - } - } - }, - "sys": { - "space": { - "sys": { - "type": "Link", - "linkType": "Space", - "id": "tvkb1s7wv0j4" - } - }, - "type": "Asset", - "id": "6gPyrmoHTOm6CkO0mMkIe2", - "revision": 1, - "createdAt": "2014-10-09T13:58:17.704Z", - "updatedAt": "2014-10-09T13:58:17.704Z" - } - } - ], - "nextSyncUrl": "https://cdn.contentful.com/spaces/ABC/sync?sync_token=XYZ", - "includes": {} -} diff --git a/src/test/resources/result_test_sync_update_empty.json b/src/test/resources/result_test_sync_update_empty.json deleted file mode 100644 index 114a4f77..00000000 --- a/src/test/resources/result_test_sync_update_empty.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "sys": { - "type": "Array" - }, - "items": [], - "nextSyncUrl": "http://cdn.contentful.com/spaces/FAKE/sync?sync_token=FAKE" -} diff --git a/src/test/resources/space.json b/src/test/resources/space.json deleted file mode 100644 index e1b9501f..00000000 --- a/src/test/resources/space.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "sys": { - "type": "Space", - "id": "cfexampleapi" - }, - "name": "Contentful Example API", - "locales": [ - { - "code": "en-US", - "default": true, - "name": "English" - }, - { - "code": "tlh", - "default": false, - "name": "Klingon" - } - ] -} diff --git a/src/test/resources/result_test_fetch_space.json b/src/test/resources/space_fetch_response.json similarity index 100% rename from src/test/resources/result_test_fetch_space.json rename to src/test/resources/space_fetch_response.json diff --git a/src/test/resources/result_test_sync_initial.json b/src/test/resources/sync_initial_response.json similarity index 71% rename from src/test/resources/result_test_sync_initial.json rename to src/test/resources/sync_initial_response.json index 5e75302a..23ca2e8f 100644 --- a/src/test/resources/result_test_sync_initial.json +++ b/src/test/resources/sync_initial_response.json @@ -98,6 +98,44 @@ "en-US": 2789 } } + }, + { + "fields": { + "title": { + "en-US": "ab" + }, + "description": { + "en-US": "cd" + }, + "file": { + "en-US": { + "fileName": "d.jpg", + "contentType": "image/jpeg", + "details": { + "image": { + "width": 1680, + "height": 1293 + }, + "size": 94390 + }, + "url": "//images.contentful.com/a/b/c/d.jpg" + } + } + }, + "sys": { + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "ljblbezb2orh" + } + }, + "type": "Asset", + "id": "3FwHbbFjeg8A4OiKe8yku6", + "revision": 1, + "createdAt": "2014-12-03T16:47:45.671Z", + "updatedAt": "2014-12-03T16:47:45.671Z" + } } ], "nextSyncUrl": "http://cdn.contentful.com/spaces/FAKE/sync?sync_token=FAKE" diff --git a/src/test/resources/result_test_sync_update.json b/src/test/resources/sync_update_response.json similarity index 82% rename from src/test/resources/result_test_sync_update.json rename to src/test/resources/sync_update_response.json index f465c7bb..534cd300 100644 --- a/src/test/resources/result_test_sync_update.json +++ b/src/test/resources/sync_update_response.json @@ -84,6 +84,23 @@ "updatedAt": "2014-07-31T15:14:59.226Z", "deletedAt": "2014-07-31T15:14:59.226Z" } + }, + { + "sys": { + "type": "DeletedAsset", + "id": "3FwHbbFjeg8A4OiKe8yku6", + "space": { + "sys": { + "type": "Link", + "linkType": "Space", + "id": "ljblbezb2orh" + } + }, + "revision": 1, + "createdAt": "2014-12-03T16:51:23.658Z", + "updatedAt": "2014-12-03T16:51:23.658Z", + "deletedAt": "2014-12-03T16:51:23.658Z" + } } ], "nextSyncUrl": "http://cdn.contentful.com/spaces/FAKE/sync?sync_token=FAKE"