├── .buildscript ├── deploy_snapshot.sh └── settings.xml ├── .codecov.yml ├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets └── feature_graphic.png ├── compiler ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── contentful │ │ │ └── vault │ │ │ └── compiler │ │ │ ├── FieldsInjection.java │ │ │ ├── Injection.java │ │ │ ├── ModelInjection.java │ │ │ ├── Processor.java │ │ │ ├── SpaceInjection.java │ │ │ └── SqliteUtils.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── javax.annotation.processing.Processor │ └── test │ ├── java │ └── com │ │ └── contentful │ │ └── vault │ │ └── compiler │ │ ├── ContentTypeTest.java │ │ ├── FieldTest.java │ │ ├── SpaceTest.java │ │ └── lib │ │ └── TestUtils.java │ └── resources │ ├── FieldsInjection.java │ ├── ModelInjection.java │ ├── SpaceInjection.java │ ├── SpaceInjectionCopyPath.java │ └── SpaceInjectionVersion.java ├── core ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── contentful │ │ │ └── vault │ │ │ ├── AbsQuery.java │ │ │ ├── Asset.java │ │ │ ├── AutoEscapeValues.java │ │ │ ├── BaseFields.java │ │ │ ├── BlobUtils.java │ │ │ ├── Constants.java │ │ │ ├── ContentType.java │ │ │ ├── FetchQuery.java │ │ │ ├── Field.java │ │ │ ├── FieldMeta.java │ │ │ ├── Link.java │ │ │ ├── LinkResolver.java │ │ │ ├── ModelHelper.java │ │ │ ├── ObserveQuery.java │ │ │ ├── QueryResolver.java │ │ │ ├── Resource.java │ │ │ ├── Space.java │ │ │ ├── SpaceHelper.java │ │ │ ├── Sql.java │ │ │ ├── SqliteHelper.java │ │ │ ├── SyncCallback.java │ │ │ ├── SyncConfig.java │ │ │ ├── SyncException.java │ │ │ ├── SyncResult.java │ │ │ ├── SyncRunnable.java │ │ │ ├── Vault.java │ │ │ ├── VaultDatabaseExporter.java │ │ │ └── VaultThreadFactory.java │ └── templates │ │ └── com │ │ └── contentful │ │ └── vault │ │ └── build │ │ └── GeneratedBuildParameters.java │ └── test │ └── resources │ └── AndroidManifest.xml ├── jitpack.yml ├── last-module └── pom.xml ├── mvnw ├── mvnw.cmd ├── pom.xml ├── proguard-vault.cfg └── tests-integration ├── pom.xml └── src ├── main ├── AndroidManifest.xml └── assets │ └── cfexampleapi.db └── test ├── java └── com │ └── contentful │ └── vaultintegration │ ├── AllTheThingsTest.java │ ├── ArrayLinks.java │ ├── ArrayTest.java │ ├── BaseTest.java │ ├── BlobTest.java │ ├── DatabaseCopyTest.java │ ├── LinksTest.java │ ├── LocaleTest.java │ ├── LocalizedLinksTest.java │ ├── ObserveTest.java │ ├── ParcelableTest.java │ ├── SqliteEscapeTest.java │ ├── SyncBase.java │ ├── SyncPreviewTest.java │ ├── SyncTest.java │ ├── UpgradeTest.java │ ├── VaultTest.java │ └── lib │ ├── allthethings │ ├── AllTheThingsResource.java │ └── AllTheThingsSpace.java │ ├── arraylinks │ ├── MultiLinksSpace.java │ ├── Product.java │ └── Shop.java │ ├── demo │ ├── Cat.java │ └── DemoSpace.java │ ├── escape │ ├── SqliteEscapeModel.java │ └── SqliteEscapeSpace.java │ ├── links │ ├── AssetsContainer.java │ └── LinksSpace.java │ ├── localizedlinks │ ├── Container.java │ └── LocalizedLinksSpace.java │ └── vault │ ├── ArraysResource.java │ ├── BlobResource.java │ └── VaultSpace.java └── resources ├── AndroidManifest.xml ├── allthethings ├── initial.json ├── locales.json └── types.json ├── arraylinks ├── initial.json ├── locales.json └── types.json ├── assets ├── empty.json ├── initial.json ├── locales.json └── types.json ├── demo ├── initial.json ├── locales.json ├── types.json └── update.json ├── escape ├── initial.json ├── locales.json └── types.json ├── links ├── initial.json ├── locales.json ├── types.json └── update.json ├── localizedlinks ├── initial.json ├── locales.json └── types.json └── vault ├── initial.json ├── locales.json └── types.json /.buildscript/deploy_snapshot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Deploy a jar, source jar, and javadoc jar to Sonatype's snapshot repo. 4 | # 5 | # Adapted from https://coderwall.com/p/9b_lfq and 6 | # http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/ 7 | 8 | SLUG="contentful/vault" 9 | JDK="oraclejdk8" 10 | BRANCH="master" 11 | 12 | set -e 13 | 14 | if [ "$TRAVIS_REPO_SLUG" != "$SLUG" ]; then 15 | echo "Skipping snapshot deployment: wrong repository. Expected '$SLUG' but was '$TRAVIS_REPO_SLUG'." 16 | elif [ "$TRAVIS_JDK_VERSION" != "$JDK" ]; then 17 | echo "Skipping snapshot deployment: wrong JDK. Expected '$JDK' but was '$TRAVIS_JDK_VERSION'." 18 | elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then 19 | echo "Skipping snapshot deployment: was pull request." 20 | elif [ "$TRAVIS_BRANCH" != "$BRANCH" ]; then 21 | echo "Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$TRAVIS_BRANCH'." 22 | else 23 | echo "Deploying snapshot to maven ..." 24 | mvn clean source:jar javadoc:jar deploy --settings=".buildscript/settings.xml" -Dmaven.test.skip=true 25 | echo "Snapshot deployed to maven!" 26 | fi 27 | 28 | echo "Deploying snapshot to jitpack ..." 29 | curl https://jitpack.io/com/github/contentful/vault/${TRAVIS_BRANCH}-SNAPSHOT 30 | echo "Snapshot deployed to jitpack!" 31 | -------------------------------------------------------------------------------- /.buildscript/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | sonatype-nexus-snapshots 5 | ${env.CI_DEPLOY_USERNAME} 6 | ${env.CI_DEPLOY_PASSWORD} 7 | 8 | 9 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | precision: 1 3 | range: 70...100 4 | 5 | status: 6 | project: 7 | default: 8 | enabled: yes 9 | threshold: 1 10 | if_not_found: success 11 | if_no_updates: success 12 | 13 | comment: 14 | behavior: new 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | target/ 3 | *.iml 4 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contentful/vault/4f6a5ed4f6c592f4ee68a4fac23c876b173b9291/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | jdk: 4 | - openjdk8 5 | - oraclejdk8 6 | 7 | after_success: 8 | - .buildscript/deploy_snapshot.sh 9 | 10 | env: 11 | global: 12 | - secure: hRICT/jbg/nUqpf3z1bA0/W5B18gG4tXcS1PknosyCJlDqTzqAoAxY8txwCDaIODXlRTr0Ttmo+JhzR2nvoP0ojMu++FJRtsB7Zk7sC9QPTJJBgVcMiV6GpzMEK/KCBN4Z/bVFnVCUWleEkysKpctYGCpUZodsjicA7CLU2bRSY3wvVF93HugPA00qZjY2o85F/pKH5m1liazo/bO3R1GWZ0qFnisqpFcaGWp0RFeh4GHG2n+h7vZmytE/wHuEg5iXrbb4lq6I4aDVeYOffpUcHp/u6fs2U1wzdNqN0krNcNQcHZI+NaRQzc0nJ3ntWdxJx+FkptBW5p1run1ynvY3y1qhT3F80qEwoLoM8z6jimvD5yJjhzFRDYyykZqNu7XqqYn88PpjUFHtghLBvJQ1WSMb7OmbMdExt/l1W/23FGWRKEcJHD8dw91pv6efZcVqT+JlweVtUiMz0XDEKdZDBjWZqhK4/wiNsIjsNeIocyKESKyzz6jg9p2qu8b8MTTR2hmVtOCJQmbhKl9uC4UVExqsK0w52LQfmtQ82BfsUU7OPMCULOCmnG195v9q0FmgGi7+IQpIm6HmL3iinNTNKFeN3atWz/EgAdmUo4cnjS5KIsf+Ko/IcbsuRLCufT3nnmKKN/JiuBPQ5RM4Eu4LnVils7G+78xbUtUa9q98c= 13 | - secure: LbWygLMrmjUdwuwgPYf8P2RGuzWC+eRgH4DsmZtsy1SvaE26EX4tlPxbrSJFD8qrDTcfrzpJjrIuQzMHC2vN7K592t7XXHFb6iIUocm3wEbjvQSoaHHpX6lLXFNhJSNabhEyhE10DiBfRn9tkXE7NbQjRgyzhb0tD8iNZY/q/xB++NU6ghAICZP/Bx8xuT8ioIIA9RmEgGZRq9Ym9sqpvlZ8Lx8vKXjQlBS8GXKgZcIwwlQRXh6ciRRim29Lsyp9pBrp2rOoTBEbm1vaozuzFuqUuhA/9mdaKGu2/H75vH3iQL3yKcm4Jgb8rAvfSpfaxTxAV3mfG4jYZA6NSyz7WIn9GppPrxnbHZhIMK+g8BbrWyHdRR3IG8LV4j/Ln05LA+0bbJee2stqOLQvRbuHCBqXN1JmsABC8VHJIN2PjLOblvcpV2cf++hq2xzTCSIjXaNt7MhOP/caFC5LnOUFv4JNt4J5KyKa78rl6O6W8IYcBdZtjHdwOPRcIkIHDcqi4kvcLQMt1cz3ZHMoQgc6Izpo3b3hMMuTSdKBbBSbY3towFtg/7XwDW4FXERVaPhs8Z5AYSUnusGlhq2wY0H0oV14HrliQO9i2Tuk2p8hlIRjQQZDzq15YGehWrI/tDpvurgNa9SYGcqxvBn+XPeS3OnTyvEypuG653Wxi/Mb/nQ= 14 | 15 | android: 16 | components: 17 | - tools 18 | - platform-tools 19 | - tools 20 | - build-tools-25.0.3 21 | - android-19 22 | licenses: 23 | - android-.+ 24 | - google-.+ 25 | 26 | sudo: required 27 | 28 | branches: 29 | except: 30 | - gh-pages 31 | 32 | notifications: 33 | slack: 34 | - secure: KTrEbtoFwNCHe3Xa+WVpyVMENu35Y+rml9Xs7XNtcjk6Ke//DvjGZTIUwuG9GWXmT+aDkLL4CaBUUhRapZdg7CUsBjIU5rusBSsOJEuAWUu0QcLDVRC1lxhSo8Ebcf8KxMtrFAW4h7psjGvDg3eBCj6vH5/+wUMS4lzgeDYoouhZUKETshKd7rrYCQy5qH4nmkoHFKQ5qJNFh/uVCyvQerEZnLOK6EHFfV5ZG9f74gt+3yNYJkQRBEvCccj7cpLUYQze42ZHyvQmqBg8AEad8stJQa4G6wVd186BXTkz03vVdtzivdLgHwcDS0NNkbd4OOiVBR0jX0EyiTAD83GYxX2tSMuumpqEDNGzZuCLdHPR+X2ZpWgHY7XB8ipafpSMMAaB0sxe+YTfjJduFiGcnPr1PcVOIY/sOWZZ4AM7jOR5ymFozQ5XlKcCZQJqrtm4cgQezmJzsTYqRZjmfp4H5VxpFN07qejOcTjKTN/n7nFpbH8LKsEflwhfN/MPHyA4iL9E00X2m3wp+jZLdj9lwjPyPhxRXynmGickvDHbLk7yYb+blO0b2fMYhnKHg1vJMxaB53iChzFv70IWW05O3n+eFH7FwVsboZBWofEmxPmat73HG2x3ViUbAwPEa/LZVAQ8Cw89mxiBZXVd1/3vyIQXWF3iaKdZrDGXIvtx6qY= 35 | 36 | cache: 37 | directories: 38 | - $HOME/.m2 39 | -------------------------------------------------------------------------------- /assets/feature_graphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contentful/vault/4f6a5ed4f6c592f4ee68a4fac23c876b173b9291/assets/feature_graphic.png -------------------------------------------------------------------------------- /compiler/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | com.contentful.vault 7 | vault-parent 8 | 3.2.7-SNAPSHOT 9 | 10 | 11 | compiler 12 | 13 | 14 | 15 | commons-codec 16 | commons-codec 17 | 18 | 19 | 20 | com.google.guava 21 | guava 22 | 23 | 24 | 25 | com.squareup 26 | javapoet 27 | 28 | 29 | 30 | com.contentful.java 31 | java-sdk 32 | 33 | 34 | 35 | com.google.android 36 | android 37 | provided 38 | 39 | 40 | 41 | com.contentful.vault 42 | core 43 | ${project.version} 44 | provided 45 | 46 | 47 | 48 | sun.jdk 49 | tools 50 | 1.8.0 51 | system 52 | ${java.home}/../lib/tools.jar 53 | 54 | 55 | 56 | 57 | junit 58 | junit 59 | test 60 | 61 | 62 | 63 | com.google.testing.compile 64 | compile-testing 65 | test 66 | 67 | 68 | 69 | com.google.truth 70 | truth 71 | test 72 | 73 | 74 | 75 | commons-io 76 | commons-io 77 | test 78 | 79 | 80 | 81 | 82 | 83 | 84 | src/test/resources 85 | 86 | 87 | 88 | 89 | org.apache.maven.plugins 90 | maven-compiler-plugin 91 | 92 | -proc:none 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/contentful/vault/compiler/FieldsInjection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault.compiler; 18 | 19 | import com.contentful.vault.BaseFields; 20 | import com.contentful.vault.FieldMeta; 21 | import com.google.common.base.CaseFormat; 22 | import com.squareup.javapoet.ClassName; 23 | import com.squareup.javapoet.FieldSpec; 24 | import com.squareup.javapoet.TypeSpec; 25 | import java.util.Set; 26 | import javax.lang.model.element.Modifier; 27 | import javax.lang.model.element.TypeElement; 28 | 29 | final class FieldsInjection extends Injection { 30 | private final Set fields; 31 | 32 | public FieldsInjection(String remoteId, ClassName className, TypeElement originatingElement, 33 | Set fields) { 34 | super(remoteId, className, originatingElement); 35 | this.fields = fields; 36 | } 37 | 38 | @Override TypeSpec.Builder getTypeSpecBuilder() { 39 | TypeSpec.Builder builder = TypeSpec.classBuilder(className.simpleName()) 40 | .addModifiers(Modifier.PUBLIC, Modifier.FINAL) 41 | .superclass(BaseFields.class); 42 | 43 | for (FieldMeta field : fields) { 44 | builder.addField(createFieldSpec(field)); 45 | } 46 | 47 | return builder; 48 | } 49 | 50 | private FieldSpec createFieldSpec(FieldMeta field) { 51 | String name = CaseFormat.LOWER_CAMEL 52 | .converterTo(CaseFormat.UPPER_UNDERSCORE) 53 | .convert(field.name()); 54 | if (name == null) { 55 | throw new IllegalArgumentException( 56 | "Invalid field with ID '" + field.id() + "' for generated class '" + 57 | className.simpleName() + "', has no name."); 58 | } 59 | return FieldSpec.builder(String.class, name, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) 60 | .initializer("$S", field.name()) 61 | .build(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/contentful/vault/compiler/Injection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault.compiler; 18 | 19 | import com.squareup.javapoet.ClassName; 20 | import com.squareup.javapoet.FieldSpec; 21 | import com.squareup.javapoet.JavaFile; 22 | import com.squareup.javapoet.MethodSpec; 23 | import com.squareup.javapoet.ParameterizedTypeName; 24 | import com.squareup.javapoet.TypeName; 25 | import com.squareup.javapoet.TypeSpec; 26 | import java.util.List; 27 | import java.util.Map; 28 | import javax.lang.model.element.Modifier; 29 | import javax.lang.model.element.TypeElement; 30 | 31 | abstract class Injection { 32 | final String remoteId; 33 | 34 | final ClassName className; 35 | 36 | final TypeElement originatingElement; 37 | 38 | public Injection(String remoteId, ClassName className, TypeElement originatingElement) { 39 | this.remoteId = remoteId; 40 | this.className = className; 41 | this.originatingElement = originatingElement; 42 | } 43 | 44 | JavaFile brewJava() { 45 | TypeSpec.Builder typeSpecBuilder = getTypeSpecBuilder() 46 | .addOriginatingElement(originatingElement); 47 | 48 | return JavaFile.builder(className.packageName(), typeSpecBuilder.build()) 49 | .skipJavaLangImports(true) 50 | .build(); 51 | } 52 | 53 | abstract TypeSpec.Builder getTypeSpecBuilder(); 54 | 55 | protected MethodSpec.Builder createGetterImpl(FieldSpec field, String name) { 56 | return MethodSpec.methodBuilder(name) 57 | .returns(field.type) 58 | .addAnnotation(Override.class) 59 | .addModifiers(Modifier.PUBLIC) 60 | .addStatement("return $N", field.name); 61 | } 62 | 63 | protected FieldSpec.Builder createListWithInitializer(String name, 64 | Class listClass, TypeName typeName) { 65 | TypeName listTypeName = ParameterizedTypeName.get(ClassName.get(List.class), typeName); 66 | 67 | TypeName initializerTypeName = 68 | ParameterizedTypeName.get(ClassName.get(listClass), typeName); 69 | 70 | return FieldSpec.builder(listTypeName, name).initializer("new $T()", initializerTypeName); 71 | } 72 | 73 | protected FieldSpec.Builder createMapWithInitializer(String name, Class mapClass, 74 | TypeName keyTypeName, TypeName valueTypeName) { 75 | TypeName mapTypeName = ParameterizedTypeName.get( 76 | ClassName.get(Map.class), keyTypeName, valueTypeName); 77 | 78 | TypeName linkedMapTypeName = ParameterizedTypeName.get( 79 | ClassName.get(mapClass), keyTypeName, valueTypeName); 80 | 81 | return FieldSpec.builder(mapTypeName, name) 82 | .initializer("new $T()", linkedMapTypeName); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/contentful/vault/compiler/SqliteUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault.compiler; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | import org.apache.commons.codec.binary.Base64; 22 | 23 | final class SqliteUtils { 24 | private SqliteUtils() { 25 | throw new AssertionError(); 26 | } 27 | 28 | static String typeForClass(String className) { 29 | if (String.class.getName().equals(className)) { 30 | return "TEXT"; 31 | } else if (Boolean.class.getName().equals(className)) { 32 | return "BOOL"; 33 | } else if (Integer.class.getName().equals(className)) { 34 | return "INT"; 35 | } else if (Double.class.getName().equals(className)) { 36 | return "DOUBLE"; 37 | } else if (Map.class.getName().equals(className)) { 38 | return "BLOB"; 39 | } else if (List.class.getName().equals(className)) { 40 | return "BLOB"; 41 | } 42 | return null; 43 | } 44 | 45 | static String hashForId(String id) { 46 | return Base64.encodeBase64String(id.getBytes()).replaceAll("=", "").toLowerCase(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /compiler/src/main/resources/META-INF/services/javax.annotation.processing.Processor: -------------------------------------------------------------------------------- 1 | com.contentful.vault.compiler.Processor -------------------------------------------------------------------------------- /compiler/src/test/java/com/contentful/vault/compiler/ContentTypeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault.compiler; 18 | 19 | import com.google.common.base.Joiner; 20 | import com.google.testing.compile.JavaFileObjects; 21 | 22 | import org.junit.Test; 23 | 24 | import javax.tools.JavaFileObject; 25 | 26 | import static com.contentful.vault.compiler.lib.TestUtils.processors; 27 | import static com.contentful.vault.compiler.lib.TestUtils.readTestResource; 28 | import static com.google.common.truth.Truth.assert_; 29 | import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 30 | 31 | public class ContentTypeTest { 32 | @Test public void testInjection() throws Exception { 33 | JavaFileObject source = JavaFileObjects.forSourceString("Test", Joiner.on('\n').join( 34 | "import com.contentful.vault.Asset;", 35 | "import com.contentful.vault.ContentType;", 36 | "import com.contentful.vault.Field;", 37 | "import com.contentful.vault.Resource;", 38 | "import com.contentful.vault.SpaceHelper;", 39 | "import java.util.List;", 40 | "import java.util.Map;", 41 | "class Test {", 42 | " @ContentType(\"cid\")", 43 | " static class AwesomeModel extends Resource {", 44 | " @Field String textField;", 45 | " @Field Boolean booleanField;", 46 | " @Field Integer integerField;", 47 | " @Field Double doubleField;", 48 | " @Field Map mapField;", 49 | " @Field Asset assetLink;", 50 | " @Field AwesomeModel entryLink;", 51 | " @Field List arrayOfAssets;", 52 | " @Field List arrayOfModels;", 53 | " @Field List arrayOfSymbols;", 54 | " }", 55 | "}" 56 | )); 57 | 58 | JavaFileObject expectedSource = JavaFileObjects.forSourceString( 59 | "Test$AwesomeModel$$ModelHelper", 60 | readTestResource("ModelInjection.java")); 61 | 62 | assert_().about(javaSource()).that(source) 63 | .processedWith(processors()) 64 | .compilesWithoutError() 65 | .and() 66 | .generatesSources(expectedSource); 67 | } 68 | 69 | @Test public void failsEmptyId() throws Exception { 70 | JavaFileObject source = JavaFileObjects.forSourceString("Test", 71 | Joiner.on('\n').join( 72 | "import com.contentful.vault.ContentType;", 73 | "import com.contentful.vault.Resource;", 74 | "@ContentType(\"\")", 75 | "class Test extends Resource {", 76 | "}" 77 | )); 78 | 79 | assert_().about(javaSource()).that(source) 80 | .processedWith(processors()) 81 | .failsToCompile() 82 | .withErrorContaining("@ContentType id may not be empty. (Test)"); 83 | } 84 | 85 | @Test public void failsInvalidType() throws Exception { 86 | JavaFileObject source = JavaFileObjects.forSourceString("Test", Joiner.on('\n').join( 87 | "import com.contentful.vault.ContentType;", 88 | "import java.util.Date;", 89 | "@ContentType(\"cid\")", 90 | "class Test {", 91 | "}")); 92 | 93 | assert_().about(javaSource()).that(source) 94 | .processedWith(processors()) 95 | .failsToCompile() 96 | .withErrorContaining( 97 | "Classes annotated with @ContentType must extend \"com.contentful.vault.Resource\". " 98 | + "(Test)"); 99 | } 100 | 101 | @Test public void failsNoFields() throws Exception { 102 | JavaFileObject source = JavaFileObjects.forSourceString("Test", Joiner.on('\n').join( 103 | "import com.contentful.vault.ContentType;", 104 | "import com.contentful.vault.Resource;", 105 | "@ContentType(\"foo\")", 106 | "class Test extends Resource {", 107 | "}")); 108 | 109 | assert_().about(javaSource()).that(source) 110 | .processedWith(processors()) 111 | .failsToCompile() 112 | .withErrorContaining("Model must contain at least one @Field element. (Test)"); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /compiler/src/test/java/com/contentful/vault/compiler/lib/TestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault.compiler.lib; 18 | 19 | import com.contentful.vault.compiler.Processor; 20 | 21 | import org.apache.commons.io.FileUtils; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.net.URL; 26 | import java.nio.charset.Charset; 27 | import java.util.Arrays; 28 | 29 | public class TestUtils { 30 | public static Iterable processors() { 31 | return Arrays.asList(new Processor()); 32 | } 33 | 34 | public static String readTestResource(String fileName) throws IOException { 35 | URL resource = TestUtils.class.getClassLoader().getResource(fileName); 36 | return FileUtils.readFileToString(new File(resource.getPath()), Charset.defaultCharset()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /compiler/src/test/resources/FieldsInjection.java: -------------------------------------------------------------------------------- 1 | import com.contentful.vault.BaseFields; 2 | 3 | public final class Test$Model$Fields extends BaseFields { 4 | public static final String FOO = "foo"; 5 | 6 | public static final String BAR = "bar"; 7 | 8 | public static final String BAZ = "baz"; 9 | 10 | public static final String BAZ2 = "baz2"; 11 | 12 | public static final String B_A_Z_123 = "b_a_z_123"; 13 | } -------------------------------------------------------------------------------- /compiler/src/test/resources/ModelInjection.java: -------------------------------------------------------------------------------- 1 | import android.database.Cursor; 2 | import com.contentful.vault.Asset; 3 | import com.contentful.vault.FieldMeta; 4 | import com.contentful.vault.ModelHelper; 5 | import com.contentful.vault.SpaceHelper; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public final class Test$AwesomeModel$$ModelHelper extends ModelHelper { 12 | final List fields = new ArrayList(); 13 | 14 | public Test$AwesomeModel$$ModelHelper() { 15 | fields.add(FieldMeta.builder().setId("textField").setName("textField").setSqliteType("TEXT").build()); 16 | fields.add(FieldMeta.builder().setId("booleanField").setName("booleanField").setSqliteType("BOOL").build()); 17 | fields.add(FieldMeta.builder().setId("integerField").setName("integerField").setSqliteType("INT").build()); 18 | fields.add(FieldMeta.builder().setId("doubleField").setName("doubleField").setSqliteType("DOUBLE").build()); 19 | fields.add(FieldMeta.builder().setId("mapField").setName("mapField").setSqliteType("BLOB").build()); 20 | fields.add(FieldMeta.builder().setId("assetLink").setName("assetLink").setLinkType("ASSET").build()); 21 | fields.add(FieldMeta.builder().setId("entryLink").setName("entryLink").setLinkType("ENTRY").build()); 22 | fields.add(FieldMeta.builder().setId("arrayOfAssets").setName("arrayOfAssets").setArrayType( 23 | "com.contentful.vault.Asset").build()); 24 | fields.add(FieldMeta.builder().setId("arrayOfModels").setName("arrayOfModels").setArrayType("Test.AwesomeModel").build()); 25 | fields.add(FieldMeta.builder().setId("arrayOfSymbols").setName("arrayOfSymbols").setSqliteType( 26 | "BLOB").setArrayType("java.lang.String").build()); 27 | } 28 | 29 | @Override 30 | public List getFields() { 31 | return fields; 32 | } 33 | 34 | @Override 35 | public String getTableName() { 36 | return "entry_y2lk"; 37 | } 38 | 39 | @Override 40 | public List getCreateStatements(SpaceHelper spaceHelper) { 41 | List list = new ArrayList(); 42 | for (String code : spaceHelper.getLocales()) { 43 | list.add("CREATE TABLE `entry_y2lk$" + code + "` (`remote_id` STRING NOT NULL UNIQUE, `created_at` STRING NOT NULL, `updated_at` STRING, `textField` TEXT, `booleanField` BOOL, `integerField` INT, `doubleField` DOUBLE, `mapField` BLOB, `arrayOfSymbols` BLOB);"); 44 | } 45 | return list; 46 | } 47 | 48 | @Override 49 | @SuppressWarnings("unchecked") 50 | public Test.AwesomeModel fromCursor(Cursor cursor) { 51 | Test.AwesomeModel result = new Test.AwesomeModel(); 52 | setContentType(result, "cid"); 53 | result.textField = cursor.getString(3); 54 | result.booleanField = Integer.valueOf(1).equals(cursor.getInt(4)); 55 | result.integerField = cursor.getInt(5); 56 | result.doubleField = cursor.getDouble(6); 57 | result.mapField = fieldFromBlob(HashMap.class, cursor, 7); 58 | result.arrayOfSymbols = fieldFromBlob(ArrayList.class, cursor, 8); 59 | return result; 60 | } 61 | 62 | @Override 63 | @SuppressWarnings("unchecked") 64 | public boolean setField(Test.AwesomeModel resource, String name, Object value) { 65 | if ("textField".equals(name)) { 66 | resource.textField = (String) value; 67 | } 68 | else if ("booleanField".equals(name)) { 69 | resource.booleanField = (Boolean) value; 70 | } 71 | else if ("integerField".equals(name)) { 72 | resource.integerField = (Integer) value; 73 | } 74 | else if ("doubleField".equals(name)) { 75 | resource.doubleField = (Double) value; 76 | } 77 | else if ("mapField".equals(name)) { 78 | resource.mapField = (Map) value; 79 | } 80 | else if ("assetLink".equals(name)) { 81 | resource.assetLink = (Asset) value; 82 | } 83 | else if ("entryLink".equals(name)) { 84 | resource.entryLink = (Test.AwesomeModel) value; 85 | } 86 | else if ("arrayOfAssets".equals(name)) { 87 | resource.arrayOfAssets = (List) value; 88 | } 89 | else if ("arrayOfModels".equals(name)) { 90 | resource.arrayOfModels = (List) value; 91 | } 92 | else if ("arrayOfSymbols".equals(name)) { 93 | resource.arrayOfSymbols = (List) value; 94 | } 95 | else { 96 | return false; 97 | } 98 | return true; 99 | } 100 | } -------------------------------------------------------------------------------- /compiler/src/test/resources/SpaceInjection.java: -------------------------------------------------------------------------------- 1 | import com.contentful.vault.ModelHelper; 2 | import com.contentful.vault.Resource; 3 | import com.contentful.vault.SpaceHelper; 4 | import java.util.Arrays; 5 | import java.util.LinkedHashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public final class Test$AwesomeSpace$$SpaceHelper extends SpaceHelper { 10 | final Map, ModelHelper> models = new LinkedHashMap, ModelHelper>(); 11 | 12 | final Map> types = new LinkedHashMap>(); 13 | 14 | final List locales = Arrays.asList("foo", "bar"); 15 | 16 | public Test$AwesomeSpace$$SpaceHelper() { 17 | models.put(Test.Model.class, new Test$Model$$ModelHelper()); 18 | types.put("cid", Test.Model.class); 19 | } 20 | 21 | @Override 22 | public String getDatabaseName() { 23 | return "space_c2lk"; 24 | } 25 | 26 | @Override 27 | public int getDatabaseVersion() { 28 | return 1; 29 | } 30 | 31 | @Override 32 | public Map, ModelHelper> getModels() { 33 | return models; 34 | } 35 | 36 | @Override 37 | public Map> getTypes() { 38 | return types; 39 | } 40 | 41 | @Override 42 | public String getCopyPath() { 43 | return null; 44 | } 45 | 46 | @Override 47 | public String getSpaceId() { 48 | return "sid"; 49 | } 50 | 51 | @Override 52 | public List getLocales() { 53 | return locales; 54 | } 55 | } -------------------------------------------------------------------------------- /compiler/src/test/resources/SpaceInjectionCopyPath.java: -------------------------------------------------------------------------------- 1 | import com.contentful.vault.ModelHelper; 2 | import com.contentful.vault.Resource; 3 | import com.contentful.vault.SpaceHelper; 4 | import java.util.Arrays; 5 | import java.util.LinkedHashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public final class Test$AwesomeSpace$$SpaceHelper extends SpaceHelper { 10 | final Map, ModelHelper> models = new LinkedHashMap, ModelHelper>(); 11 | 12 | final Map> types = new LinkedHashMap>(); 13 | 14 | final List locales = Arrays.asList("foo"); 15 | 16 | public Test$AwesomeSpace$$SpaceHelper() { 17 | models.put(Test.Model.class, new Test$Model$$ModelHelper()); 18 | types.put("cid", Test.Model.class); 19 | } 20 | 21 | @Override 22 | public String getDatabaseName() { 23 | return "space_c2lk"; 24 | } 25 | 26 | @Override 27 | public int getDatabaseVersion() { 28 | return 1; 29 | } 30 | 31 | @Override 32 | public Map, ModelHelper> getModels() { 33 | return models; 34 | } 35 | 36 | @Override 37 | public Map> getTypes() { 38 | return types; 39 | } 40 | 41 | @Override 42 | public String getCopyPath() { 43 | return "foo.db"; 44 | } 45 | 46 | @Override 47 | public String getSpaceId() { 48 | return "sid"; 49 | } 50 | 51 | @Override 52 | public List getLocales() { 53 | return locales; 54 | } 55 | } -------------------------------------------------------------------------------- /compiler/src/test/resources/SpaceInjectionVersion.java: -------------------------------------------------------------------------------- 1 | import com.contentful.vault.ModelHelper; 2 | import com.contentful.vault.Resource; 3 | import com.contentful.vault.SpaceHelper; 4 | import java.util.Arrays; 5 | import java.util.LinkedHashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public final class Test$AwesomeSpace$$SpaceHelper extends SpaceHelper { 10 | final Map, ModelHelper> models = new LinkedHashMap, ModelHelper>(); 11 | 12 | final Map> types = new LinkedHashMap>(); 13 | 14 | final List locales = Arrays.asList("foo"); 15 | 16 | public Test$AwesomeSpace$$SpaceHelper() { 17 | models.put(Test.Model.class, new Test$Model$$ModelHelper()); 18 | types.put("cid", Test.Model.class); 19 | } 20 | 21 | @Override 22 | public String getDatabaseName() { 23 | return "space_c2lk"; 24 | } 25 | 26 | @Override 27 | public int getDatabaseVersion() { 28 | return 9; 29 | } 30 | 31 | @Override 32 | public Map, ModelHelper> getModels() { 33 | return models; 34 | } 35 | 36 | @Override 37 | public Map> getTypes() { 38 | return types; 39 | } 40 | 41 | @Override 42 | public String getCopyPath() { 43 | return null; 44 | } 45 | 46 | @Override 47 | public String getSpaceId() { 48 | return "sid"; 49 | } 50 | 51 | 52 | @Override 53 | public List getLocales() { 54 | return locales; 55 | } 56 | } -------------------------------------------------------------------------------- /core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | com.contentful.vault 7 | vault-parent 8 | 3.2.7-SNAPSHOT 9 | 10 | 11 | core 12 | 13 | 14 | 15 | org.apache.commons 16 | commons-lang3 17 | 18 | 19 | 20 | commons-io 21 | commons-io 22 | 23 | 24 | 25 | com.contentful.java 26 | java-sdk 27 | 28 | 29 | 30 | com.google.android 31 | android 32 | provided 33 | 34 | 35 | 36 | io.reactivex.rxjava3 37 | rxjava 38 | 3.0.0 39 | provided 40 | 41 | 42 | 43 | 44 | junit 45 | junit 46 | test 47 | 48 | 49 | 50 | org.mockito 51 | mockito-core 52 | test 53 | 54 | 55 | 56 | org.robolectric 57 | robolectric 58 | test 59 | 60 | 61 | 62 | 63 | 64 | 65 | src/main/resources 66 | true 67 | 68 | 69 | src/main/templates 70 | true 71 | 72 | ${project.build.directory}/generated-sources/ 73 | 74 | 75 | 76 | 77 | 78 | 79 | org.codehaus.mojo 80 | build-helper-maven-plugin 81 | ${build-helper.version} 82 | 83 | 84 | generate-sources 85 | 86 | add-source 87 | 88 | 89 | 90 | ${project.build.directory}/generated-sources/ 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/AbsQuery.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vault; 2 | 3 | abstract class AbsQuery> { 4 | private final Class type; 5 | 6 | private final Vault vault; 7 | 8 | private Params params = new Params(); 9 | 10 | AbsQuery(Class type, Vault vault) { 11 | this.type = type; 12 | this.vault = vault; 13 | } 14 | 15 | @SuppressWarnings("unchecked") 16 | public E where(String selection, String... args) { 17 | params.setSelection(selection); 18 | params.setSelectionArgs(args); 19 | return (E) this; 20 | } 21 | 22 | @SuppressWarnings("unchecked") 23 | public E limit(Integer limit) { 24 | String value = null; 25 | if (limit != null) { 26 | value = limit.toString(); 27 | } 28 | params.setLimit(value); 29 | return (E) this; 30 | } 31 | 32 | @SuppressWarnings("unchecked") 33 | public E order(String... order) { 34 | params.setOrder(order); 35 | return (E) this; 36 | } 37 | 38 | Class type() { 39 | return type; 40 | } 41 | 42 | Vault vault() { 43 | return vault; 44 | } 45 | 46 | Params params() { 47 | return params; 48 | } 49 | 50 | void setParams(Params params) { 51 | this.params = params; 52 | } 53 | 54 | static final class Params { 55 | private String selection; 56 | private String[] selectionArgs; 57 | private String limit; 58 | private String[] order; 59 | 60 | public String selection() { 61 | return selection; 62 | } 63 | 64 | public void setSelection(String selection) { 65 | this.selection = selection; 66 | } 67 | 68 | public String[] selectionArgs() { 69 | return selectionArgs; 70 | } 71 | 72 | public void setSelectionArgs(String[] selectionArgs) { 73 | this.selectionArgs = selectionArgs; 74 | } 75 | 76 | public String limit() { 77 | return limit; 78 | } 79 | 80 | public void setLimit(String limit) { 81 | this.limit = limit; 82 | } 83 | 84 | public String[] order() { 85 | return order; 86 | } 87 | 88 | public void setOrder(String[] order) { 89 | this.order = order; 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/Asset.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import android.os.Parcel; 20 | import android.os.Parcelable; 21 | import java.util.HashMap; 22 | import java.util.Map; 23 | 24 | import static com.contentful.java.cda.CDAType.ASSET; 25 | 26 | public final class Asset extends Resource implements Parcelable { 27 | private final String url; 28 | 29 | private final String mimeType; 30 | 31 | private final String title; 32 | 33 | private final String description; 34 | 35 | private final HashMap file; 36 | 37 | Asset(Builder builder) { 38 | this.url = builder.url; 39 | this.mimeType = builder.mimeType; 40 | this.title = builder.title; 41 | this.description = builder.description; 42 | this.file = builder.file; 43 | } 44 | 45 | public String url() { 46 | return url; 47 | } 48 | 49 | public String mimeType() { 50 | return mimeType; 51 | } 52 | 53 | public String title() { 54 | return title; 55 | } 56 | 57 | public String description() { 58 | return description; 59 | } 60 | 61 | public Map file() { 62 | return file; 63 | } 64 | 65 | @Override String getIdPrefix() { 66 | return ASSET.toString(); 67 | } 68 | 69 | static Builder builder() { 70 | return new Builder(); 71 | } 72 | 73 | static class Builder { 74 | String url; 75 | String mimeType; 76 | String title; 77 | String description; 78 | HashMap file; 79 | 80 | public Builder setUrl(String url) { 81 | this.url = url; 82 | return this; 83 | } 84 | 85 | public Builder setMimeType(String mimeType) { 86 | this.mimeType = mimeType; 87 | return this; 88 | } 89 | 90 | public Builder setTitle(String title) { 91 | this.title = title; 92 | return this; 93 | } 94 | 95 | public Builder setDescription(String description) { 96 | this.description = description; 97 | return this; 98 | } 99 | 100 | public Builder setFile(HashMap file) { 101 | this.file = file; 102 | return this; 103 | } 104 | 105 | public Asset build() { 106 | return new Asset(this); 107 | } 108 | } 109 | 110 | // Parcelable 111 | public int describeContents() { 112 | return 0; 113 | } 114 | 115 | public void writeToParcel(Parcel out, int flags) { 116 | out.writeString(remoteId()); 117 | 118 | out.writeString(createdAt()); 119 | 120 | writeOptionalString(out, updatedAt()); 121 | 122 | out.writeString(url); 123 | 124 | out.writeString(mimeType); 125 | 126 | writeOptionalString(out, title()); 127 | 128 | writeOptionalString(out, description()); 129 | 130 | if (file == null) { 131 | out.writeInt(-1); 132 | } else { 133 | out.writeInt(1); 134 | out.writeSerializable(file); 135 | } 136 | } 137 | 138 | private void writeOptionalString(Parcel out, String s) { 139 | if (s == null) { 140 | out.writeInt(-1); 141 | } else { 142 | out.writeInt(1); 143 | out.writeString(s); 144 | } 145 | } 146 | 147 | public static final Parcelable.Creator CREATOR 148 | = new Parcelable.Creator() { 149 | public Asset createFromParcel(Parcel in) { 150 | return new Asset(in); 151 | } 152 | 153 | public Asset[] newArray(int size) { 154 | return new Asset[size]; 155 | } 156 | }; 157 | 158 | @SuppressWarnings("unchecked") 159 | Asset(Parcel in) { 160 | setRemoteId(in.readString()); 161 | 162 | setCreatedAt(in.readString()); 163 | 164 | if (in.readInt() != -1) { 165 | setUpdatedAt(in.readString()); 166 | } 167 | 168 | this.url = in.readString(); 169 | 170 | this.mimeType = in.readString(); 171 | 172 | if (in.readInt() == -1) { 173 | this.title = null; 174 | } else { 175 | this.title = in.readString(); 176 | } 177 | 178 | if (in.readInt() == -1) { 179 | this.description = null; 180 | } else { 181 | this.description = in.readString(); 182 | } 183 | 184 | if (in.readInt() == -1) { 185 | this.file = null; 186 | } else { 187 | this.file = (HashMap) in.readSerializable(); 188 | } 189 | } 190 | 191 | public static final class Fields extends BaseFields { 192 | public static final String URL = "url"; 193 | 194 | public static final String MIME_TYPE = "mime_type"; 195 | 196 | public static final String TITLE = "title"; 197 | 198 | public static final String DESCRIPTION = "description"; 199 | 200 | public static final String FILE = "file"; 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/AutoEscapeValues.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import android.content.ContentValues; 20 | import java.util.Map; 21 | import java.util.Set; 22 | 23 | import static com.contentful.vault.Sql.escape; 24 | 25 | final class AutoEscapeValues { 26 | private final ContentValues values = new ContentValues(); 27 | 28 | public void put(String key, String value) { 29 | values.put(escape(key), value); 30 | } 31 | 32 | public void put(String key, Byte value) { 33 | values.put(escape(key), value); 34 | } 35 | 36 | public void put(String key, Short value) { 37 | values.put(escape(key), value); 38 | } 39 | 40 | public void put(String key, Integer value) { 41 | values.put(escape(key), value); 42 | } 43 | 44 | public void put(String key, Long value) { 45 | values.put(escape(key), value); 46 | } 47 | 48 | public void put(String key, Float value) { 49 | values.put(escape(key), value); 50 | } 51 | 52 | public void put(String key, Double value) { 53 | values.put(escape(key), value); 54 | } 55 | 56 | public void put(String key, Boolean value) { 57 | values.put(escape(key), value); 58 | } 59 | 60 | public void put(String key, byte[] value) { 61 | values.put(escape(key), value); 62 | } 63 | 64 | public void putNull(String key) { 65 | values.putNull(escape(key)); 66 | } 67 | 68 | public int size() { 69 | return values.size(); 70 | } 71 | 72 | public void remove(String key) { 73 | values.remove(escape(key)); 74 | } 75 | 76 | public void clear() { 77 | values.clear(); 78 | } 79 | 80 | public boolean containsKey(String key) { 81 | return values.containsKey(escape(key)); 82 | } 83 | 84 | public Object get(String key) { 85 | return values.get(escape(key)); 86 | } 87 | 88 | public String getAsString(String key) { 89 | return values.getAsString(escape(key)); 90 | } 91 | 92 | public Long getAsLong(String key) { 93 | return values.getAsLong(escape(key)); 94 | } 95 | 96 | public Integer getAsInteger(String key) { 97 | return values.getAsInteger(escape(key)); 98 | } 99 | 100 | public Short getAsShort(String key) { 101 | return values.getAsShort(escape(key)); 102 | } 103 | 104 | public Byte getAsByte(String key) { 105 | return values.getAsByte(escape(key)); 106 | } 107 | 108 | public Double getAsDouble(String key) { 109 | return values.getAsDouble(escape(key)); 110 | } 111 | 112 | public Float getAsFloat(String key) { 113 | return values.getAsFloat(escape(key)); 114 | } 115 | 116 | public Boolean getAsBoolean(String key) { 117 | return values.getAsBoolean(escape(key)); 118 | } 119 | 120 | public byte[] getAsByteArray(String key) { 121 | return values.getAsByteArray(escape(key)); 122 | } 123 | 124 | public Set> valueSet() { 125 | return values.valueSet(); 126 | } 127 | 128 | public Set keySet() { 129 | return values.keySet(); 130 | } 131 | 132 | public ContentValues get() { 133 | return values; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/BaseFields.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | public abstract class BaseFields { 20 | public static final String REMOTE_ID = "remote_id"; 21 | 22 | public static final String CREATED_AT = "created_at"; 23 | 24 | public static final String UPDATED_AT = "updated_at"; 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/BlobUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import java.io.ByteArrayInputStream; 20 | import java.io.ByteArrayOutputStream; 21 | import java.io.IOException; 22 | import java.io.ObjectInputStream; 23 | import java.io.ObjectOutputStream; 24 | import java.io.Serializable; 25 | 26 | final class BlobUtils { 27 | @SuppressWarnings("unchecked") 28 | static T fromBlob(Class clazz, byte[] blob) 29 | throws IOException, ClassNotFoundException { 30 | T result = null; 31 | ObjectInputStream ois = null; 32 | try { 33 | ByteArrayInputStream bos = new ByteArrayInputStream(blob); 34 | ois = new ObjectInputStream(bos); 35 | result = (T) ois.readObject(); 36 | } finally { 37 | if (ois != null) { 38 | try { 39 | ois.close(); 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | } 45 | return result; 46 | } 47 | 48 | static byte[] toBlob(Serializable object) throws IOException { 49 | ObjectOutputStream oos = null; 50 | ByteArrayOutputStream bos; 51 | byte[] result = null; 52 | try { 53 | bos = new ByteArrayOutputStream(); 54 | oos = new ObjectOutputStream(bos); 55 | oos.writeObject(object); 56 | result = bos.toByteArray(); 57 | } finally { 58 | if (oos != null) { 59 | try { 60 | oos.close(); 61 | } catch (IOException e) { 62 | e.printStackTrace(); 63 | } 64 | } 65 | } 66 | return result; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | public final class Constants { 20 | private Constants() { 21 | throw new AssertionError(); 22 | } 23 | 24 | public static final String SUFFIX_FIELDS = "$Fields"; 25 | 26 | public static final String SUFFIX_MODEL = "$$ModelHelper"; 27 | 28 | public static final String SUFFIX_SPACE = "$$SpaceHelper"; 29 | } 30 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/ContentType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.Target; 21 | 22 | import static java.lang.annotation.ElementType.TYPE; 23 | import static java.lang.annotation.RetentionPolicy.CLASS; 24 | 25 | @Target(TYPE) 26 | @Retention(CLASS) 27 | public @interface ContentType { 28 | /** Remote ID */ 29 | String value(); 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/FetchQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import java.util.List; 20 | 21 | public final class FetchQuery extends AbsQuery> { 22 | FetchQuery(Class type, Vault vault) { 23 | super(type, vault); 24 | } 25 | 26 | List resolveAll(boolean resolveLinks, String locale) { 27 | if (locale == null) { 28 | locale = vault().getSqliteHelper().getSpaceHelper().getDefaultLocale(); 29 | } 30 | return new QueryResolver<>(this).all(resolveLinks, locale); 31 | } 32 | 33 | T resolveFirst(boolean resolveLinks, String locale) { 34 | if (locale == null) { 35 | locale = vault().getSqliteHelper().getSpaceHelper().getDefaultLocale(); 36 | } 37 | List all = limit(1).resolveAll(resolveLinks, locale); 38 | if (all.isEmpty()) { 39 | return null; 40 | } 41 | return all.get(0); 42 | } 43 | 44 | public List all() { 45 | return all(null); 46 | } 47 | 48 | public List all(String locale) { 49 | return resolveAll(true, locale); 50 | } 51 | 52 | public T first() { 53 | return first(null); 54 | } 55 | 56 | public T first(String locale) { 57 | return resolveFirst(true, locale); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/Field.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.Target; 21 | 22 | import static java.lang.annotation.ElementType.FIELD; 23 | import static java.lang.annotation.RetentionPolicy.CLASS; 24 | 25 | @Target(FIELD) 26 | @Retention(CLASS) 27 | public @interface Field { 28 | /** Remote ID. Leave this blank in order to use the name of the annotated field as the ID. */ 29 | String value() default ""; 30 | } 31 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/FieldMeta.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import javax.lang.model.type.TypeMirror; 20 | 21 | public final class FieldMeta { 22 | private final String id; 23 | 24 | private final String name; 25 | 26 | private final TypeMirror type; 27 | 28 | private final String sqliteType; 29 | 30 | private final String linkType; 31 | 32 | private final String arrayType; 33 | 34 | FieldMeta(Builder builder) { 35 | this.id = builder.id; 36 | this.name = builder.name; 37 | this.type = builder.type; 38 | this.sqliteType = builder.sqliteType; 39 | this.linkType = builder.linkType; 40 | this.arrayType = builder.arrayType; 41 | } 42 | 43 | public String id() { 44 | return id; 45 | } 46 | 47 | public String name() { 48 | return name; 49 | } 50 | 51 | public TypeMirror type() { 52 | return type; 53 | } 54 | 55 | public String sqliteType() { 56 | return sqliteType; 57 | } 58 | 59 | public String linkType() { 60 | return linkType; 61 | } 62 | 63 | public String arrayType() { 64 | return arrayType; 65 | } 66 | 67 | public boolean isLink() { 68 | return linkType != null; 69 | } 70 | 71 | public boolean isArray() { 72 | return arrayType != null; 73 | } 74 | 75 | public boolean isArrayOfSymbols() { 76 | return isArray() && String.class.getName().equals(arrayType); 77 | } 78 | 79 | public boolean isArrayOfLinks() { 80 | return isArray() && !isArrayOfSymbols(); 81 | } 82 | 83 | @Override public boolean equals(Object o) { 84 | if (this == o) return true; 85 | if (!(o instanceof FieldMeta)) return false; 86 | 87 | FieldMeta fieldMeta = (FieldMeta) o; 88 | 89 | return id.equals(fieldMeta.id); 90 | } 91 | 92 | @Override public int hashCode() { 93 | return id.hashCode(); 94 | } 95 | 96 | public static class Builder { 97 | String id; 98 | String name; 99 | TypeMirror type; 100 | String sqliteType; 101 | String linkType; 102 | String arrayType; 103 | 104 | public Builder setId(String id) { 105 | this.id = id; 106 | return this; 107 | } 108 | 109 | public Builder setName(String name) { 110 | this.name = name; 111 | return this; 112 | } 113 | 114 | public Builder setType(TypeMirror type) { 115 | this.type = type; 116 | return this; 117 | } 118 | 119 | public Builder setSqliteType(String sqliteType) { 120 | this.sqliteType = sqliteType; 121 | return this; 122 | } 123 | 124 | public Builder setLinkType(String linkType) { 125 | this.linkType = linkType; 126 | return this; 127 | } 128 | 129 | public Builder setArrayType(String arrayType) { 130 | this.arrayType = arrayType; 131 | return this; 132 | } 133 | 134 | public FieldMeta build() { 135 | return new FieldMeta(this); 136 | } 137 | } 138 | 139 | public static Builder builder() { 140 | return new Builder(); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/Link.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | final class Link { 20 | private final String parent; 21 | 22 | private final String child; 23 | 24 | private final String fieldId; 25 | 26 | private final String childContentType; 27 | 28 | Link(String parent, String child, String fieldId, String childContentType) { 29 | this.parent = parent; 30 | this.child = child; 31 | this.fieldId = fieldId; 32 | this.childContentType = childContentType; 33 | } 34 | 35 | public String parent() { 36 | return parent; 37 | } 38 | 39 | public String child() { 40 | return child; 41 | } 42 | 43 | public String fieldId() { 44 | return fieldId; 45 | } 46 | 47 | public String childContentType() { 48 | return childContentType; 49 | } 50 | 51 | public boolean isAsset() { 52 | return childContentType == null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/ModelHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import android.database.Cursor; 20 | import java.io.IOException; 21 | import java.io.Serializable; 22 | import java.util.List; 23 | 24 | public abstract class ModelHelper { 25 | public abstract String getTableName(); 26 | 27 | public abstract List getFields(); 28 | 29 | public abstract List getCreateStatements(SpaceHelper spaceHelper); 30 | 31 | public abstract T fromCursor(Cursor cursor); 32 | 33 | protected abstract boolean setField(T resource, String name, Object value); 34 | 35 | protected final E fieldFromBlob(Class clazz, Cursor cursor, 36 | int columnIndex) { 37 | byte[] blob = cursor.getBlob(columnIndex); 38 | if (blob == null || blob.length == 0) { 39 | return null; 40 | } 41 | E result = null; 42 | Exception exception = null; 43 | try { 44 | result = BlobUtils.fromBlob(clazz, blob); 45 | } catch (IOException | ClassNotFoundException e) { 46 | exception = e; 47 | } 48 | if (exception != null) { 49 | throw new RuntimeException(String.format("Failed creating BLOB from column %d of %s.", 50 | columnIndex, getTableName()), exception); 51 | } 52 | return result; 53 | } 54 | 55 | protected final void setContentType(T resource, String type) { 56 | resource.setContentType(type); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/ObserveQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import java.util.List; 20 | 21 | import io.reactivex.rxjava3.annotations.NonNull; 22 | import io.reactivex.rxjava3.core.BackpressureStrategy; 23 | import io.reactivex.rxjava3.core.Flowable; 24 | import io.reactivex.rxjava3.core.FlowableEmitter; 25 | import io.reactivex.rxjava3.core.FlowableOnSubscribe; 26 | 27 | public final class ObserveQuery extends AbsQuery> { 28 | ObserveQuery(Class type, Vault vault) { 29 | super(type, vault); 30 | } 31 | 32 | public Flowable all() { 33 | return all(null); 34 | } 35 | 36 | public Flowable all(String locale) { 37 | return Flowable.create(new AllOnSubscribe(this, locale), BackpressureStrategy.BUFFER); 38 | } 39 | 40 | static class AllOnSubscribe implements FlowableOnSubscribe { 41 | private final ObserveQuery query; 42 | private final String locale; 43 | 44 | public AllOnSubscribe(ObserveQuery query, String locale) { 45 | this.query = query; 46 | this.locale = locale; 47 | } 48 | 49 | @Override 50 | public void subscribe(@NonNull FlowableEmitter emitter) { 51 | try { 52 | FetchQuery fetchQuery = query.vault().fetch(query.type()); 53 | fetchQuery.setParams(query.params()); 54 | List items = fetchQuery.all(locale); 55 | for (T item : items) { 56 | if (emitter.isCancelled()) { 57 | return; 58 | } 59 | emitter.onNext(item); 60 | } 61 | } catch (Throwable t) { 62 | if (!emitter.isCancelled()) { 63 | emitter.onError(t); 64 | } 65 | return; 66 | } 67 | if (!emitter.isCancelled()) { 68 | emitter.onComplete(); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/QueryResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import android.database.Cursor; 20 | import java.util.ArrayList; 21 | import java.util.HashMap; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | import static android.text.TextUtils.join; 26 | import static com.contentful.vault.Sql.TABLE_ASSETS; 27 | import static com.contentful.vault.Sql.escape; 28 | import static com.contentful.vault.Sql.localizeName; 29 | 30 | final class QueryResolver { 31 | private final AbsQuery query; 32 | 33 | private final Vault vault; 34 | 35 | private final Map assets = new HashMap<>(); 36 | 37 | private final Map entries = new HashMap<>(); 38 | 39 | QueryResolver(AbsQuery query) { 40 | this.query = query; 41 | this.vault = query.vault(); 42 | } 43 | 44 | List all(boolean resolveLinks, String locale) { 45 | Cursor cursor = cursorFromQuery(query, locale); 46 | List result = new ArrayList(); 47 | try { 48 | if (cursor.moveToFirst()) { 49 | Map cache = cacheForType(query.type()); 50 | do { 51 | T item = vault.getSqliteHelper().fromCursor(query.type(), cursor); 52 | if (item == null) { 53 | continue; 54 | } 55 | result.add(item); 56 | cache.put(item.remoteId(), item); 57 | } while (cursor.moveToNext()); 58 | } 59 | } finally { 60 | cursor.close(); 61 | } 62 | 63 | if (resolveLinks && query.type() != Asset.class && !result.isEmpty()) { 64 | resolveLinks(result, locale); 65 | } 66 | 67 | return result; 68 | } 69 | 70 | private Map cacheForType(Class type) { 71 | if (type == Asset.class) { 72 | return assets; 73 | } 74 | return entries; 75 | } 76 | 77 | private void resolveLinks(List resources, String locale) { 78 | LinkResolver resolver = new LinkResolver(query, assets, entries); 79 | for (T resource : resources) { 80 | resolver.resolveLinks(resource, helperForEntry(resource).getFields(), locale); 81 | } 82 | } 83 | 84 | private ModelHelper helperForEntry(T resource) { 85 | SpaceHelper spaceHelper = vault.getSqliteHelper().getSpaceHelper(); 86 | Class modelType = spaceHelper.getTypes().get(resource.contentType()); 87 | return spaceHelper.getModels().get(modelType); 88 | } 89 | 90 | private Cursor cursorFromQuery(AbsQuery query, String locale) { 91 | String[] orderArray = query.params().order(); 92 | String order = null; 93 | if (orderArray != null && orderArray.length > 0) { 94 | order = join(", ", orderArray); 95 | } 96 | String tableName; 97 | if (query.type() == Asset.class) { 98 | tableName = TABLE_ASSETS; 99 | } else { 100 | tableName = query.vault() 101 | .getSqliteHelper() 102 | .getSpaceHelper() 103 | .getModels() 104 | .get(query.type()) 105 | .getTableName(); 106 | } 107 | return query.vault().getReadableDatabase().query( 108 | escape(localizeName(tableName, locale)), 109 | null, // columns 110 | query.params().selection(), // selection 111 | query.params().selectionArgs(), // selectionArgs 112 | null, // groupBy 113 | null, // having 114 | order, // order 115 | query.params().limit()); // limit 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/Resource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import org.apache.commons.lang3.StringUtils; 20 | 21 | public abstract class Resource { 22 | String remoteId; 23 | 24 | String createdAt; 25 | 26 | String updatedAt; 27 | 28 | String contentType; 29 | 30 | public String remoteId() { 31 | return remoteId; 32 | } 33 | 34 | public String createdAt() { 35 | return createdAt; 36 | } 37 | 38 | public String updatedAt() { 39 | return updatedAt; 40 | } 41 | 42 | void setRemoteId(String remoteId) { 43 | this.remoteId = remoteId; 44 | } 45 | 46 | void setCreatedAt(String createdAt) { 47 | this.createdAt = createdAt; 48 | } 49 | 50 | void setUpdatedAt(String updatedAt) { 51 | this.updatedAt = updatedAt; 52 | } 53 | 54 | void setContentType(String contentType) { 55 | this.contentType = contentType; 56 | } 57 | 58 | String contentType() { 59 | return contentType; 60 | } 61 | 62 | String getIdPrefix() { 63 | return null; 64 | } 65 | 66 | @Override public boolean equals(Object o) { 67 | if (this == o) return true; 68 | if (!(o instanceof Resource)) return false; 69 | 70 | Resource resource = (Resource) o; 71 | String prefix = StringUtils.defaultString(getIdPrefix(), ""); 72 | if (!prefix.equals(StringUtils.defaultString(resource.getIdPrefix(), ""))) return false; 73 | return (prefix + remoteId()).equals(prefix + resource.remoteId()); 74 | } 75 | 76 | @Override public int hashCode() { 77 | return (StringUtils.defaultString(getIdPrefix(), "") + remoteId).hashCode(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/Space.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.Target; 21 | 22 | import static java.lang.annotation.ElementType.TYPE; 23 | import static java.lang.annotation.RetentionPolicy.CLASS; 24 | 25 | @Target(TYPE) 26 | @Retention(CLASS) 27 | public @interface Space { 28 | /** Remote ID */ 29 | String value(); 30 | 31 | /** Supported {@link Resource} models. */ 32 | Class[] models(); 33 | 34 | /** 35 | * Version of the database. Increasing this value will trigger a migration. 36 | * WARNING: Migrations invalidate any pre-existing data. 37 | */ 38 | int dbVersion() default 1; 39 | 40 | /** 41 | * File path under the application's 'assets' folder pointing to an existing Vault database file. 42 | * This is used for pre-populating the database with static content prior to initial sync. 43 | * The first time the database file is created if this property is not blank Vault will attempt 44 | * and copy the contents to its database. 45 | * 46 | * If you wish to apply a {@code copyPath} to an shipped app make sure to increase 47 | * the {@code dbVersion} property. 48 | */ 49 | String copyPath() default ""; 50 | 51 | /** Array of locale codes. */ 52 | String[] locales(); 53 | } 54 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/SpaceHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | public abstract class SpaceHelper { 23 | public abstract String getDatabaseName(); 24 | 25 | public abstract int getDatabaseVersion(); 26 | 27 | public abstract Map, ModelHelper> getModels(); 28 | 29 | public abstract Map> getTypes(); 30 | 31 | public abstract String getCopyPath(); 32 | 33 | public abstract String getSpaceId(); 34 | 35 | public abstract List getLocales(); 36 | 37 | public final String getDefaultLocale() { 38 | return getLocales().get(0); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/Sql.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import java.util.Arrays; 20 | import java.util.List; 21 | import org.apache.commons.lang3.StringUtils; 22 | 23 | import static com.contentful.vault.BaseFields.CREATED_AT; 24 | import static com.contentful.vault.BaseFields.REMOTE_ID; 25 | import static com.contentful.vault.BaseFields.UPDATED_AT; 26 | 27 | public final class Sql { 28 | private Sql() { 29 | throw new AssertionError(); 30 | } 31 | 32 | public static final String[] RESOURCE_COLUMNS = new String[] { 33 | declareField(REMOTE_ID, "STRING", false, " UNIQUE"), 34 | declareField(CREATED_AT, "STRING", false, null), 35 | declareField(UPDATED_AT, "STRING", true, null), 36 | }; 37 | 38 | static final String TABLE_ENTRY_TYPES = "entry_types"; 39 | static final String TABLE_SYNC_INFO = "sync_info"; 40 | static final String TABLE_ASSETS = "assets"; 41 | static final String TABLE_LINKS = "links"; 42 | 43 | static final String CREATE_ENTRY_TYPES = "CREATE TABLE " 44 | + escape(TABLE_ENTRY_TYPES) + " (" 45 | + declareField(REMOTE_ID, "STRING", false, ", ") 46 | + declareField("type_id", "STRING", false, ", ") 47 | + "UNIQUE(" + escape(REMOTE_ID) + ")" 48 | + ");"; 49 | 50 | static final String CREATE_SYNC_INFO = "CREATE TABLE " 51 | + escape(TABLE_SYNC_INFO) + " (" 52 | + declareField("token", "STRING", false, ", ") 53 | + declareField("last_sync_ts", "TIMESTAMP", false, " DEFAULT CURRENT_TIMESTAMP") 54 | + ");"; 55 | 56 | static String createLinks(String locale) { 57 | return "CREATE TABLE " + escape(localizeName(TABLE_LINKS, locale)) + " (" 58 | + declareField("parent", "STRING", false, ", ") 59 | + declareField("child", "STRING", false, ", ") 60 | + declareField("field", "STRING", false, ", ") 61 | + declareField("is_asset", "INT", false, ", ") 62 | + declareField("position", "INT", false, ", ") 63 | + "UNIQUE (" 64 | + escape("parent") + ", " 65 | + escape("child") + ", " 66 | + escape("field") + ", " 67 | + escape("is_asset") + ", " 68 | + escape("position") + ")" 69 | + ");"; 70 | } 71 | 72 | static String createAssets(String locale) { 73 | return "CREATE TABLE " + escape(localizeName(TABLE_ASSETS, locale)) + " (" 74 | + StringUtils.join(RESOURCE_COLUMNS, ", ") + "," 75 | + declareField(Asset.Fields.URL, "STRING", true, ", ") 76 | + declareField(Asset.Fields.MIME_TYPE, "STRING", true, ", ") 77 | + declareField(Asset.Fields.TITLE, "STRING", true, ", ") 78 | + declareField(Asset.Fields.DESCRIPTION, "STRING", true, ", ") 79 | + declareField(Asset.Fields.FILE, "BLOB", true, null) 80 | + ");"; 81 | } 82 | 83 | static final List RESOURCE_COLUMN_INDEXES = Arrays.asList( 84 | REMOTE_ID, 85 | CREATED_AT, 86 | UPDATED_AT); 87 | 88 | static final List ASSET_COLUMN_INDEXES = Arrays.asList( 89 | Asset.Fields.URL, 90 | Asset.Fields.MIME_TYPE, 91 | Asset.Fields.TITLE, 92 | Asset.Fields.DESCRIPTION, 93 | Asset.Fields.FILE); 94 | 95 | static int resourceColumnIndex(String name) { 96 | int i = RESOURCE_COLUMN_INDEXES.indexOf(name); 97 | if (i == -1) { 98 | throw new IllegalArgumentException("Invalid resource column name '" + name + '.'); 99 | } 100 | return i; 101 | } 102 | 103 | static int assetColumnIndex(String name) { 104 | int i = ASSET_COLUMN_INDEXES.indexOf(name); 105 | if (i == -1) { 106 | throw new IllegalArgumentException("Invalid asset column name '" + name + '.'); 107 | } 108 | return RESOURCE_COLUMNS.length + i; 109 | } 110 | 111 | static String escape(String name) { 112 | return String.format("`%s`", name); 113 | } 114 | 115 | static String declareField(String name, String type, boolean nullable, String suffix) { 116 | StringBuilder builder = new StringBuilder(); 117 | builder.append(escape(name)) 118 | .append(" ") 119 | .append(type); 120 | if (!nullable) { 121 | builder.append(" ") 122 | .append("NOT NULL"); 123 | } 124 | if (suffix != null) { 125 | builder.append(suffix); 126 | } 127 | return builder.toString(); 128 | } 129 | 130 | static String localizeName(String name, String locale) { 131 | return String.format("%s$%s", name, locale); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/SyncCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | public abstract class SyncCallback { 20 | private String tag; 21 | 22 | public abstract void onResult(SyncResult result); 23 | 24 | final void setTag(String tag) { 25 | this.tag = tag; 26 | } 27 | 28 | final String getTag() { 29 | return tag; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/SyncConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import com.contentful.java.cda.CDAClient; 20 | 21 | import static com.contentful.vault.build.GeneratedBuildParameters.PROJECT_VERSION; 22 | import static java.text.MessageFormat.format; 23 | 24 | public final class SyncConfig { 25 | private final CDAClient client; 26 | 27 | private final boolean invalidate; 28 | 29 | SyncConfig(Builder builder) { 30 | this.invalidate = builder.invalidate; 31 | 32 | if (builder.client == null) { 33 | if (builder.accessToken == null) { 34 | throw new IllegalStateException("Cannot create a CDA client with no access token. " + 35 | "Please set it."); 36 | } 37 | 38 | if (builder.spaceId == null) { 39 | throw new IllegalStateException("Cannot create a CDA client with no space id. " + 40 | "Please set it."); 41 | } 42 | 43 | this.client = CDAClient 44 | .builder() 45 | .setToken(builder.accessToken) 46 | .setSpace(builder.spaceId) 47 | .setEnvironment(builder.environment) 48 | .setIntegration("Vault", PROJECT_VERSION) 49 | .build(); 50 | } else { 51 | this.client = builder.client; 52 | } 53 | } 54 | 55 | public CDAClient client() { 56 | return client; 57 | } 58 | 59 | public boolean shouldInvalidate() { 60 | return invalidate; 61 | } 62 | 63 | public static Builder builder() { 64 | return new Builder(); 65 | } 66 | 67 | public static class Builder { 68 | 69 | private static final String FIELD_ALREADY_EXISTS = "Do not set {0}, when {1} is already set. " + 70 | "Use either {0} or a previously added {1}."; 71 | 72 | CDAClient client; 73 | boolean invalidate; 74 | String accessToken; 75 | String spaceId; 76 | String environment; 77 | 78 | public Builder setAccessToken(String accessToken) { 79 | if (client != null) { 80 | throw new IllegalStateException(format(FIELD_ALREADY_EXISTS, "access token", "client")); 81 | } 82 | this.accessToken = accessToken; 83 | return this; 84 | } 85 | 86 | public Builder setSpaceId(String spaceId) { 87 | if (client != null) { 88 | throw new IllegalStateException(format(FIELD_ALREADY_EXISTS, "space id", "client")); 89 | } 90 | this.spaceId = spaceId; 91 | return this; 92 | } 93 | 94 | public Builder setEnvironment(String environment) { 95 | if (client != null) { 96 | throw new IllegalStateException(format(FIELD_ALREADY_EXISTS, "environment", "client")); 97 | } 98 | this.environment = environment; 99 | return this; 100 | } 101 | 102 | public Builder setClient(CDAClient client) { 103 | if (accessToken != null) { 104 | throw new IllegalStateException(format(FIELD_ALREADY_EXISTS, "client", "access token")); 105 | } 106 | if (spaceId != null) { 107 | throw new IllegalStateException(format(FIELD_ALREADY_EXISTS, "client", "space id")); 108 | } 109 | 110 | if (environment != null) { 111 | throw new IllegalStateException(format(FIELD_ALREADY_EXISTS, "client", "environment")); 112 | } 113 | 114 | this.client = client; 115 | return this; 116 | } 117 | 118 | public Builder setInvalidate(boolean invalidate) { 119 | this.invalidate = invalidate; 120 | return this; 121 | } 122 | 123 | public SyncConfig build() { 124 | return new SyncConfig(this); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/SyncException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | public class SyncException extends RuntimeException { 20 | 21 | public SyncException(String message) { 22 | super(message); 23 | } 24 | 25 | public SyncException(String message, Throwable cause) { 26 | super(message, cause); 27 | } 28 | 29 | public SyncException(Throwable cause) { 30 | super(cause); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/SyncResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | public final class SyncResult { 20 | private final String spaceId; 21 | 22 | private final Throwable error; 23 | 24 | SyncResult(String spaceId, Throwable error) { 25 | this.spaceId = spaceId; 26 | this.error = error; 27 | } 28 | 29 | public String spaceId() { 30 | return spaceId; 31 | } 32 | 33 | public boolean isSuccessful() { 34 | return error == null; 35 | } 36 | 37 | public Throwable error() { 38 | return error; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/VaultDatabaseExporter.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vault; 2 | 3 | 4 | import android.content.Context; 5 | import android.database.sqlite.SQLiteDatabase; 6 | 7 | import org.apache.commons.io.FileUtils; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.util.concurrent.CountDownLatch; 12 | import java.util.concurrent.Executor; 13 | 14 | import static java.lang.String.format; 15 | import static java.util.Locale.getDefault; 16 | 17 | /** 18 | * This exporter takes a given space and syncs it's Contentful resources to a sqlite database. 19 | */ 20 | public class VaultDatabaseExporter { 21 | boolean successful; 22 | 23 | /** 24 | * Use this method to export Contentful spaces into sqlite3 databases which can be imported later. 25 | * 26 | * @param context Android (Robolectric?) Context for creating the sqlite database. 27 | * @param spaceClass Configured {@link Space} containing the name and the id of the space. 28 | * @param accessToken a CDA access token, used for retrieving the resources. 29 | * @return true in case of success. On error, please read System.err output. 30 | */ 31 | public boolean export(Context context, Class spaceClass, String accessToken, String environment) { 32 | successful = false; 33 | final SpaceHelper helper = crateSpaceHelper(spaceClass); 34 | final String outputPath = createOutputPath(helper); 35 | 36 | final CountDownLatch countDownLatch = new CountDownLatch(1); 37 | 38 | final Vault vault = Vault.with(context, spaceClass); 39 | vault.requestSync( 40 | SyncConfig 41 | .builder() 42 | .setSpaceId(helper.getSpaceId()) 43 | .setAccessToken(accessToken) 44 | .setEnvironment(environment) 45 | .build(), 46 | new SyncCallback() { 47 | @Override public void onResult(SyncResult result) { 48 | try { 49 | successful = saveResultInDatabaseFile(result, vault, outputPath); 50 | } catch (Throwable t) { 51 | t.printStackTrace(System.err); 52 | } finally { 53 | countDownLatch.countDown(); 54 | } 55 | } 56 | }, new Executor() { 57 | @Override public void execute(Runnable runnable) { 58 | runnable.run(); 59 | } 60 | }); 61 | 62 | try { 63 | countDownLatch.await(); 64 | } catch (InterruptedException e) { 65 | e.printStackTrace(System.err); 66 | } 67 | 68 | return successful; 69 | } 70 | 71 | String createOutputPath(SpaceHelper helper) { 72 | String outputPath = "src/main/assets/"; 73 | if (helper.getCopyPath() != null) { 74 | outputPath += helper.getCopyPath(); 75 | if (!new File(outputPath).exists()) { 76 | final String spaceName = getSpaceClassName(helper); 77 | throw new IllegalStateException("Database file does not exist on the filesystem. " + 78 | "Please remove it's annotation from " + spaceName + " and try again."); 79 | } 80 | } else { 81 | // no database name given, so use a default. 82 | outputPath += "initial_seed.db"; 83 | } 84 | 85 | return outputPath; 86 | } 87 | 88 | String getSpaceClassName(SpaceHelper helper) { 89 | return helper.getClass().getCanonicalName().split("\\$")[0]; 90 | } 91 | 92 | SpaceHelper crateSpaceHelper(Class spaceClass) { 93 | final Class clazz; 94 | try { 95 | clazz = Class.forName(spaceClass.getName() + Constants.SUFFIX_SPACE); 96 | } catch (ClassNotFoundException e) { 97 | throw new IllegalStateException("Could not find class", e); 98 | } 99 | 100 | final SpaceHelper helper; 101 | try { 102 | helper = (SpaceHelper) clazz.newInstance(); 103 | } catch (InstantiationException | IllegalAccessException e) { 104 | throw new IllegalStateException("Cannot create a new instance of the space helper.", e); 105 | } 106 | 107 | if (helper == null) { 108 | throw new IllegalStateException("Cannot find SpaceHelper. " + 109 | "Did you use the Vault annotations and rebuild the app?"); 110 | } 111 | 112 | return helper; 113 | } 114 | 115 | boolean saveResultInDatabaseFile(SyncResult result, Vault vault, String dataBaseFilePath) { 116 | boolean successful = result.isSuccessful(); 117 | if (!successful) { 118 | throw new IllegalStateException("Could not return a valid result.", result.error()); 119 | } else { 120 | final File outputDatabase = new File(dataBaseFilePath); 121 | 122 | final SQLiteDatabase readableDatabase = vault.getReadableDatabase(); 123 | System.out.println( 124 | format( 125 | getDefault(), 126 | "Copying from '%s' to '%s'.", 127 | readableDatabase.getPath(), 128 | outputDatabase.getAbsolutePath()) 129 | ); 130 | 131 | try { 132 | FileUtils.copyFile(new File(readableDatabase.getPath()), outputDatabase); 133 | } catch (IOException e) { 134 | e.printStackTrace(System.err); 135 | successful = false; 136 | } 137 | 138 | System.out.println("Copying done."); 139 | } 140 | 141 | return successful; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /core/src/main/java/com/contentful/vault/VaultThreadFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vault; 18 | 19 | import android.os.Process; 20 | import java.util.concurrent.ThreadFactory; 21 | 22 | final class VaultThreadFactory implements ThreadFactory { 23 | @SuppressWarnings("NullableProblems") 24 | @Override 25 | public Thread newThread(Runnable r) { 26 | return new CFThread(r); 27 | } 28 | 29 | private static class CFThread extends Thread { 30 | public CFThread(Runnable target) { 31 | super(target); 32 | } 33 | 34 | @Override public void run() { 35 | Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 36 | super.run(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/templates/com/contentful/vault/build/GeneratedBuildParameters.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vault.build; 2 | 3 | /** 4 | * Generated class containing the project version. 5 | * 6 | * This is generated on build time, so we don't have to fetch the properties on application 7 | * load. 8 | */ 9 | public final class GeneratedBuildParameters { 10 | /** 11 | * Which version of '${project.groupId}' is getting used? 12 | */ 13 | public static final String PROJECT_VERSION = "${project.version}"; 14 | } 15 | -------------------------------------------------------------------------------- /core/src/test/resources/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | jdk: 2 | - oraclejdk8 3 | -------------------------------------------------------------------------------- /last-module/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | vault-parent 5 | com.contentful.vault 6 | 3.2.7-SNAPSHOT 7 | 8 | 4.0.0 9 | 10 | last-module 11 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /proguard-vault.cfg: -------------------------------------------------------------------------------- 1 | # Vault 2 | -keepattributes Signature 3 | -dontwarn javax.lang.model.type.TypeMirror 4 | -keep class com.contentful.vault.** { *; } 5 | -keep class **$$SpaceHelper { *; } 6 | -keep class **$$ModelHelper { *; } 7 | -keep class **$Fields extends com.contentful.vault.BaseFields { *; } 8 | -keep @com.contentful.vault.ContentType class * { *; } 9 | -keep @com.contentful.vault.Space class * { *; } 10 | 11 | # contentful.java 12 | -keep class com.contentful.java.cda.** { *; } 13 | 14 | # RxJava 15 | -dontwarn rx.** 16 | 17 | # OkHttp 18 | -keepattributes *Annotation* 19 | -keep class com.squareup.okhttp.** { *; } 20 | -keep interface com.squareup.okhttp.** { *; } 21 | -dontwarn com.squareup.okhttp.** 22 | 23 | # Retrofit 24 | -dontwarn retrofit.** 25 | -keep class retrofit.** { *; } 26 | -keepclasseswithmembers class * { 27 | @retrofit.http.* ; 28 | } 29 | 30 | # Okio 31 | -keep class sun.misc.Unsafe { *; } 32 | -dontwarn java.nio.file.* 33 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 34 | -dontwarn okio.** 35 | 36 | # Gson 37 | -keepattributes EnclosingMethod 38 | -keep class com.google.gson.stream.** { *; } -------------------------------------------------------------------------------- /tests-integration/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | com.contentful.vault 7 | vault-parent 8 | 3.2.7-SNAPSHOT 9 | 10 | 11 | tests-integration 12 | apk 13 | 14 | 15 | 16 | com.contentful.vault 17 | compiler 18 | ${project.version} 19 | 20 | 21 | sun.jdk 22 | tools 23 | 24 | 25 | 26 | 27 | 28 | com.contentful.vault 29 | core 30 | ${project.version} 31 | 32 | 33 | 34 | com.google.android 35 | android 36 | provided 37 | 38 | 39 | 40 | junit 41 | junit 42 | test 43 | 44 | 45 | 46 | org.robolectric 47 | robolectric 48 | test 49 | 50 | 51 | 52 | com.squareup.okhttp3 53 | mockwebserver 54 | test 55 | 56 | 57 | 58 | com.squareup.okhttp3 59 | okhttp-urlconnection 60 | test 61 | 62 | 63 | 64 | commons-io 65 | commons-io 66 | test 67 | 68 | 69 | 70 | org.mockito 71 | mockito-core 72 | test 73 | 74 | 75 | 76 | com.google.truth 77 | truth 78 | test 79 | 80 | 81 | 82 | io.reactivex.rxjava3 83 | rxjava 84 | test 85 | 86 | 87 | 88 | 89 | 90 | 91 | com.simpligility.maven.plugins 92 | android-maven-plugin 93 | true 94 | 95 | 96 | 97 | org.apache.maven.plugins 98 | maven-deploy-plugin 99 | 100 | true 101 | 102 | 103 | 104 | 105 | org.sonatype.plugins 106 | nexus-staging-maven-plugin 107 | 108 | true 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /tests-integration/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests-integration/src/main/assets/cfexampleapi.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contentful/vault/4f6a5ed4f6c592f4ee68a4fac23c876b173b9291/tests-integration/src/main/assets/cfexampleapi.db -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/AllTheThingsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.vault.Asset; 20 | import com.contentful.vault.Vault; 21 | import com.contentful.vaultintegration.lib.allthethings.AllTheThingsResource; 22 | import com.contentful.vaultintegration.lib.allthethings.AllTheThingsSpace; 23 | 24 | import org.junit.Test; 25 | import org.robolectric.RuntimeEnvironment; 26 | import org.robolectric.annotation.Config; 27 | 28 | import static com.contentful.vault.BaseFields.REMOTE_ID; 29 | import static com.google.common.truth.Truth.assertThat; 30 | import static org.junit.Assert.fail; 31 | 32 | @Config(manifest = "src/main/AndroidManifest.xml", sdk = 23) 33 | public class AllTheThingsTest extends BaseTest { 34 | @Override protected void setupVault() { 35 | vault = Vault.with(RuntimeEnvironment.application, AllTheThingsSpace.class); 36 | } 37 | 38 | @Test public void testAllTheThings() throws Exception { 39 | enqueueSync("allthethings"); 40 | sync(); 41 | checkEntryFoo(); 42 | checkEntryBar(); 43 | } 44 | 45 | @SuppressWarnings("unchecked") 46 | private void checkEntryBar() { 47 | AllTheThingsResource bar = vault.fetch(AllTheThingsResource.class) 48 | .where(REMOTE_ID + " = ?", "4EYJjgMg0oG084iuACY6Ue") 49 | .first(); 50 | 51 | assertThat(bar).isNotNull(); 52 | assertThat(bar.text()).isEqualTo("bar"); 53 | assertThat(bar.number()).isEqualTo(1); 54 | assertThat(bar.decimal()).isEqualTo(2.0); 55 | assertThat(bar.yesno()).isFalse(); 56 | assertThat(bar.dateTime()).isNull(); 57 | assertThat(bar.location()).isNull(); 58 | assertThat(bar.entry()).isNull(); 59 | assertThat(bar.asset()).isNull(); 60 | assertThat(bar.object()).isNull(); 61 | 62 | assertThat(bar.entries()).isNotNull(); 63 | assertThat(bar.entries()).isEmpty(); 64 | 65 | assertThat(bar.assets()).isNotNull(); 66 | assertThat(bar.assets()).isEmpty(); 67 | 68 | assertThat(bar.symbols()).isNotNull(); 69 | assertThat(bar.symbols()).isEmpty(); 70 | } 71 | 72 | @SuppressWarnings("unchecked") 73 | private void checkEntryFoo() { 74 | AllTheThingsResource foo = vault.fetch(AllTheThingsResource.class) 75 | .where(REMOTE_ID + " = ?", "6K1Md1qADuOsoom2UIEKkq") 76 | .first(); 77 | 78 | assertThat(foo).isNotNull(); 79 | assertThat(foo.text()).isEqualTo("foo"); 80 | assertThat(foo.number()).isEqualTo(31337); 81 | assertThat(foo.decimal()).isEqualTo(1.337); 82 | assertThat(foo.yesno()).isTrue(); 83 | assertThat(foo.dateTime()).isEqualTo("2015-07-01"); 84 | 85 | assertThat(foo.location()).isNotNull(); 86 | assertThat(foo.location().get("lat")).isEqualTo(52.52000659999999); 87 | assertThat(foo.location().get("lon")).isEqualTo(13.404953999999975); 88 | 89 | assertThat(foo.entry()).isNotNull(); 90 | assertThat(foo.entry().remoteId()).isEqualTo("4EYJjgMg0oG084iuACY6Ue"); 91 | 92 | assertThat(foo.asset()).isNotNull(); 93 | assertThat(foo.asset().remoteId()).isEqualTo("6Kknr7SqpGWs8kIKwCuQCU"); 94 | 95 | assertThat(foo.object()).isNotNull(); 96 | assertThat(foo.object()).hasSize(2); 97 | assertThat(foo.object()).containsEntry("foo", "bar"); 98 | assertThat(foo.object()).containsEntry("bar", "foo"); 99 | 100 | assertThat(foo.entries()).isNotNull(); 101 | assertThat(foo.entries()).hasSize(1); 102 | assertThat(foo.entries().get(0).remoteId()).isEqualTo("4EYJjgMg0oG084iuACY6Ue"); 103 | 104 | assertThat(foo.assets()).isNotNull(); 105 | assertThat(foo.assets()).hasSize(2); 106 | boolean hasFoo = false, hasBar = false; 107 | for (Asset asset : foo.assets()) { 108 | if ("6Kknr7SqpGWs8kIKwCuQCU".equals(asset.remoteId())) { 109 | hasFoo = true; 110 | } else if ("w4ZPwQ0Cmko2QqyWgSEGy".equals(asset.remoteId())) { 111 | hasBar = true; 112 | } else { 113 | fail(); 114 | } 115 | } 116 | assertThat(hasFoo).isTrue(); 117 | assertThat(hasBar).isTrue(); 118 | 119 | assertThat(foo.symbols()).isNotNull(); 120 | assertThat(foo.symbols()).hasSize(2); 121 | assertThat(foo.symbols()).containsExactly("foo", "bar"); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/ArrayLinks.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration; 2 | 3 | import com.contentful.vault.Vault; 4 | import com.contentful.vaultintegration.lib.arraylinks.MultiLinksSpace; 5 | import com.contentful.vaultintegration.lib.arraylinks.Product; 6 | import com.contentful.vaultintegration.lib.arraylinks.Product$Fields; 7 | import com.contentful.vaultintegration.lib.arraylinks.Shop; 8 | 9 | import org.junit.Test; 10 | import org.robolectric.RuntimeEnvironment; 11 | 12 | import java.util.List; 13 | 14 | import static com.google.common.truth.Truth.assertThat; 15 | 16 | public class ArrayLinks extends BaseTest { 17 | 18 | @Override protected void setupVault() { 19 | vault = Vault.with(RuntimeEnvironment.application, MultiLinksSpace.class); 20 | } 21 | 22 | @Test public void testLinks() throws Exception { 23 | // Initial 24 | enqueueSync("arraylinks"); 25 | sync(); 26 | 27 | // fetch only one 28 | final List all = vault.fetch(Product.class) 29 | .where(Product$Fields.REMOTE_ID + " = ?", "2ZMtY36Lj2M204kesAs4CK") 30 | .all(); 31 | 32 | assertThat(all.size()).isEqualTo(1); 33 | final Product product = all.get(0); 34 | assertThat(product.remoteId().equals("2ZMtY36Lj2M204kesAs4CK")).isTrue(); 35 | 36 | final Shop shop = product.shops().get(0); 37 | assertThat(shop.name()).isEqualTo("Alexa"); 38 | assertThat(shop.products().size()).isEqualTo(6); 39 | assertThat(shop.products().get(3).remoteId()).isEqualTo(product.remoteId()); 40 | 41 | assertThat(shop.products().get(2).shops().size()).isEqualTo(2); 42 | assertThat(shop.products().get(2).shops().get(1).name()).isEqualTo("Rewe"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/ArrayTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.vault.Vault; 20 | import com.contentful.vaultintegration.lib.vault.ArraysResource; 21 | import com.contentful.vaultintegration.lib.vault.VaultSpace; 22 | import java.util.Arrays; 23 | import java.util.List; 24 | import org.junit.Test; 25 | import org.robolectric.RuntimeEnvironment; 26 | 27 | import static com.contentful.vault.BaseFields.REMOTE_ID; 28 | import static com.google.common.truth.Truth.assertThat; 29 | 30 | public class ArrayTest extends BaseTest { 31 | @Override protected void setupVault() { 32 | vault = Vault.with(RuntimeEnvironment.application, VaultSpace.class); 33 | } 34 | 35 | @Test public void testArray() throws Exception { 36 | enqueueSync("vault"); 37 | sync(); 38 | 39 | ArraysResource resource = vault.fetch(ArraysResource.class) 40 | .where(REMOTE_ID + " = ?", "u2L1goyi3eA4W0AKcqEou") 41 | .first(); 42 | 43 | assertThat(resource).isNotNull(); 44 | 45 | assertThat(resource.assets()).hasSize(2); 46 | List ids = Arrays.asList("1yj8f2uFEgGEkuqeoGIQws", "2cMA1o04G42KGoQioOqqUA"); 47 | assertThat(ids).contains(resource.assets().get(0).remoteId()); 48 | assertThat(ids).contains(resource.assets().get(1).remoteId()); 49 | 50 | assertThat(resource.symbols()).isNotNull(); 51 | assertThat(resource.symbols()).containsExactly("a", "b", "c"); 52 | 53 | assertThat(resource.blobs()).isNotNull(); 54 | assertThat(resource.blobs()).hasSize(1); 55 | assertThat(resource.blobs().get(0)).isNotNull(); 56 | } 57 | 58 | @Test public void testEmptyFields() throws Exception { 59 | enqueueSync("vault"); 60 | sync(); 61 | 62 | ArraysResource resource = vault.fetch(ArraysResource.class) 63 | .where(REMOTE_ID + " = ?", "FyFV7zVpMQUG6IIEekeI0") 64 | .first(); 65 | 66 | assertThat(resource).isNotNull(); 67 | assertThat(resource.assets()).isNotNull(); 68 | assertThat(resource.assets()).isEmpty(); 69 | 70 | assertThat(resource.symbols()).isNotNull(); 71 | assertThat(resource.symbols()).isEmpty(); 72 | 73 | assertThat(resource.blobs()).isNotNull(); 74 | assertThat(resource.blobs()).isEmpty(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/BaseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.java.cda.CDAClient; 20 | import com.contentful.vault.SyncCallback; 21 | import com.contentful.vault.SyncConfig; 22 | import com.contentful.vault.SyncResult; 23 | import com.contentful.vault.Vault; 24 | 25 | import org.apache.commons.io.FileUtils; 26 | import org.junit.After; 27 | import org.junit.Before; 28 | import org.junit.runner.RunWith; 29 | import org.robolectric.RobolectricTestRunner; 30 | import org.robolectric.annotation.Config; 31 | 32 | import java.io.File; 33 | import java.io.IOException; 34 | import java.net.URL; 35 | import java.nio.charset.Charset; 36 | import java.util.concurrent.CountDownLatch; 37 | import java.util.concurrent.Executor; 38 | import java.util.logging.LogManager; 39 | 40 | import okhttp3.mockwebserver.MockResponse; 41 | import okhttp3.mockwebserver.MockWebServer; 42 | 43 | import static com.google.common.truth.Truth.assertThat; 44 | 45 | @RunWith(RobolectricTestRunner.class) 46 | @Config(manifest = "src/main/AndroidManifest.xml", sdk = 23) 47 | public abstract class BaseTest { 48 | MockWebServer server; 49 | CDAClient client; 50 | Vault vault; 51 | 52 | @Before public void setUp() throws Exception { 53 | LogManager.getLogManager().reset(); 54 | server = new MockWebServer(); 55 | server.start(); 56 | setupClient(); 57 | setupVault(); 58 | } 59 | 60 | @After public void tearDown() throws Exception { 61 | server.shutdown(); 62 | vault.releaseAll(); 63 | } 64 | 65 | protected abstract void setupVault(); 66 | 67 | protected void setupClient() { 68 | client = CDAClient.builder() 69 | .setSpace("space") 70 | .setToken("token") 71 | .setEndpoint(getServerUrl()) 72 | .build(); 73 | } 74 | 75 | protected String getServerUrl() { 76 | return "http://" + server.getHostName() + ":" + server.getPort(); 77 | } 78 | 79 | protected void enqueue(String fileName) throws IOException { 80 | URL resource = getClass().getClassLoader().getResource(fileName); 81 | if (resource == null) { 82 | throw new IllegalArgumentException("File not found"); 83 | } 84 | server.enqueue(new MockResponse().setResponseCode(200) 85 | .setBody(FileUtils.readFileToString(new File(resource.getFile()), 86 | Charset.defaultCharset()))); 87 | } 88 | 89 | protected void enqueueSync(String space) throws IOException { 90 | enqueueSync(space, false); 91 | } 92 | 93 | protected void enqueueSync(String space, boolean update) throws IOException { 94 | enqueue(space + "/locales.json"); 95 | enqueue(space + "/types.json"); 96 | if (update) { 97 | enqueue(space + "/update.json"); 98 | } else { 99 | enqueue(space + "/initial.json"); 100 | } 101 | } 102 | 103 | protected void sync() throws InterruptedException { 104 | sync(null); 105 | } 106 | 107 | protected void sync(SyncConfig config) throws InterruptedException { 108 | if (config == null) { 109 | config = SyncConfig.builder().setClient(client).build(); 110 | } 111 | 112 | final CountDownLatch latch = new CountDownLatch(1); 113 | 114 | Executor executor = new Executor() { 115 | @Override public void execute(Runnable command) { 116 | command.run(); 117 | } 118 | }; 119 | 120 | final SyncResult[] result = {null}; 121 | SyncCallback callback = new SyncCallback() { 122 | @Override public void onResult(SyncResult r) { 123 | result[0] = r; 124 | latch.countDown(); 125 | } 126 | }; 127 | 128 | vault.requestSync(config, callback, executor); 129 | latch.await(); 130 | 131 | assertThat(result[0]).isNotNull(); 132 | 133 | if (!result[0].isSuccessful()) { 134 | throw (RuntimeException) result[0].error(); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/BlobTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.vault.Vault; 20 | import com.contentful.vaultintegration.lib.vault.BlobResource; 21 | import com.contentful.vaultintegration.lib.vault.VaultSpace; 22 | import java.util.Map; 23 | import org.junit.Test; 24 | import org.robolectric.RuntimeEnvironment; 25 | 26 | import static com.contentful.vault.BaseFields.REMOTE_ID; 27 | import static com.google.common.truth.Truth.assertThat; 28 | import static org.junit.Assert.assertEquals; 29 | 30 | public class BlobTest extends BaseTest { 31 | @Override protected void setupVault() { 32 | vault = Vault.with(RuntimeEnvironment.application, VaultSpace.class); 33 | } 34 | 35 | @SuppressWarnings("unchecked") 36 | @Test public void testBlob() throws Exception { 37 | enqueueSync("vault"); 38 | sync(); 39 | 40 | BlobResource blobResource = vault.fetch(BlobResource.class) 41 | .where(REMOTE_ID + " = ?", "6tOdhkd6Ewekq8M6MQe4GY") 42 | .first(); 43 | 44 | assertThat(blobResource).isNotNull(); 45 | assertThat(blobResource.object()).isNotNull(); 46 | assertThat(blobResource.object()).containsEntry("fieldString", "hello"); 47 | assertThat(blobResource.object()).containsEntry("fieldInteger", 31337.0); 48 | assertThat(blobResource.object()).containsEntry("fieldFloat", 3.1337); 49 | assertThat(blobResource.object()).containsEntry("fieldBoolean", true); 50 | 51 | Object fieldMap = blobResource.object().get("fieldMap"); 52 | assertThat(fieldMap).isNotNull(); 53 | assertThat(fieldMap).isInstanceOf(Map.class); 54 | assertEquals("value", ((Map) fieldMap).get("key")); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/DatabaseCopyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.vault.Asset; 20 | import com.contentful.vault.ContentType; 21 | import com.contentful.vault.Field; 22 | import com.contentful.vault.Resource; 23 | import com.contentful.vault.Space; 24 | import com.contentful.vault.Vault; 25 | import com.contentful.vault.VaultDatabaseExporter; 26 | 27 | import org.junit.Ignore; 28 | import org.junit.Test; 29 | import org.junit.runner.RunWith; 30 | import org.robolectric.RobolectricTestRunner; 31 | import org.robolectric.RuntimeEnvironment; 32 | import org.robolectric.annotation.Config; 33 | 34 | import java.util.List; 35 | 36 | import static com.google.common.truth.Truth.assertThat; 37 | import static org.junit.Assert.assertTrue; 38 | 39 | @RunWith(RobolectricTestRunner.class) 40 | @Config(manifest = "src/main/AndroidManifest.xml") 41 | public class DatabaseCopyTest extends BaseTest { 42 | @Space( 43 | value = "cfexampleapi", 44 | models = Cat.class, 45 | locales = {"en-US", "tlh"}, 46 | copyPath = "cfexampleapi.db" 47 | ) interface Sp { 48 | String TOKEN = "b4c0n73n7fu1"; 49 | String ENVIRONMENT = "environment"; 50 | } 51 | 52 | @ContentType("cat") 53 | static class Cat extends Resource { 54 | @Field String name; 55 | @Field Cat bestFriend; 56 | @Field Asset image; 57 | } 58 | 59 | @Override protected void setupVault() { 60 | vault = Vault.with(RuntimeEnvironment.application, Sp.class); 61 | } 62 | 63 | @Test public void testDatabaseCopy() throws Exception { 64 | List cats = vault.fetch(Cat.class).all(); 65 | assertThat(cats).hasSize(3); 66 | } 67 | 68 | @Ignore("Do not update db on ci.") 69 | @Test 70 | public void testSyncDBtoSqlite() throws Exception { 71 | assertTrue( 72 | new VaultDatabaseExporter() 73 | .export( 74 | RuntimeEnvironment.application, 75 | Sp.class, 76 | Sp.TOKEN, 77 | Sp.ENVIRONMENT) 78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/LinksTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.vault.Vault; 20 | import com.contentful.vaultintegration.lib.links.AssetsContainer; 21 | import com.contentful.vaultintegration.lib.links.LinksSpace; 22 | import java.util.Arrays; 23 | import java.util.List; 24 | import org.junit.Test; 25 | import org.robolectric.RuntimeEnvironment; 26 | 27 | import static com.contentful.vault.BaseFields.REMOTE_ID; 28 | import static com.google.common.truth.Truth.assertThat; 29 | 30 | public class LinksTest extends BaseTest { 31 | @Override protected void setupVault() { 32 | vault = Vault.with(RuntimeEnvironment.application, LinksSpace.class); 33 | } 34 | 35 | @Test public void testLinks() throws Exception { 36 | final String CONTAINER_ID = "34ljO1zKukgIYmcQ64IgOo"; 37 | 38 | // Initial 39 | enqueueSync("links"); 40 | sync(); 41 | 42 | AssetsContainer container = vault.fetch(AssetsContainer.class) 43 | .where(REMOTE_ID + " = ?", CONTAINER_ID) 44 | .first(); 45 | 46 | assertThat(container).isNotNull(); 47 | assertThat(container.assets()).isNotNull(); 48 | assertThat(container.assets()).hasSize(1); 49 | assertThat(container.assets().get(0).remoteId()).isEqualTo("4eHZNAfWq4UaiYIywMiSAy"); 50 | 51 | // Update 52 | enqueueSync("links", true); 53 | sync(); 54 | 55 | container = vault.fetch(AssetsContainer.class) 56 | .where(REMOTE_ID + " = ?", CONTAINER_ID) 57 | .first(); 58 | 59 | assertThat(container).isNotNull(); 60 | assertThat(container.assets()).isNotNull(); 61 | assertThat(container.assets()).hasSize(2); 62 | List ids = Arrays.asList("2lD1fm3UBiwYk0m6CgmiQQ", "65ou5OAxawuQIkOAe2e42c"); 63 | assertThat(ids).contains(container.assets().get(0).remoteId()); 64 | assertThat(ids).contains(container.assets().get(1).remoteId()); 65 | } 66 | 67 | @Test public void testLinkArrayOrder() throws Exception { 68 | final String CONTAINER_ID = "ordered"; 69 | 70 | // Initial 71 | enqueueSync("links"); 72 | sync(); 73 | 74 | AssetsContainer container = vault.fetch(AssetsContainer.class) 75 | .where(REMOTE_ID + " = ?", CONTAINER_ID) 76 | .first(); 77 | 78 | assertThat(container).isNotNull(); 79 | assertThat(container.assets()).hasSize(4); 80 | assertThat(container.assets().get(0).remoteId()).isEqualTo("4eHZNAfWq4UaiYIywMiSAy"); 81 | assertThat(container.assets().get(1).remoteId()).isEqualTo("1g07qGA9BMkucwiUysi8qQ"); 82 | assertThat(container.assets().get(2).remoteId()).isEqualTo("2lD1fm3UBiwYk0m6CgmiQQ"); 83 | assertThat(container.assets().get(3).remoteId()).isEqualTo("65ou5OAxawuQIkOAe2e42c"); 84 | } 85 | 86 | @Test public void testLinkArrayDuplicates() throws Exception { 87 | final String CONTAINER_ID = "duplicates"; 88 | 89 | // Initial 90 | enqueueSync("links"); 91 | sync(); 92 | 93 | AssetsContainer container = vault.fetch(AssetsContainer.class) 94 | .where(REMOTE_ID + " = ?", CONTAINER_ID) 95 | .first(); 96 | 97 | assertThat(container).isNotNull(); 98 | assertThat(container.assets()).hasSize(3); 99 | 100 | String id = "4eHZNAfWq4UaiYIywMiSAy"; 101 | assertThat(container.assets().get(0).remoteId()).isEqualTo(id); 102 | assertThat(container.assets().get(1).remoteId()).isEqualTo(id); 103 | assertThat(container.assets().get(2).remoteId()).isEqualTo(id); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/LocaleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.vault.Vault; 20 | import com.contentful.vaultintegration.lib.demo.Cat; 21 | import com.contentful.vaultintegration.lib.demo.DemoSpace; 22 | import org.junit.Test; 23 | import org.robolectric.RuntimeEnvironment; 24 | 25 | import static com.contentful.vault.BaseFields.REMOTE_ID; 26 | import static com.google.common.truth.Truth.assertThat; 27 | 28 | public class LocaleTest extends BaseTest { 29 | @Override protected void setupVault() { 30 | vault = Vault.with(RuntimeEnvironment.application, DemoSpace.class); 31 | } 32 | 33 | @Test public void testLocale() throws Exception { 34 | enqueueSync("demo"); 35 | sync(); 36 | checkDefaultLocale(); 37 | checkCustomLocale(); 38 | } 39 | 40 | private void checkCustomLocale() { 41 | // Klingon 42 | Cat cat = vault.fetch(Cat.class) 43 | .where(REMOTE_ID + " = ?", "happycat") 44 | .first("tlh"); 45 | 46 | assertThat(cat).isNotNull(); 47 | assertThat(cat.name()).isEqualTo("Quch vIghro'"); 48 | } 49 | 50 | private void checkDefaultLocale() throws Exception { 51 | // Default locale 52 | enqueueSync("demo"); 53 | sync(); 54 | 55 | Cat cat = vault.fetch(Cat.class) 56 | .where(REMOTE_ID + " = ?", "happycat") 57 | .first(); 58 | 59 | assertThat(cat).isNotNull(); 60 | assertThat(cat.name()).isEqualTo("Happy Cat"); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/LocalizedLinksTest.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration; 2 | 3 | import com.contentful.vault.Vault; 4 | import com.contentful.vaultintegration.lib.localizedlinks.Container; 5 | import com.contentful.vaultintegration.lib.localizedlinks.LocalizedLinksSpace; 6 | import org.junit.Test; 7 | import org.robolectric.RuntimeEnvironment; 8 | 9 | import static com.google.common.truth.Truth.assertThat; 10 | 11 | public final class LocalizedLinksTest extends BaseTest { 12 | @Override protected void setupVault() { 13 | vault = Vault.with(RuntimeEnvironment.application, LocalizedLinksSpace.class); 14 | } 15 | 16 | @Test public void localizedLink() throws Exception { 17 | enqueueSync("localizedlinks"); 18 | sync(); 19 | 20 | final Container english = vault.fetch(Container.class).first(); 21 | final Container hebrew = vault.fetch(Container.class).first("he-IL"); 22 | 23 | assertThat(english.one().title()).isEqualTo("hello"); 24 | assertThat(hebrew.one().title()).isEqualTo("shalom"); 25 | } 26 | 27 | @Test public void testNonLocalizedArray() throws Exception { 28 | enqueueSync("localizedlinks"); 29 | sync(); 30 | 31 | final Container english = vault.fetch(Container.class).first(); 32 | final Container hebrew = vault.fetch(Container.class).first("he-IL"); 33 | 34 | assertThat(english.assets()).hasSize(2); 35 | assertThat(hebrew.assets()).hasSize(2); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/ObserveTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.vault.BaseFields; 20 | import com.contentful.vault.SyncResult; 21 | import com.contentful.vault.Vault; 22 | import com.contentful.vaultintegration.lib.demo.Cat; 23 | import com.contentful.vaultintegration.lib.demo.Cat$Fields; 24 | import com.contentful.vaultintegration.lib.demo.DemoSpace; 25 | import java.util.List; 26 | 27 | import io.reactivex.rxjava3.subscribers.TestSubscriber; 28 | import org.junit.Test; 29 | import org.robolectric.RuntimeEnvironment; 30 | 31 | 32 | import static com.google.common.truth.Truth.assertThat; 33 | 34 | public class ObserveTest extends BaseTest { 35 | @Override protected void setupVault() { 36 | vault = Vault.with(RuntimeEnvironment.application, DemoSpace.class); 37 | } 38 | 39 | @Test public void observeQuery() throws Exception { 40 | enqueue("demo/locales.json"); 41 | enqueue("demo/types.json"); 42 | enqueue("demo/initial.json"); 43 | sync(); 44 | 45 | TestSubscriber subscriber = new TestSubscriber<>(); 46 | vault.observe(Cat.class) 47 | .where(BaseFields.REMOTE_ID + " IN(?, ?, ?)", "happycat", "nyancat", "garfield") 48 | .limit(2) 49 | .order(Cat$Fields.UPDATED_AT + " DESC") 50 | .all() 51 | .subscribe(subscriber); 52 | 53 | subscriber.assertNoErrors(); 54 | subscriber.assertComplete(); 55 | 56 | List cats = subscriber.values(); 57 | assertThat(cats).hasSize(2); 58 | assertThat(cats.get(0).updatedAt()).isEqualTo("2013-11-18T15:58:02.018Z"); 59 | assertThat(cats.get(1).updatedAt()).isEqualTo("2013-09-04T09:19:39.027Z"); 60 | } 61 | 62 | @Test public void observeSyncResults() throws Exception { 63 | enqueue("demo/locales.json"); 64 | enqueue("demo/types.json"); 65 | enqueue("demo/initial.json"); 66 | 67 | TestSubscriber subscriber = new TestSubscriber<>(); 68 | Vault.observeSyncResults().subscribe(subscriber); 69 | 70 | subscriber.assertNoValues(); 71 | sync(); 72 | subscriber.assertNoErrors(); 73 | 74 | List events = subscriber.values(); 75 | assertThat(events).hasSize(1); 76 | assertThat(events.get(0).isSuccessful()).isTrue(); 77 | assertThat(events.get(0).spaceId()).isEqualTo("cfexampleapi"); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/ParcelableTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import android.os.Parcel; 20 | import com.contentful.vault.Asset; 21 | import com.contentful.vault.Vault; 22 | import com.contentful.vaultintegration.lib.demo.DemoSpace; 23 | import java.util.List; 24 | import org.junit.Test; 25 | import org.robolectric.RuntimeEnvironment; 26 | 27 | import static com.google.common.truth.Truth.assertThat; 28 | 29 | public class ParcelableTest extends BaseTest { 30 | @Override protected void setupVault() { 31 | vault = Vault.with(RuntimeEnvironment.application, DemoSpace.class); 32 | } 33 | 34 | @Test public void asset() throws Exception { 35 | enqueue("demo/locales.json"); 36 | enqueue("demo/types.json"); 37 | enqueue("demo/initial.json"); 38 | sync(); 39 | 40 | List assets = vault.fetch(Asset.class).all(); 41 | assertThat(assets).isNotEmpty(); 42 | 43 | for (Asset asset : assets) { 44 | checkParcelable(asset); 45 | } 46 | } 47 | 48 | @SuppressWarnings("unchecked") 49 | private void checkParcelable(Asset source) { 50 | Parcel parcel = Parcel.obtain(); 51 | source.writeToParcel(parcel, 0); 52 | parcel.setDataPosition(0); 53 | Asset reconstructed = Asset.CREATOR.createFromParcel(parcel); 54 | assertThat(reconstructed).isNotNull(); 55 | assertThat(source.url()).isEqualTo(reconstructed.url()); 56 | assertThat(source.mimeType()).isEqualTo(reconstructed.mimeType()); 57 | assertThat(source.title()).isEqualTo(reconstructed.title()); 58 | assertThat(source.description()).isEqualTo(reconstructed.description()); 59 | 60 | assertThat((Iterable) source.file().keySet()) 61 | .containsAllIn(reconstructed.file().keySet()); 62 | 63 | assertThat((Iterable) source.file().keySet()).hasSize(reconstructed.file().keySet().size()); 64 | 65 | assertThat((Iterable) source.file().values()) 66 | .containsAllIn(reconstructed.file().values()); 67 | 68 | assertThat((Iterable) source.file().values()).hasSize(reconstructed.file().values().size()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/SqliteEscapeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.vault.Vault; 20 | import com.contentful.vaultintegration.lib.escape.SqliteEscapeModel; 21 | import com.contentful.vaultintegration.lib.escape.SqliteEscapeModel$Fields; 22 | import com.contentful.vaultintegration.lib.escape.SqliteEscapeSpace; 23 | import org.junit.Test; 24 | import org.robolectric.RuntimeEnvironment; 25 | 26 | import static com.google.common.truth.Truth.assertThat; 27 | 28 | public class SqliteEscapeTest extends BaseTest { 29 | @Override protected void setupVault() { 30 | vault = Vault.with(RuntimeEnvironment.application, SqliteEscapeSpace.class); 31 | } 32 | 33 | @Test public void testSync() throws Exception { 34 | enqueueSync("escape"); 35 | sync(); 36 | 37 | SqliteEscapeModel item = vault.fetch(SqliteEscapeModel.class).first(); 38 | assertItem(item); 39 | 40 | item = vault.fetch(SqliteEscapeModel.class) 41 | .where("`" + SqliteEscapeModel$Fields.ORDER + "` = ?", "foo") 42 | .first(); 43 | 44 | assertItem(item); 45 | } 46 | 47 | private void assertItem(SqliteEscapeModel first) { 48 | assertThat(first).isNotNull(); 49 | assertThat(first.order).isEqualTo("foo"); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/SyncBase.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration; 2 | 3 | import com.contentful.vault.Asset; 4 | import com.contentful.vault.Vault; 5 | import com.contentful.vaultintegration.lib.demo.Cat; 6 | import com.contentful.vaultintegration.lib.demo.DemoSpace; 7 | 8 | import org.junit.Ignore; 9 | import org.robolectric.RuntimeEnvironment; 10 | 11 | import java.io.IOException; 12 | import java.util.List; 13 | 14 | import okhttp3.mockwebserver.RecordedRequest; 15 | 16 | import static com.contentful.vault.BaseFields.CREATED_AT; 17 | import static com.contentful.vault.BaseFields.REMOTE_ID; 18 | import static com.google.common.truth.Truth.assertThat; 19 | 20 | @Ignore("Do not test the base test class.") 21 | public class SyncBase extends BaseTest { 22 | 23 | @Override protected void setupVault() { 24 | vault = Vault.with(RuntimeEnvironment.application, DemoSpace.class); 25 | } 26 | 27 | protected void assertSyncUpdate() throws InterruptedException { 28 | assertRequestUpdate(); 29 | assertUpdateAssets(); 30 | assertUpdateEntries(); 31 | } 32 | 33 | protected void assertSyncInitial() throws InterruptedException { 34 | assertRequestInitial(); 35 | assertInitialAssets(); 36 | assertInitialEntries(); 37 | assertSingleLink(); 38 | } 39 | 40 | protected void assertRequestUpdate() throws InterruptedException { 41 | server.takeRequest(); 42 | server.takeRequest(); 43 | RecordedRequest request = server.takeRequest(); 44 | assertThat(request.getPath()).isEqualTo("/spaces/space/environments/master/sync?sync_token=st1"); 45 | } 46 | 47 | protected void assertRequestInitial() throws InterruptedException { 48 | server.takeRequest(); 49 | server.takeRequest(); 50 | RecordedRequest request = server.takeRequest(); 51 | assertThat(request.getPath()).isEqualTo("/spaces/space/environments/master/sync?initial=true"); 52 | } 53 | 54 | protected void enqueueInitial() throws IOException { 55 | enqueue("demo/locales.json"); 56 | enqueue("demo/types.json"); 57 | enqueue("demo/initial.json"); 58 | } 59 | 60 | protected void enqueueUpdate() throws IOException { 61 | enqueue("demo/locales.json"); 62 | enqueue("demo/types.json"); 63 | enqueue("demo/update.json"); 64 | } 65 | 66 | protected void assertSingleLink() { 67 | Cat nyanCat = vault.fetch(Cat.class) 68 | .where(REMOTE_ID + " = ?", "nyancat") 69 | .first(); 70 | 71 | assertThat(nyanCat).isNotNull(); 72 | 73 | Cat happyCat = nyanCat.bestFriend(); 74 | assertThat(happyCat).isNotNull(); 75 | 76 | assertThat(nyanCat).isSameAs(happyCat.bestFriend()); 77 | } 78 | 79 | protected void assertInitialAssets() { 80 | List assets = vault.fetch(Asset.class) 81 | .order(CREATED_AT) 82 | .all(); 83 | 84 | assertThat(assets).isNotNull(); 85 | assertThat(assets).hasSize(4); 86 | 87 | assertThat(assets.get(0).remoteId()).isEqualTo("nyancat"); 88 | assertThat(assets.get(1).remoteId()).isEqualTo("jake"); 89 | assertThat(assets.get(2).remoteId()).isEqualTo("happycat"); 90 | assertThat(assets.get(2).url()).isEqualTo("https://happycat.jpg"); 91 | assertThat(assets.get(3).remoteId()).isEqualTo("1x0xpXu4pSGS4OukSyWGUK"); 92 | 93 | for (Asset asset : assets) { 94 | assertThat(asset.url()).isNotNull(); 95 | assertThat(asset.mimeType()).isNotNull(); 96 | assertThat(asset.remoteId()).isNotNull(); 97 | assertThat(asset.updatedAt()).isNotNull(); 98 | } 99 | } 100 | 101 | protected void assertUpdateAssets() { 102 | List assets = vault.fetch(Asset.class) 103 | .order(CREATED_AT) 104 | .all(); 105 | 106 | assertThat(assets).isNotNull(); 107 | assertThat(assets).hasSize(3); 108 | assertThat(assets.get(0).remoteId()).isEqualTo("nyancat"); 109 | assertThat(assets.get(1).remoteId()).isEqualTo("happycat"); 110 | assertThat(assets.get(1).url()).isEqualTo("https://happiercat.jpg"); 111 | assertThat(assets.get(2).remoteId()).isEqualTo("1x0xpXu4pSGS4OukSyWGUK"); 112 | 113 | for (Asset asset : assets) { 114 | assertThat(asset.url()).isNotNull(); 115 | assertThat(asset.mimeType()).isNotNull(); 116 | assertThat(asset.remoteId()).isNotNull(); 117 | assertThat(asset.updatedAt()).isNotNull(); 118 | } 119 | } 120 | 121 | protected void assertInitialEntries() { 122 | List cats = vault.fetch(Cat.class) 123 | .order(CREATED_AT) 124 | .all(); 125 | 126 | assertThat(cats).isNotNull(); 127 | assertThat(cats).hasSize(3); 128 | 129 | Cat nyanCat = cats.get(0); 130 | assertThat(nyanCat).isNotNull(); 131 | assertThat(nyanCat.remoteId()).isEqualTo("nyancat"); 132 | assertThat(nyanCat.image()).isNotNull(); 133 | 134 | Cat happyCat = cats.get(1); 135 | assertThat(happyCat).isNotNull(); 136 | assertThat(happyCat.remoteId()).isEqualTo("happycat"); 137 | assertThat(happyCat.name()).isEqualTo("Happy Cat"); 138 | assertThat(happyCat.image()).isNotNull(); 139 | 140 | Cat garfield = cats.get(2); 141 | assertThat(garfield).isNotNull(); 142 | assertThat(garfield.remoteId()).isEqualTo("garfield"); 143 | assertThat(garfield.image()).isSameAs(happyCat.image()); 144 | assertThat(garfield.bestFriend()).isNull(); 145 | 146 | assertThat(nyanCat.bestFriend()).isEqualTo(happyCat); 147 | assertThat(happyCat.bestFriend()).isEqualTo(nyanCat); 148 | } 149 | 150 | protected void assertUpdateEntries() { 151 | List cats = vault.fetch(Cat.class) 152 | .order(CREATED_AT) 153 | .all(); 154 | 155 | assertThat(cats).isNotNull(); 156 | assertThat(cats).hasSize(3); 157 | assertThat(cats.get(0).name()).isEqualTo("Happier Cat"); 158 | assertThat(cats.get(0).remoteId()).isEqualTo("happycat"); 159 | assertThat(cats.get(1).remoteId()).isEqualTo("garfield"); 160 | assertThat(cats.get(2).remoteId()).isEqualTo("supercat"); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/SyncPreviewTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.java.cda.CDAClient; 20 | import com.contentful.vault.Vault; 21 | import com.contentful.vaultintegration.lib.demo.DemoSpace; 22 | 23 | import org.junit.Test; 24 | import org.robolectric.RuntimeEnvironment; 25 | 26 | public class SyncPreviewTest extends SyncBase { 27 | 28 | @Override protected void setupVault() { 29 | vault = Vault.with(RuntimeEnvironment.application, DemoSpace.class); 30 | } 31 | 32 | @Override protected void setupClient() { 33 | client = CDAClient.builder() 34 | .setSpace("space") 35 | .setToken("token") 36 | .preview() 37 | .setEndpoint(getServerUrl()) 38 | .build(); 39 | } 40 | 41 | @Test public void testSyncInPreview() throws Exception { 42 | enqueue("demo/locales.json"); 43 | enqueue("demo/types.json"); 44 | enqueue("demo/initial.json"); 45 | 46 | sync(); 47 | 48 | assertSyncInitial(); 49 | } 50 | 51 | @Test 52 | public void testSyncInPreviewNotInitialDoesInitial() throws Exception { 53 | enqueue("demo/locales.json"); 54 | enqueue("demo/types.json"); 55 | enqueue("demo/initial.json"); 56 | 57 | sync(); 58 | assertSyncInitial(); 59 | 60 | enqueue("demo/locales.json"); 61 | enqueue("demo/types.json"); 62 | enqueue("demo/initial.json"); 63 | 64 | sync(); 65 | assertSyncInitial(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/SyncTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.java.cda.CDAClient; 20 | import com.contentful.vault.Asset; 21 | import com.contentful.vault.SyncConfig; 22 | 23 | import org.junit.Test; 24 | 25 | import java.util.List; 26 | 27 | import okhttp3.mockwebserver.RecordedRequest; 28 | 29 | import static com.contentful.vault.BaseFields.CREATED_AT; 30 | import static com.google.common.truth.Truth.assertThat; 31 | 32 | public class SyncTest extends SyncBase { 33 | 34 | @Test public void testAssetFallback() throws Exception { 35 | enqueue("assets/locales.json"); 36 | enqueue("assets/types.json"); 37 | enqueue("assets/initial.json"); 38 | sync(); 39 | 40 | server.takeRequest(); 41 | server.takeRequest(); 42 | RecordedRequest request = server.takeRequest(); 43 | assertThat(request.getPath()).isEqualTo("/spaces/space/environments/master/sync?initial=true"); 44 | } 45 | 46 | @Test public void testAssetsInDraft() throws Exception { 47 | enqueue("assets/locales.json"); 48 | enqueue("assets/types.json"); 49 | enqueue("assets/empty.json"); 50 | sync(); 51 | 52 | server.takeRequest(); // ignore locales request 53 | server.takeRequest(); // ignore content types request 54 | RecordedRequest request = server.takeRequest(); // analyse empty asset response 55 | assertThat(request.getPath()).isEqualTo("/spaces/space/environments/master/sync?initial=true"); 56 | 57 | 58 | List assets = vault.fetch(Asset.class).all(); 59 | 60 | assertThat(assets).isNotNull(); 61 | assertThat(assets).hasSize(1); 62 | 63 | Asset asset = assets.get(0); 64 | assertThat(asset).isNotNull(); 65 | assertThat(asset.file()).isNull(); 66 | } 67 | 68 | @Test public void testSync() throws Exception { 69 | // Initial 70 | enqueueInitial(); 71 | sync(); 72 | assertSyncInitial(); 73 | 74 | // Update 75 | enqueueUpdate(); 76 | sync(); 77 | assertSyncUpdate(); 78 | } 79 | 80 | @Test public void testSyncInvalidate() throws Exception { 81 | // Initial 82 | enqueueInitial(); 83 | sync(); 84 | assertSyncInitial(); 85 | 86 | // Initial (invalidate) 87 | enqueueInitial(); 88 | sync(SyncConfig.builder().setClient(client).setInvalidate(true).build()); 89 | assertSyncInitial(); 90 | } 91 | 92 | @Test public void testAssetMetadata() throws Exception { 93 | enqueueInitial(); 94 | sync(); 95 | 96 | List assets = vault.fetch(Asset.class) 97 | .order(CREATED_AT) 98 | .all(); 99 | 100 | assertThat(assets).isNotNull(); 101 | assertThat(assets).hasSize(4); 102 | 103 | assertThat(assets.get(0).title()).isEqualTo("Nyan Cat"); 104 | assertThat(assets.get(0).description()).isNull(); 105 | assertThat(assets.get(0).file()).hasSize(4); 106 | 107 | assertThat(assets.get(1).title()).isEqualTo("Jake"); 108 | assertThat(assets.get(1).description()).isNull(); 109 | assertThat(assets.get(1).file()).hasSize(4); 110 | 111 | assertThat(assets.get(2).title()).isEqualTo("Happy Cat"); 112 | assertThat(assets.get(2).description()).isNull(); 113 | assertThat(assets.get(2).file()).hasSize(4); 114 | 115 | assertThat(assets.get(3).title()).isEqualTo("Doge"); 116 | assertThat(assets.get(3).description()).isEqualTo("nice picture"); 117 | assertThat(assets.get(3).file()).hasSize(4); 118 | } 119 | 120 | @Test 121 | public void syncingOnEnvironmentsWorks() throws Throwable { 122 | enqueue("assets/locales.json"); 123 | enqueue("assets/types.json"); 124 | enqueue("assets/initial.json"); 125 | 126 | final CDAClient localClient = CDAClient.builder() 127 | .setSpace("space") 128 | .setToken("token") 129 | .setEnvironment("environment") 130 | .setEndpoint(getServerUrl()) // only used for testing: leave blank if not white labeling 131 | .build(); 132 | 133 | final SyncConfig config = new SyncConfig.Builder().setClient(localClient).build(); 134 | 135 | sync(config); 136 | 137 | RecordedRequest request = server.takeRequest(); 138 | assertThat(request.getPath()).startsWith("/spaces/space/environments/environment/locales"); 139 | 140 | request = server.takeRequest(); 141 | assertThat(request.getPath()).startsWith("/spaces/space/environments/environment/content_types"); 142 | 143 | request = server.takeRequest(); 144 | assertThat(request.getPath()).startsWith("/spaces/space/environments/environment/sync"); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/UpgradeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration; 18 | 19 | import com.contentful.vault.Space; 20 | import com.contentful.vault.Vault; 21 | import com.contentful.vaultintegration.lib.demo.Cat; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.robolectric.RobolectricTestRunner; 25 | import org.robolectric.RuntimeEnvironment; 26 | import org.robolectric.annotation.Config; 27 | 28 | @RunWith(RobolectricTestRunner.class) 29 | @Config(manifest = "src/main/AndroidManifest.xml") 30 | public class UpgradeTest extends BaseTest { 31 | @Space( 32 | value = "cfexampleapi", 33 | models = Cat.class, 34 | locales = "en-US" 35 | ) 36 | static class Sp1 { } 37 | 38 | @Space( 39 | value = "cfexampleapi", 40 | models = Cat.class, 41 | locales = "en-US", 42 | dbVersion = 2 43 | ) 44 | static class Sp2 { } 45 | 46 | @Override protected void setupVault() { 47 | vault = Vault.with(RuntimeEnvironment.application, Sp1.class); 48 | } 49 | 50 | @Test public void testUpgrade() throws Exception { 51 | Vault v = vault; 52 | v.getReadableDatabase(); 53 | v.releaseAll(); 54 | v = Vault.with(RuntimeEnvironment.application, Sp2.class); 55 | v.getReadableDatabase(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/VaultTest.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration; 2 | 3 | import com.contentful.java.cda.CDAClient; 4 | import com.contentful.vault.SyncConfig; 5 | import com.contentful.vault.Vault; 6 | import com.contentful.vaultintegration.lib.demo.DemoSpace; 7 | 8 | import org.junit.Test; 9 | import org.robolectric.RuntimeEnvironment; 10 | 11 | import static com.google.common.truth.Truth.assertThat; 12 | import static org.junit.Assert.fail; 13 | 14 | public class VaultTest extends BaseTest { 15 | @Override protected void setupVault() { 16 | vault = Vault.with(RuntimeEnvironment.application, DemoSpace.class); 17 | } 18 | 19 | @Test public void failsInvalidSpaceClass() throws Exception { 20 | try { 21 | Vault.with(RuntimeEnvironment.application, Object.class); 22 | fail(); 23 | } catch (RuntimeException e) { 24 | assertThat(e.getMessage()).isEqualTo( 25 | "Cannot find generated class for space: java.lang.Object"); 26 | } 27 | } 28 | 29 | @Test(expected = IllegalStateException.class) 30 | public void failsIfRequestingToSyncAndNothingIsSet() { 31 | SyncConfig 32 | .builder() 33 | .build(); 34 | } 35 | 36 | @Test(expected = IllegalStateException.class) 37 | public void failsIfRequestingToSyncAndOnlyAccessTokenSet() { 38 | SyncConfig 39 | .builder() 40 | .setAccessToken("foo") 41 | .build(); 42 | } 43 | 44 | @Test(expected = IllegalStateException.class) 45 | public void failsIfRequestingToSyncAndOnlySpaceIdSet() { 46 | SyncConfig 47 | .builder() 48 | .setSpaceId("foo") 49 | .build(); 50 | } 51 | 52 | @Test(expected = IllegalStateException.class) 53 | public void failsIfRequestingToSyncAndOnlyEnvironmentSet() { 54 | SyncConfig 55 | .builder() 56 | .setEnvironment("foo") 57 | .build(); 58 | } 59 | @Test(expected = IllegalStateException.class) 60 | public void failsIfRequestingToSyncAndAccessTokenAndClientSet() { 61 | SyncConfig 62 | .builder() 63 | .setAccessToken("foo") 64 | .setClient(null) 65 | .build(); 66 | } 67 | 68 | @Test(expected = IllegalStateException.class) 69 | public void failsIfRequestingToSyncAndSpaceIdAndClientSet() { 70 | SyncConfig 71 | .builder() 72 | .setSpaceId("foo") 73 | .setClient(null) 74 | .build(); 75 | } 76 | 77 | @Test(expected = IllegalStateException.class) 78 | public void failsIfRequestingToSyncAndEnvironmentAndClientSet() { 79 | SyncConfig 80 | .builder() 81 | .setEnvironment("foo") 82 | .setClient(null) 83 | .build(); 84 | } 85 | 86 | @Test 87 | public void createsACustomCDAClient() { 88 | final SyncConfig syncConfig = SyncConfig 89 | .builder() 90 | .setAccessToken("foo") 91 | .setSpaceId("bar") 92 | .setEnvironment("environment") 93 | .build(); 94 | 95 | final CDAClient client = syncConfig.client(); 96 | assertThat(client).isNotNull(); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/allthethings/AllTheThingsResource.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.allthethings; 2 | 3 | import com.contentful.vault.Asset; 4 | import com.contentful.vault.ContentType; 5 | import com.contentful.vault.Field; 6 | import com.contentful.vault.Resource; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | @ContentType("2585ClSxW8OeuMEoIiKW4i") 11 | public class AllTheThingsResource extends Resource { 12 | @Field String text; 13 | 14 | @Field Integer number; 15 | 16 | @Field Double decimal; 17 | 18 | @Field Boolean yesno; 19 | 20 | @Field String dateTime; 21 | 22 | @Field Map location; 23 | 24 | @Field AllTheThingsResource entry; 25 | 26 | @Field Asset asset; 27 | 28 | @Field Map object; 29 | 30 | @Field List entries; 31 | 32 | @Field List assets; 33 | 34 | @Field List symbols; 35 | 36 | public String text() { 37 | return text; 38 | } 39 | 40 | public Integer number() { 41 | return number; 42 | } 43 | 44 | public Double decimal() { 45 | return decimal; 46 | } 47 | 48 | public Boolean yesno() { 49 | return yesno; 50 | } 51 | 52 | public String dateTime() { 53 | return dateTime; 54 | } 55 | 56 | public Map location() { 57 | return location; 58 | } 59 | 60 | public AllTheThingsResource entry() { 61 | return entry; 62 | } 63 | 64 | public Asset asset() { 65 | return asset; 66 | } 67 | 68 | public Map object() { 69 | return object; 70 | } 71 | 72 | public List entries() { 73 | return entries; 74 | } 75 | 76 | public List assets() { 77 | return assets; 78 | } 79 | 80 | public List symbols() { 81 | return symbols; 82 | } 83 | } -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/allthethings/AllTheThingsSpace.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.allthethings; 2 | 3 | import com.contentful.vault.Space; 4 | 5 | @Space(value = "hwp8ctxa24x7", models = AllTheThingsResource.class, locales = "en-US") 6 | public class AllTheThingsSpace { 7 | } 8 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/arraylinks/MultiLinksSpace.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.arraylinks; 2 | 3 | import com.contentful.vault.Space; 4 | 5 | @Space( 6 | value = "kykc8h4zm12t", 7 | models = {Product.class, Shop.class}, 8 | locales = "en-US" 9 | ) 10 | public class MultiLinksSpace { 11 | } 12 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/arraylinks/Product.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.arraylinks; 2 | 3 | import com.contentful.vault.ContentType; 4 | import com.contentful.vault.Field; 5 | import com.contentful.vault.Resource; 6 | 7 | import java.util.List; 8 | 9 | @ContentType("product") 10 | public class Product extends Resource { 11 | @Field String name; 12 | 13 | @Field List shops; 14 | 15 | public String name() { 16 | return name; 17 | } 18 | 19 | public List shops() { 20 | return shops; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/arraylinks/Shop.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.arraylinks; 2 | 3 | import com.contentful.vault.ContentType; 4 | import com.contentful.vault.Field; 5 | import com.contentful.vault.Resource; 6 | 7 | import java.util.List; 8 | 9 | @ContentType("shop") 10 | public class Shop extends Resource { 11 | @Field String name; 12 | 13 | @Field List products; 14 | 15 | public String name() { 16 | return name; 17 | } 18 | 19 | public List products() { 20 | return products; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/demo/Cat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration.lib.demo; 18 | 19 | import com.contentful.vault.Asset; 20 | import com.contentful.vault.ContentType; 21 | import com.contentful.vault.Field; 22 | import com.contentful.vault.Resource; 23 | 24 | @ContentType("cat") 25 | public class Cat extends Resource { 26 | @Field String name; 27 | 28 | @Field Cat bestFriend; 29 | 30 | @Field Asset image; 31 | 32 | public String name() { 33 | return name; 34 | } 35 | 36 | public Cat bestFriend() { 37 | return bestFriend; 38 | } 39 | 40 | public Asset image() { 41 | return image; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/demo/DemoSpace.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration.lib.demo; 18 | 19 | import com.contentful.vault.Space; 20 | 21 | @Space(value = "cfexampleapi", models = Cat.class, locales = { "en-US", "tlh" }) 22 | public class DemoSpace { 23 | } 24 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/escape/SqliteEscapeModel.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.escape; 2 | 3 | import com.contentful.vault.ContentType; 4 | import com.contentful.vault.Field; 5 | import com.contentful.vault.Resource; 6 | 7 | @ContentType("foo") 8 | public class SqliteEscapeModel extends Resource { 9 | @Field public String order; 10 | } 11 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/escape/SqliteEscapeSpace.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.escape; 2 | 3 | import com.contentful.vault.Space; 4 | 5 | @Space(value = "ev53h12ay8c5", models = SqliteEscapeModel.class, locales = "en-US") 6 | public class SqliteEscapeSpace { 7 | } 8 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/links/AssetsContainer.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.links; 2 | 3 | import com.contentful.vault.Asset; 4 | import com.contentful.vault.ContentType; 5 | import com.contentful.vault.Field; 6 | import com.contentful.vault.Resource; 7 | import java.util.List; 8 | 9 | @ContentType("5QVPSeE41yo28mA4sU6gIo") 10 | public class AssetsContainer extends Resource { 11 | @Field List assets; 12 | 13 | public List assets() { 14 | return assets; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/links/LinksSpace.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.links; 2 | 3 | import com.contentful.vault.Space; 4 | 5 | @Space(value = "fp9iccz5ot6h", models = AssetsContainer.class, locales = "en-US") 6 | public class LinksSpace { 7 | } 8 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/localizedlinks/Container.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.localizedlinks; 2 | 3 | import com.contentful.vault.Asset; 4 | import com.contentful.vault.ContentType; 5 | import com.contentful.vault.Field; 6 | import com.contentful.vault.Resource; 7 | import java.util.List; 8 | 9 | @ContentType("2Ux73cONSU2w2sCe42Gusy") 10 | public final class Container extends Resource { 11 | @Field List assets; 12 | 13 | @Field Asset one; 14 | 15 | public List assets() { 16 | return assets; 17 | } 18 | 19 | public Asset one() { 20 | return one; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/localizedlinks/LocalizedLinksSpace.java: -------------------------------------------------------------------------------- 1 | package com.contentful.vaultintegration.lib.localizedlinks; 2 | 3 | import com.contentful.vault.Space; 4 | 5 | @Space(value = "dotunxzzh0et", models = { Container.class }, locales = { "en-US", "he-IL" }) 6 | public final class LocalizedLinksSpace { 7 | } 8 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/vault/ArraysResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration.lib.vault; 18 | 19 | import com.contentful.vault.Asset; 20 | import com.contentful.vault.ContentType; 21 | import com.contentful.vault.Field; 22 | import com.contentful.vault.Resource; 23 | import java.util.List; 24 | 25 | @ContentType("4rD4z2Ex0kEOgeWCWG4Se2") 26 | public class ArraysResource extends Resource { 27 | @Field List assets; 28 | 29 | @Field List symbols; 30 | 31 | @Field List blobs; 32 | 33 | public List assets() { 34 | return assets; 35 | } 36 | 37 | public List symbols() { 38 | return symbols; 39 | } 40 | 41 | public List blobs() { 42 | return blobs; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/vault/BlobResource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration.lib.vault; 18 | 19 | import com.contentful.vault.ContentType; 20 | import com.contentful.vault.Field; 21 | import com.contentful.vault.Resource; 22 | import java.util.Map; 23 | 24 | @ContentType("1HRG7uai2g8YMswwqoAaC8") 25 | public class BlobResource extends Resource { 26 | @Field Map object; 27 | 28 | public Map object() { 29 | return object; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests-integration/src/test/java/com/contentful/vaultintegration/lib/vault/VaultSpace.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 Contentful GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.contentful.vaultintegration.lib.vault; 18 | 19 | import com.contentful.vault.Space; 20 | 21 | @Space( 22 | value = "y005y7p7nrqo", 23 | models = { ArraysResource.class, BlobResource.class }, 24 | locales = "en-US" 25 | ) 26 | public class VaultSpace { 27 | } 28 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/allthethings/initial.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "items": [ 6 | { 7 | "sys": { 8 | "space": { 9 | "sys": { 10 | "type": "Link", 11 | "linkType": "Space", 12 | "id": "hwp8ctxa24x7" 13 | } 14 | }, 15 | "type": "Entry", 16 | "contentType": { 17 | "sys": { 18 | "type": "Link", 19 | "linkType": "ContentType", 20 | "id": "2585ClSxW8OeuMEoIiKW4i" 21 | } 22 | }, 23 | "id": "6K1Md1qADuOsoom2UIEKkq", 24 | "revision": 3, 25 | "createdAt": "2015-07-07T08:28:22.270Z", 26 | "updatedAt": "2015-07-07T08:32:32.283Z" 27 | }, 28 | "fields": { 29 | "text": { 30 | "en-US": "foo" 31 | }, 32 | "number": { 33 | "en-US": 31337 34 | }, 35 | "decimal": { 36 | "en-US": 1.337 37 | }, 38 | "yesno": { 39 | "en-US": true 40 | }, 41 | "dateTime": { 42 | "en-US": "2015-07-01" 43 | }, 44 | "location": { 45 | "en-US": { 46 | "lat": 52.52000659999999, 47 | "lon": 13.404953999999975 48 | } 49 | }, 50 | "object": { 51 | "en-US": { 52 | "foo": "bar", 53 | "bar": "foo" 54 | } 55 | }, 56 | "symbols": { 57 | "en-US": [ 58 | "foo", 59 | "bar" 60 | ] 61 | }, 62 | "asset": { 63 | "en-US": { 64 | "sys": { 65 | "type": "Link", 66 | "linkType": "Asset", 67 | "id": "6Kknr7SqpGWs8kIKwCuQCU" 68 | } 69 | } 70 | }, 71 | "assets": { 72 | "en-US": [ 73 | { 74 | "sys": { 75 | "type": "Link", 76 | "linkType": "Asset", 77 | "id": "6Kknr7SqpGWs8kIKwCuQCU" 78 | } 79 | }, 80 | { 81 | "sys": { 82 | "type": "Link", 83 | "linkType": "Asset", 84 | "id": "w4ZPwQ0Cmko2QqyWgSEGy" 85 | } 86 | } 87 | ] 88 | }, 89 | "entry": { 90 | "en-US": { 91 | "sys": { 92 | "type": "Link", 93 | "linkType": "Entry", 94 | "id": "4EYJjgMg0oG084iuACY6Ue" 95 | } 96 | } 97 | }, 98 | "entries": { 99 | "en-US": [ 100 | { 101 | "sys": { 102 | "type": "Link", 103 | "linkType": "Entry", 104 | "id": "4EYJjgMg0oG084iuACY6Ue" 105 | } 106 | } 107 | ] 108 | } 109 | } 110 | }, 111 | { 112 | "sys": { 113 | "space": { 114 | "sys": { 115 | "type": "Link", 116 | "linkType": "Space", 117 | "id": "hwp8ctxa24x7" 118 | } 119 | }, 120 | "type": "Entry", 121 | "contentType": { 122 | "sys": { 123 | "type": "Link", 124 | "linkType": "ContentType", 125 | "id": "2585ClSxW8OeuMEoIiKW4i" 126 | } 127 | }, 128 | "id": "4EYJjgMg0oG084iuACY6Ue", 129 | "revision": 1, 130 | "createdAt": "2015-07-07T08:32:14.737Z", 131 | "updatedAt": "2015-07-07T08:32:14.737Z" 132 | }, 133 | "fields": { 134 | "text": { 135 | "en-US": "bar" 136 | }, 137 | "yesno": { 138 | "en-US": false 139 | }, 140 | "number": { 141 | "en-US": 1 142 | }, 143 | "decimal": { 144 | "en-US": 2 145 | } 146 | } 147 | }, 148 | { 149 | "fields": { 150 | "title": { 151 | "en-US": "bar" 152 | }, 153 | "description": { 154 | "en-US": "baz" 155 | }, 156 | "file": { 157 | "en-US": { 158 | "fileName": "snap.jpg", 159 | "contentType": "image/jpeg", 160 | "details": { 161 | "image": { 162 | "width": 400, 163 | "height": 280 164 | }, 165 | "size": 11705 166 | }, 167 | "url": "//images.contentful.com/hwp8ctxa24x7/w4ZPwQ0Cmko2QqyWgSEGy/c5d5d5a9bd05e062caa5ca226e85266c/snap.jpg" 168 | } 169 | } 170 | }, 171 | "sys": { 172 | "space": { 173 | "sys": { 174 | "type": "Link", 175 | "linkType": "Space", 176 | "id": "hwp8ctxa24x7" 177 | } 178 | }, 179 | "type": "Asset", 180 | "id": "w4ZPwQ0Cmko2QqyWgSEGy", 181 | "revision": 1, 182 | "createdAt": "2015-07-07T08:31:21.928Z", 183 | "updatedAt": "2015-07-07T08:31:21.928Z" 184 | } 185 | }, 186 | { 187 | "fields": { 188 | "title": { 189 | "en-US": "foo" 190 | }, 191 | "description": { 192 | "en-US": "bar" 193 | }, 194 | "file": { 195 | "en-US": { 196 | "fileName": "snap.jpg", 197 | "contentType": "image/jpeg", 198 | "details": { 199 | "image": { 200 | "width": 400, 201 | "height": 280 202 | }, 203 | "size": 21937 204 | }, 205 | "url": "//images.contentful.com/hwp8ctxa24x7/6Kknr7SqpGWs8kIKwCuQCU/a69bdeca0a9ce099b0093045694b28af/snap.jpg" 206 | } 207 | } 208 | }, 209 | "sys": { 210 | "space": { 211 | "sys": { 212 | "type": "Link", 213 | "linkType": "Space", 214 | "id": "hwp8ctxa24x7" 215 | } 216 | }, 217 | "type": "Asset", 218 | "id": "6Kknr7SqpGWs8kIKwCuQCU", 219 | "revision": 1, 220 | "createdAt": "2015-07-07T08:30:49.700Z", 221 | "updatedAt": "2015-07-07T08:30:49.700Z" 222 | } 223 | } 224 | ], 225 | "nextSyncUrl": "https://cdn.contentful.com/spaces/hwp8ctxa24x7/sync?sync_token=w5ZGw6JFwqZmVcKsE8Kow4grw45QdybCnMOGNsOHVmJzw5rCmQYjw4LCu296w4nDjQfDtsKebMKBwrkcwrPCvj7Dq2FHw7cYw4PCocOywoxWw5vCqcKgAsOrcsOESMK9wrPDmMOHBVR6SsKhdWVnOcKIVUwMwq0d" 226 | } -------------------------------------------------------------------------------- /tests-integration/src/test/resources/allthethings/locales.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 1, 6 | "skip": 0, 7 | "limit": 1000, 8 | "items": [ 9 | { 10 | "code": "en-US", 11 | "name": "English", 12 | "default": true, 13 | "fallbackCode": null, 14 | "sys": { 15 | "id": "id", 16 | "type": "Locale", 17 | "version": 1 18 | } 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /tests-integration/src/test/resources/allthethings/types.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 1, 6 | "skip": 0, 7 | "limit": 100, 8 | "items": [ 9 | { 10 | "name": "All The Things", 11 | "fields": [ 12 | { 13 | "name": "text", 14 | "id": "text", 15 | "type": "Text" 16 | }, 17 | { 18 | "name": "number", 19 | "id": "number", 20 | "type": "Integer" 21 | }, 22 | { 23 | "name": "decimal", 24 | "id": "decimal", 25 | "type": "Number" 26 | }, 27 | { 28 | "name": "yesno", 29 | "id": "yesno", 30 | "type": "Boolean" 31 | }, 32 | { 33 | "name": "dateTime", 34 | "id": "dateTime", 35 | "type": "Date" 36 | }, 37 | { 38 | "name": "location", 39 | "id": "location", 40 | "type": "Location" 41 | }, 42 | { 43 | "name": "entry", 44 | "id": "entry", 45 | "type": "Link", 46 | "linkType": "Entry" 47 | }, 48 | { 49 | "name": "asset", 50 | "id": "asset", 51 | "type": "Link", 52 | "linkType": "Asset" 53 | }, 54 | { 55 | "name": "object", 56 | "id": "object", 57 | "type": "Object" 58 | }, 59 | { 60 | "name": "entries", 61 | "id": "entries", 62 | "type": "Array", 63 | "items": { 64 | "type": "Link", 65 | "linkType": "Entry", 66 | "validations": [ 67 | { 68 | "linkContentType": [ 69 | "2585ClSxW8OeuMEoIiKW4i" 70 | ] 71 | } 72 | ] 73 | } 74 | }, 75 | { 76 | "name": "assets", 77 | "id": "assets", 78 | "type": "Array", 79 | "items": { 80 | "type": "Link", 81 | "linkType": "Asset" 82 | } 83 | }, 84 | { 85 | "name": "symbols", 86 | "id": "symbols", 87 | "type": "Array", 88 | "items": { 89 | "type": "Symbol" 90 | } 91 | } 92 | ], 93 | "displayField": "text", 94 | "sys": { 95 | "space": { 96 | "sys": { 97 | "type": "Link", 98 | "linkType": "Space", 99 | "id": "hwp8ctxa24x7" 100 | } 101 | }, 102 | "type": "ContentType", 103 | "id": "2585ClSxW8OeuMEoIiKW4i", 104 | "revision": 2, 105 | "createdAt": "2015-07-07T08:26:47.081Z", 106 | "updatedAt": "2015-07-07T08:27:21.639Z" 107 | } 108 | } 109 | ] 110 | } -------------------------------------------------------------------------------- /tests-integration/src/test/resources/arraylinks/locales.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 1, 6 | "skip": 0, 7 | "limit": 1000, 8 | "items": [ 9 | { 10 | "code": "en-US", 11 | "default": true, 12 | "name": "U.S. English", 13 | "fallbackCode": null, 14 | "sys": { 15 | "id": "id", 16 | "type": "Locale", 17 | "version": 1 18 | } 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/arraylinks/types.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 2, 6 | "skip": 0, 7 | "limit": 100, 8 | "items": [ 9 | { 10 | "sys": { 11 | "space": { 12 | "sys": { 13 | "type": "Link", 14 | "linkType": "Space", 15 | "id": "kykc8h4zm12t" 16 | } 17 | }, 18 | "id": "product", 19 | "type": "ContentType", 20 | "createdAt": "2017-08-15T13:46:27.919Z", 21 | "updatedAt": "2017-08-15T13:52:44.380Z", 22 | "revision": 3 23 | }, 24 | "displayField": "name", 25 | "name": "Product", 26 | "description": "A product in a shop", 27 | "fields": [ 28 | { 29 | "id": "name", 30 | "name": "name", 31 | "type": "Symbol", 32 | "localized": false, 33 | "required": false, 34 | "disabled": false, 35 | "omitted": false 36 | }, 37 | { 38 | "id": "shops", 39 | "name": "shops", 40 | "type": "Array", 41 | "localized": false, 42 | "required": false, 43 | "disabled": false, 44 | "omitted": false, 45 | "items": { 46 | "type": "Link", 47 | "validations": [ 48 | { 49 | "linkContentType": [ 50 | "shop" 51 | ] 52 | } 53 | ], 54 | "linkType": "Entry" 55 | } 56 | } 57 | ] 58 | }, 59 | { 60 | "sys": { 61 | "space": { 62 | "sys": { 63 | "type": "Link", 64 | "linkType": "Space", 65 | "id": "kykc8h4zm12t" 66 | } 67 | }, 68 | "id": "shop", 69 | "type": "ContentType", 70 | "createdAt": "2017-08-15T13:47:07.542Z", 71 | "updatedAt": "2017-08-15T13:52:34.917Z", 72 | "revision": 2 73 | }, 74 | "displayField": "name", 75 | "name": "Shop", 76 | "description": "A shop of producs", 77 | "fields": [ 78 | { 79 | "id": "name", 80 | "name": "name", 81 | "type": "Symbol", 82 | "localized": false, 83 | "required": false, 84 | "disabled": false, 85 | "omitted": false 86 | }, 87 | { 88 | "id": "products", 89 | "name": "products", 90 | "type": "Array", 91 | "localized": false, 92 | "required": false, 93 | "disabled": false, 94 | "omitted": false, 95 | "items": { 96 | "type": "Link", 97 | "validations": [ 98 | { 99 | "linkContentType": [ 100 | "product" 101 | ] 102 | } 103 | ], 104 | "linkType": "Entry" 105 | } 106 | } 107 | ] 108 | } 109 | ] 110 | } 111 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/assets/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "items": [ 6 | { 7 | "sys": { 8 | "space": { 9 | "sys": { 10 | "type": "Link", 11 | "linkType": "Space", 12 | "id": "cfexampleapi" 13 | }, 14 | "environment": { 15 | "sys": { 16 | "id": "staging", 17 | "type": "Link", 18 | "linkType": "Environment" 19 | } 20 | } 21 | }, 22 | "type": "Asset", 23 | "id": "id", 24 | "revision": 6, 25 | "createdAt": "2018-05-06T09:45:10.000Z", 26 | "updatedAt": "2018-06-18T13:27:14.917Z" 27 | }, 28 | "fields": {} 29 | } 30 | ], 31 | "nextSyncUrl": "http://cdn.contentful.com/spaces/cfexampleapi/sync?sync_token=st1" 32 | } 33 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/assets/initial.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "items": [ 6 | { 7 | "sys": { 8 | "space": { 9 | "sys": { 10 | "type": "Link", 11 | "linkType": "Space", 12 | "id": "cfexampleapi" 13 | } 14 | }, 15 | "type": "Asset", 16 | "id": "1x0xpXu4pSGS4OukSyWGUK", 17 | "revision": 6, 18 | "createdAt": "2013-11-06T09:45:10.000Z", 19 | "updatedAt": "2013-12-18T13:27:14.917Z" 20 | }, 21 | "fields": { 22 | "title": { 23 | "en-US": "Doge", 24 | "de-DE": "Dogge" 25 | }, 26 | "file": { 27 | "en-US": { 28 | "fileName": "doge.jpg", 29 | "contentType": "image/jpeg", 30 | "details": { 31 | "image": { 32 | "width": 5800, 33 | "height": 4350 34 | }, 35 | "size": 522943 36 | }, 37 | "url": "//images.contentful.com/cfexampleapi/1x0xpXu4pSGS4OukSyWGUK/cc1239c6385428ef26f4180190532818/doge.jpg" 38 | } 39 | }, 40 | "description": { 41 | "en-US": "nice picture", 42 | "de-DE": "Schönes Bild" 43 | } 44 | } 45 | } 46 | ], 47 | "nextSyncUrl": "http://cdn.contentful.com/spaces/cfexampleapi/sync?sync_token=st1" 48 | } 49 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/assets/locales.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 3, 6 | "skip": 0, 7 | "limit": 1000, 8 | "items": [ 9 | { 10 | "code": "en-US", 11 | "default": true, 12 | "name": "U.S. English 🇺🇸", 13 | "fallbackCode": null, 14 | "sys": { 15 | "id": "id1", 16 | "type": "Locale", 17 | "version": 1 18 | } 19 | }, 20 | { 21 | "code": "de-DE", 22 | "default": false, 23 | "name": "Deutsch 🇩🇪", 24 | "fallbackCode": "en-US", 25 | "sys": { 26 | "id": "id2", 27 | "type": "Locale", 28 | "version": 1 29 | } 30 | }, 31 | { 32 | "code": "tlh", 33 | "default": false, 34 | "name": "Klingon", 35 | "fallbackCode": "de-DE", 36 | "sys": { 37 | "id": "id3", 38 | "type": "Locale", 39 | "version": 1 40 | } 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/assets/types.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 2, 6 | "skip": 0, 7 | "limit": 100, 8 | "items": [ 9 | { 10 | "sys": { 11 | "space": { 12 | "sys": { 13 | "type": "Link", 14 | "linkType": "Space", 15 | "id": "kykc8h4zm12t" 16 | } 17 | }, 18 | "id": "product", 19 | "type": "ContentType", 20 | "createdAt": "2017-08-15T13:46:27.919Z", 21 | "updatedAt": "2017-08-15T13:52:44.380Z", 22 | "revision": 3 23 | }, 24 | "displayField": "name", 25 | "name": "Product", 26 | "description": "A product in a shop", 27 | "fields": [ 28 | { 29 | "id": "name", 30 | "name": "name", 31 | "type": "Symbol", 32 | "localized": false, 33 | "required": false, 34 | "disabled": false, 35 | "omitted": false 36 | }, 37 | { 38 | "id": "shops", 39 | "name": "shops", 40 | "type": "Array", 41 | "localized": false, 42 | "required": false, 43 | "disabled": false, 44 | "omitted": false, 45 | "items": { 46 | "type": "Link", 47 | "validations": [ 48 | { 49 | "linkContentType": [ 50 | "shop" 51 | ] 52 | } 53 | ], 54 | "linkType": "Entry" 55 | } 56 | } 57 | ] 58 | }, 59 | { 60 | "sys": { 61 | "space": { 62 | "sys": { 63 | "type": "Link", 64 | "linkType": "Space", 65 | "id": "kykc8h4zm12t" 66 | } 67 | }, 68 | "id": "shop", 69 | "type": "ContentType", 70 | "createdAt": "2017-08-15T13:47:07.542Z", 71 | "updatedAt": "2017-08-15T13:52:34.917Z", 72 | "revision": 2 73 | }, 74 | "displayField": "name", 75 | "name": "Shop", 76 | "description": "A shop of producs", 77 | "fields": [ 78 | { 79 | "id": "name", 80 | "name": "name", 81 | "type": "Symbol", 82 | "localized": false, 83 | "required": false, 84 | "disabled": false, 85 | "omitted": false 86 | }, 87 | { 88 | "id": "products", 89 | "name": "products", 90 | "type": "Array", 91 | "localized": false, 92 | "required": false, 93 | "disabled": false, 94 | "omitted": false, 95 | "items": { 96 | "type": "Link", 97 | "validations": [ 98 | { 99 | "linkContentType": [ 100 | "product" 101 | ] 102 | } 103 | ], 104 | "linkType": "Entry" 105 | } 106 | } 107 | ] 108 | } 109 | ] 110 | } 111 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/demo/locales.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 1, 6 | "skip": 0, 7 | "limit": 1000, 8 | "items": [ 9 | { 10 | "code": "en-US", 11 | "default": true, 12 | "name": "English", 13 | "sys": { 14 | "id": "id1", 15 | "type": "Locale", 16 | "version": 1 17 | } 18 | 19 | }, 20 | { 21 | "code": "tlh", 22 | "default": false, 23 | "name": "Klingon", 24 | "fallbackCode": "en-US", 25 | "sys": { 26 | "id": "id2", 27 | "type": "Locale", 28 | "version": 1 29 | } 30 | 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/demo/update.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "items": [ 6 | { 7 | "fields": { 8 | "name": { 9 | "en-US": "SuperCat" 10 | }, 11 | "likes": { 12 | "en-US": [ 13 | "dogs" 14 | ] 15 | }, 16 | "color": { 17 | "en-US": "black" 18 | }, 19 | "lifes": { 20 | "en-US": null 21 | }, 22 | "lives": { 23 | "en-US": 123 24 | }, 25 | "birthday": { 26 | "en-US": "1979-06-18T23:00:00+00:00" 27 | } 28 | }, 29 | "sys": { 30 | "space": { 31 | "sys": { 32 | "type": "Link", 33 | "linkType": "Space", 34 | "id": "cfexampleapi" 35 | } 36 | }, 37 | "type": "Entry", 38 | "contentType": { 39 | "sys": { 40 | "type": "Link", 41 | "linkType": "ContentType", 42 | "id": "cat" 43 | } 44 | }, 45 | "id": "supercat", 46 | "revision": 1, 47 | "createdAt": "2013-06-27T22:46:20.821Z", 48 | "updatedAt": "2013-08-27T10:09:07.929Z" 49 | } 50 | }, 51 | { 52 | "sys": { 53 | "type": "DeletedEntry", 54 | "id": "nyancat", 55 | "space": { 56 | "sys": { 57 | "type": "Link", 58 | "linkType": "Space", 59 | "id": "cfexampleapi" 60 | } 61 | }, 62 | "revision": 6, 63 | "createdAt": "2014-07-31T15:14:59.226Z", 64 | "updatedAt": "2014-07-31T15:14:59.226Z", 65 | "deletedAt": "2014-07-31T15:14:59.226Z" 66 | } 67 | }, 68 | { 69 | "sys": { 70 | "type": "DeletedAsset", 71 | "id": "jake", 72 | "space": { 73 | "sys": { 74 | "type": "Link", 75 | "linkType": "Space", 76 | "id": "DeletedAsset" 77 | } 78 | }, 79 | "revision": 1, 80 | "createdAt": "2014-12-03T16:51:23.658Z", 81 | "updatedAt": "2014-12-03T16:51:23.658Z", 82 | "deletedAt": "2014-12-03T16:51:23.658Z" 83 | } 84 | }, 85 | { 86 | "fields": { 87 | "name": { 88 | "en-US": "Happier Cat" 89 | }, 90 | "bestFriend": { 91 | "en-US": { 92 | "sys": { 93 | "type": "Link", 94 | "linkType": "Entry", 95 | "id": "nyancat" 96 | } 97 | } 98 | }, 99 | "likes": { 100 | "en-US": [ 101 | "cheezburger" 102 | ] 103 | }, 104 | "color": { 105 | "en-US": "gray" 106 | }, 107 | "birthday": { 108 | "en-US": "2003-10-28T23:00:00+00:00" 109 | }, 110 | "lives": { 111 | "en-US": 1 112 | }, 113 | "image": { 114 | "en-US": { 115 | "sys": { 116 | "type": "Link", 117 | "linkType": "Asset", 118 | "id": "happycat" 119 | } 120 | } 121 | } 122 | }, 123 | "sys": { 124 | "space": { 125 | "sys": { 126 | "type": "Link", 127 | "linkType": "Space", 128 | "id": "cfexampleapi" 129 | } 130 | }, 131 | "type": "Entry", 132 | "contentType": { 133 | "sys": { 134 | "type": "Link", 135 | "linkType": "ContentType", 136 | "id": "cat" 137 | } 138 | }, 139 | "id": "happycat", 140 | "revision": 9, 141 | "createdAt": "2013-06-27T22:46:20.171Z", 142 | "updatedAt": "2013-11-18T15:58:02.018Z" 143 | } 144 | }, 145 | { 146 | "fields": { 147 | "file": { 148 | "en-US": { 149 | "fileName": "happycatw.jpg", 150 | "contentType": "image/jpeg", 151 | "details": { 152 | "image": { 153 | "width": 273, 154 | "height": 397 155 | }, 156 | "size": 59939 157 | }, 158 | "url": "//happiercat.jpg" 159 | } 160 | }, 161 | "title": { 162 | "en-US": "Happy Cat" 163 | } 164 | }, 165 | "sys": { 166 | "space": { 167 | "sys": { 168 | "type": "Link", 169 | "linkType": "Space", 170 | "id": "cfexampleapi" 171 | } 172 | }, 173 | "type": "Asset", 174 | "id": "happycat", 175 | "revision": 2, 176 | "createdAt": "2013-09-02T14:56:34.267Z", 177 | "updatedAt": "2013-09-02T15:11:24.361Z" 178 | } 179 | } 180 | ], 181 | "nextSyncUrl": "http://cdn.contentful.com/spaces/FAKE/sync?sync_token=st2" 182 | } 183 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/escape/initial.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "items": [ 6 | { 7 | "sys": { 8 | "space": { 9 | "sys": { 10 | "type": "Link", 11 | "linkType": "Space", 12 | "id": "ev53h12ay8c5" 13 | } 14 | }, 15 | "type": "Entry", 16 | "contentType": { 17 | "sys": { 18 | "type": "Link", 19 | "linkType": "ContentType", 20 | "id": "foo" 21 | } 22 | }, 23 | "id": "2aK6jhLFoMQuEc2wmoEAI4", 24 | "revision": 1, 25 | "createdAt": "2015-07-03T01:38:11.932Z", 26 | "updatedAt": "2015-07-03T01:38:11.932Z" 27 | }, 28 | "fields": { 29 | "order": { 30 | "en-US": "foo" 31 | } 32 | } 33 | } 34 | ], 35 | "nextSyncUrl": "http://cdn.contentful.com/spaces/ev53h12ay8c5/sync?sync_token=foo" 36 | } -------------------------------------------------------------------------------- /tests-integration/src/test/resources/escape/locales.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 1, 6 | "skip": 0, 7 | "limit": 1000, 8 | "items": [ 9 | { 10 | "code": "en-US", 11 | "default": true, 12 | "name": "U.S. English", 13 | "fallbackCode": null, 14 | "sys": { 15 | "id": "id", 16 | "type": "Locale", 17 | "version": 1 18 | } 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/escape/types.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 1, 6 | "skip": 0, 7 | "limit": 100, 8 | "items": [ 9 | { 10 | "name": "SqliteEscapeModel", 11 | "fields": [ 12 | { 13 | "name": "order", 14 | "id": "order", 15 | "type": "Text" 16 | } 17 | ], 18 | "sys": { 19 | "space": { 20 | "sys": { 21 | "type": "Link", 22 | "linkType": "Space", 23 | "id": "fp9iccz5ot6h" 24 | } 25 | }, 26 | "type": "ContentType", 27 | "id": "foo", 28 | "revision": 1, 29 | "createdAt": "2015-05-21T08:58:17.595Z", 30 | "updatedAt": "2015-05-21T08:58:17.595Z" 31 | } 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /tests-integration/src/test/resources/links/locales.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 2, 6 | "skip": 0, 7 | "limit": 1000, 8 | "items": [ 9 | { 10 | "code": "en-US", 11 | "default": true, 12 | "name": "U.S. English", 13 | "sys": { 14 | "id": "id1", 15 | "type": "Locale", 16 | "version": 1 17 | } 18 | }, 19 | { 20 | "code": "he-IL", 21 | "default": false, 22 | "name": "Hebrew", 23 | "fallbackCode": "en-US", 24 | "sys": { 25 | "id": "id2", 26 | "type": "Locale", 27 | "version": 1 28 | } 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/links/types.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 1, 6 | "skip": 0, 7 | "limit": 100, 8 | "items": [ 9 | { 10 | "name": "AssetsContainer", 11 | "fields": [ 12 | { 13 | "name": "assets", 14 | "id": "assets", 15 | "type": "Array", 16 | "items": { 17 | "type": "Link", 18 | "linkType": "Asset" 19 | }, 20 | "localized": true 21 | } 22 | ], 23 | "sys": { 24 | "space": { 25 | "sys": { 26 | "type": "Link", 27 | "linkType": "Space", 28 | "id": "fp9iccz5ot6h" 29 | } 30 | }, 31 | "type": "ContentType", 32 | "id": "5QVPSeE41yo28mA4sU6gIo", 33 | "revision": 1, 34 | "createdAt": "2015-05-21T08:58:17.595Z", 35 | "updatedAt": "2015-05-21T08:58:17.595Z" 36 | } 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /tests-integration/src/test/resources/links/update.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "items": [ 6 | { 7 | "sys": { 8 | "space": { 9 | "sys": { 10 | "type": "Link", 11 | "linkType": "Space", 12 | "id": "fp9iccz5ot6h" 13 | } 14 | }, 15 | "type": "Entry", 16 | "contentType": { 17 | "sys": { 18 | "type": "Link", 19 | "linkType": "ContentType", 20 | "id": "5QVPSeE41yo28mA4sU6gIo" 21 | } 22 | }, 23 | "id": "34ljO1zKukgIYmcQ64IgOo", 24 | "revision": 2, 25 | "createdAt": "2015-05-21T09:07:48.379Z", 26 | "updatedAt": "2015-05-21T09:09:30.230Z" 27 | }, 28 | "fields": { 29 | "assets": { 30 | "en-US": [ 31 | { 32 | "sys": { 33 | "type": "Link", 34 | "linkType": "Asset", 35 | "id": "2lD1fm3UBiwYk0m6CgmiQQ" 36 | } 37 | }, 38 | { 39 | "sys": { 40 | "type": "Link", 41 | "linkType": "Asset", 42 | "id": "65ou5OAxawuQIkOAe2e42c" 43 | } 44 | } 45 | ], 46 | "he-IL": [ 47 | { 48 | "sys": { 49 | "type": "Link", 50 | "linkType": "Asset", 51 | "id": "65ou5OAxawuQIkOAe2e42c" 52 | } 53 | } 54 | ] 55 | } 56 | } 57 | } 58 | ], 59 | "nextSyncUrl": "https://cdn.contentful.com/spaces/fp9iccz5ot6h/sync?sync_token=w5ZGw6JFwqZmVcKsE8Kow4grw45QdyYVU37CgMO4wr_Ct8KGAMOVw7fCtcOgwqcTUcK8wq7Do8K3woUZwrQVLBnDg0jDmcKNHCtwXWnCucKpXsKJwoPCpxHCt8OMw6jDqsKoCDTCi3MMw6PDgS9KwqsNHm5YwpA7XQ" 60 | } 61 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/localizedlinks/initial.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "items": [ 6 | { 7 | "sys": { 8 | "space": { 9 | "sys": { 10 | "type": "Link", 11 | "linkType": "Space", 12 | "id": "dotunxzzh0et" 13 | } 14 | }, 15 | "type": "Entry", 16 | "contentType": { 17 | "sys": { 18 | "type": "Link", 19 | "linkType": "ContentType", 20 | "id": "2Ux73cONSU2w2sCe42Gusy" 21 | } 22 | }, 23 | "id": "5oM5rpMdGgQQomIyGe8cM6", 24 | "revision": 1, 25 | "createdAt": "2015-11-23T05:05:19.262Z", 26 | "updatedAt": "2015-11-23T05:05:19.262Z" 27 | }, 28 | "fields": { 29 | "assets": { 30 | "en-US": [ 31 | { 32 | "sys": { 33 | "type": "Link", 34 | "linkType": "Asset", 35 | "id": "3XREDPOkZqCSWgomgUWU4G" 36 | } 37 | }, 38 | { 39 | "sys": { 40 | "type": "Link", 41 | "linkType": "Asset", 42 | "id": "1Up25hQn3SU8mW4K4q2WKa" 43 | } 44 | } 45 | ] 46 | }, 47 | "one": { 48 | "en-US": { 49 | "sys": { 50 | "type": "Link", 51 | "linkType": "Asset", 52 | "id": "3XREDPOkZqCSWgomgUWU4G" 53 | } 54 | }, 55 | "he-IL": { 56 | "sys": { 57 | "type": "Link", 58 | "linkType": "Asset", 59 | "id": "1Up25hQn3SU8mW4K4q2WKa" 60 | } 61 | } 62 | } 63 | } 64 | }, 65 | { 66 | "fields": { 67 | "file": { 68 | "en-US": { 69 | "fileName": "snap.jpg", 70 | "contentType": "image/jpeg", 71 | "details": { 72 | "image": { 73 | "width": 800, 74 | "height": 450 75 | }, 76 | "size": 12726 77 | }, 78 | "url": "//images.contentful.com/dotunxzzh0et/3XREDPOkZqCSWgomgUWU4G/e99b7ac9bfb4c331eecfaec2cf8896af/snap.jpg" 79 | } 80 | }, 81 | "title": { 82 | "en-US": "hello" 83 | } 84 | }, 85 | "sys": { 86 | "space": { 87 | "sys": { 88 | "type": "Link", 89 | "linkType": "Space", 90 | "id": "dotunxzzh0et" 91 | } 92 | }, 93 | "type": "Asset", 94 | "id": "3XREDPOkZqCSWgomgUWU4G", 95 | "revision": 2, 96 | "createdAt": "2015-11-21T12:45:44.092Z", 97 | "updatedAt": "2015-11-21T12:47:20.933Z" 98 | } 99 | }, 100 | { 101 | "fields": { 102 | "title": { 103 | "en-US": "shalom" 104 | }, 105 | "file": { 106 | "en-US": { 107 | "fileName": "snap.jpg", 108 | "contentType": "image/jpeg", 109 | "details": { 110 | "image": { 111 | "width": 800, 112 | "height": 450 113 | }, 114 | "size": 10200 115 | }, 116 | "url": "//images.contentful.com/dotunxzzh0et/1Up25hQn3SU8mW4K4q2WKa/c3b04f48b25fcda1c89d3545526d61a9/snap.jpg" 117 | } 118 | } 119 | }, 120 | "sys": { 121 | "space": { 122 | "sys": { 123 | "type": "Link", 124 | "linkType": "Space", 125 | "id": "dotunxzzh0et" 126 | } 127 | }, 128 | "type": "Asset", 129 | "id": "1Up25hQn3SU8mW4K4q2WKa", 130 | "revision": 1, 131 | "createdAt": "2015-11-21T12:47:11.033Z", 132 | "updatedAt": "2015-11-21T12:47:11.033Z" 133 | } 134 | } 135 | ], 136 | "nextSyncUrl": "https://cdn.contentful.com/spaces/dotunxzzh0et/sync?sync_token=foo" 137 | } 138 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/localizedlinks/locales.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 1, 6 | "skip": 0, 7 | "limit": 1000, 8 | "items": [ 9 | { 10 | "code": "en-US", 11 | "default": true, 12 | "name": "U.S. English", 13 | "sys": { 14 | "id": "id1", 15 | "type": "Locale", 16 | "version": 1 17 | } 18 | }, 19 | { 20 | "code": "he-IL", 21 | "default": false, 22 | "name": "Hebrew (Israel)", 23 | "fallbackCode": "en-US", 24 | "sys": { 25 | "id": "id2", 26 | "type": "Locale", 27 | "version": 1 28 | } 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/localizedlinks/types.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 1, 6 | "skip": 0, 7 | "limit": 100, 8 | "items": [ 9 | { 10 | "name": "foo", 11 | "fields": [ 12 | { 13 | "name": "assets", 14 | "id": "assets", 15 | "type": "Array", 16 | "items": { 17 | "type": "Link", 18 | "linkType": "Asset", 19 | "validations": [] 20 | }, 21 | "localized": false 22 | }, 23 | { 24 | "name": "one", 25 | "id": "one", 26 | "type": "Link", 27 | "linkType": "Asset", 28 | "localized": true 29 | } 30 | ], 31 | "description": "", 32 | "sys": { 33 | "space": { 34 | "sys": { 35 | "type": "Link", 36 | "linkType": "Space", 37 | "id": "dotunxzzh0et" 38 | } 39 | }, 40 | "type": "ContentType", 41 | "id": "2Ux73cONSU2w2sCe42Gusy", 42 | "revision": 1, 43 | "createdAt": "2015-11-23T05:04:52.898Z", 44 | "updatedAt": "2015-11-23T05:04:52.898Z" 45 | } 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/vault/initial.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "items": [ 6 | { 7 | "sys": { 8 | "space": { 9 | "sys": { 10 | "type": "Link", 11 | "linkType": "Space", 12 | "id": "y005y7p7nrqo" 13 | } 14 | }, 15 | "type": "Entry", 16 | "contentType": { 17 | "sys": { 18 | "type": "Link", 19 | "linkType": "ContentType", 20 | "id": "4rD4z2Ex0kEOgeWCWG4Se2" 21 | } 22 | }, 23 | "id": "FyFV7zVpMQUG6IIEekeI0", 24 | "revision": 1, 25 | "createdAt": "2015-05-19T19:32:05.078Z", 26 | "updatedAt": "2015-05-19T19:32:05.078Z" 27 | } 28 | }, 29 | { 30 | "sys": { 31 | "space": { 32 | "sys": { 33 | "type": "Link", 34 | "linkType": "Space", 35 | "id": "y005y7p7nrqo" 36 | } 37 | }, 38 | "type": "Entry", 39 | "contentType": { 40 | "sys": { 41 | "type": "Link", 42 | "linkType": "ContentType", 43 | "id": "6yhJBtk1nUYq0iumy6gMY4" 44 | } 45 | }, 46 | "id": "32CFKK4sjKSM8KWoMEigwM", 47 | "revision": 2, 48 | "createdAt": "2015-05-11T13:23:19.498Z", 49 | "updatedAt": "2015-05-11T13:23:41.412Z" 50 | }, 51 | "fields": { 52 | "text": { 53 | "en-US": "english", 54 | "es-ES": "español" 55 | } 56 | } 57 | }, 58 | { 59 | "sys": { 60 | "space": { 61 | "sys": { 62 | "type": "Link", 63 | "linkType": "Space", 64 | "id": "y005y7p7nrqo" 65 | } 66 | }, 67 | "type": "Entry", 68 | "contentType": { 69 | "sys": { 70 | "type": "Link", 71 | "linkType": "ContentType", 72 | "id": "4rD4z2Ex0kEOgeWCWG4Se2" 73 | } 74 | }, 75 | "id": "u2L1goyi3eA4W0AKcqEou", 76 | "revision": 1, 77 | "createdAt": "2015-04-30T09:20:36.286Z", 78 | "updatedAt": "2015-04-30T09:20:36.286Z" 79 | }, 80 | "fields": { 81 | "symbols": { 82 | "en-US": [ 83 | "a", 84 | "b", 85 | "c" 86 | ] 87 | }, 88 | "assets": { 89 | "en-US": [ 90 | { 91 | "sys": { 92 | "type": "Link", 93 | "linkType": "Asset", 94 | "id": "1yj8f2uFEgGEkuqeoGIQws" 95 | } 96 | }, 97 | { 98 | "sys": { 99 | "type": "Link", 100 | "linkType": "Asset", 101 | "id": "2cMA1o04G42KGoQioOqqUA" 102 | } 103 | } 104 | ] 105 | }, 106 | "blobs": { 107 | "en-US": [ 108 | { 109 | "sys": { 110 | "type": "Link", 111 | "linkType": "Entry", 112 | "id": "6tOdhkd6Ewekq8M6MQe4GY" 113 | } 114 | } 115 | ] 116 | } 117 | } 118 | }, 119 | { 120 | "sys": { 121 | "space": { 122 | "sys": { 123 | "type": "Link", 124 | "linkType": "Space", 125 | "id": "y005y7p7nrqo" 126 | } 127 | }, 128 | "type": "Entry", 129 | "contentType": { 130 | "sys": { 131 | "type": "Link", 132 | "linkType": "ContentType", 133 | "id": "1HRG7uai2g8YMswwqoAaC8" 134 | } 135 | }, 136 | "id": "6tOdhkd6Ewekq8M6MQe4GY", 137 | "revision": 4, 138 | "createdAt": "2015-04-27T14:56:36.713Z", 139 | "updatedAt": "2015-04-30T09:20:17.339Z" 140 | }, 141 | "fields": { 142 | "object": { 143 | "en-US": { 144 | "fieldString": "hello", 145 | "fieldInteger": 31337, 146 | "fieldFloat": 3.1337, 147 | "fieldBoolean": true, 148 | "fieldMap": { 149 | "key": "value" 150 | } 151 | } 152 | } 153 | } 154 | }, 155 | { 156 | "sys": { 157 | "space": { 158 | "sys": { 159 | "type": "Link", 160 | "linkType": "Space", 161 | "id": "y005y7p7nrqo" 162 | } 163 | }, 164 | "type": "Asset", 165 | "id": "1yj8f2uFEgGEkuqeoGIQws", 166 | "revision": 1, 167 | "createdAt": "2015-04-28T12:11:11.683Z", 168 | "updatedAt": "2015-04-28T12:11:11.683Z" 169 | }, 170 | "fields": { 171 | "file": { 172 | "en-US": { 173 | "fileName": "jake.png", 174 | "contentType": "image/png", 175 | "details": { 176 | "image": { 177 | "width": 100, 178 | "height": 161 179 | }, 180 | "size": 20480 181 | }, 182 | "url": "//images.contentful.com/y005y7p7nrqo/1yj8f2uFEgGEkuqeoGIQws/8787e09f322e17c089cbe4d4af6f4dbf/jake.png" 183 | } 184 | }, 185 | "title": { 186 | "en-US": "jake" 187 | } 188 | } 189 | }, 190 | { 191 | "sys": { 192 | "space": { 193 | "sys": { 194 | "type": "Link", 195 | "linkType": "Space", 196 | "id": "y005y7p7nrqo" 197 | } 198 | }, 199 | "type": "Asset", 200 | "id": "2cMA1o04G42KGoQioOqqUA", 201 | "revision": 1, 202 | "createdAt": "2015-04-28T12:10:46.283Z", 203 | "updatedAt": "2015-04-28T12:10:46.283Z" 204 | }, 205 | "fields": { 206 | "title": { 207 | "en-US": "doge" 208 | }, 209 | "file": { 210 | "en-US": { 211 | "fileName": "doge.jpg", 212 | "contentType": "image/jpeg", 213 | "details": { 214 | "image": { 215 | "width": 5800, 216 | "height": 4350 217 | }, 218 | "size": 522943 219 | }, 220 | "url": "//images.contentful.com/y005y7p7nrqo/2cMA1o04G42KGoQioOqqUA/a43a19999ac4a5fd310d176ad40a5b14/doge.jpg" 221 | } 222 | } 223 | } 224 | } 225 | ], 226 | "nextSyncUrl": "http://cdn.contentful.com/spaces/y005y7p7nrqo/sync?sync_token=w5ZGw6JFwqZmVcKsE8Kow4grw45QdyZtXMOMIMKiwo0dMcOuwo3Di8KYwpzCh8Oxw6rDqcOSw5HCk37CvcOsFMKtwpPDkyAgw7wmaMKwXMO8A8OPJn83LxhrMsKRw49hwpTCkXHDvsKww6Y0wqotZMKLZMKcwpHDsj1g" 227 | } 228 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/vault/locales.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 2, 6 | "skip": 0, 7 | "limit": 1000, 8 | "items": [ 9 | { 10 | "code": "en-US", 11 | "default": true, 12 | "name": "U.S. English", 13 | "sys": { 14 | "id": "id1", 15 | "type": "Locale", 16 | "version": 1 17 | } 18 | }, 19 | { 20 | "code": "es-ES", 21 | "default": false, 22 | "name": "Spanish", 23 | "fallbackCode": "en-US", 24 | "sys": { 25 | "id": "id2", 26 | "type": "Locale", 27 | "version": 1 28 | } 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /tests-integration/src/test/resources/vault/types.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Array" 4 | }, 5 | "total": 4, 6 | "skip": 0, 7 | "limit": 100, 8 | "items": [ 9 | { 10 | "name": "Blob", 11 | "fields": [ 12 | { 13 | "name": "object", 14 | "id": "object", 15 | "type": "Object" 16 | } 17 | ], 18 | "description": "", 19 | "sys": { 20 | "space": { 21 | "sys": { 22 | "type": "Link", 23 | "linkType": "Space", 24 | "id": "y005y7p7nrqo" 25 | } 26 | }, 27 | "type": "ContentType", 28 | "id": "1HRG7uai2g8YMswwqoAaC8", 29 | "revision": 1, 30 | "createdAt": "2015-04-27T14:54:45.139Z", 31 | "updatedAt": "2015-04-27T14:54:45.139Z" 32 | } 33 | }, 34 | { 35 | "name": "Arrays", 36 | "fields": [ 37 | { 38 | "name": "symbols", 39 | "id": "symbols", 40 | "type": "Array", 41 | "items": { 42 | "type": "Symbol" 43 | } 44 | }, 45 | { 46 | "name": "assets", 47 | "id": "assets", 48 | "type": "Array", 49 | "items": { 50 | "type": "Link", 51 | "linkType": "Asset" 52 | } 53 | }, 54 | { 55 | "name": "blobs", 56 | "id": "blobs", 57 | "type": "Array", 58 | "items": { 59 | "type": "Link", 60 | "linkType": "Entry", 61 | "validations": [ 62 | { 63 | "linkContentType": [ 64 | "1HRG7uai2g8YMswwqoAaC8" 65 | ] 66 | } 67 | ] 68 | } 69 | } 70 | ], 71 | "displayField": null, 72 | "sys": { 73 | "space": { 74 | "sys": { 75 | "type": "Link", 76 | "linkType": "Space", 77 | "id": "y005y7p7nrqo" 78 | } 79 | }, 80 | "type": "ContentType", 81 | "id": "4rD4z2Ex0kEOgeWCWG4Se2", 82 | "revision": 6, 83 | "createdAt": "2015-04-29T13:24:31.565Z", 84 | "updatedAt": "2015-04-30T09:20:08.674Z" 85 | } 86 | }, 87 | { 88 | "name": "Text", 89 | "fields": [ 90 | { 91 | "name": "text", 92 | "id": "text", 93 | "type": "Text", 94 | "localized": true 95 | } 96 | ], 97 | "displayField": "text", 98 | "sys": { 99 | "space": { 100 | "sys": { 101 | "type": "Link", 102 | "linkType": "Space", 103 | "id": "y005y7p7nrqo" 104 | } 105 | }, 106 | "type": "ContentType", 107 | "id": "6yhJBtk1nUYq0iumy6gMY4", 108 | "revision": 1, 109 | "createdAt": "2015-05-11T13:23:02.564Z", 110 | "updatedAt": "2015-05-11T13:23:02.564Z" 111 | } 112 | }, 113 | { 114 | "name": "Bool", 115 | "fields": [ 116 | { 117 | "name": "value", 118 | "id": "value", 119 | "type": "Boolean" 120 | } 121 | ], 122 | "sys": { 123 | "space": { 124 | "sys": { 125 | "type": "Link", 126 | "linkType": "Space", 127 | "id": "y005y7p7nrqo" 128 | } 129 | }, 130 | "type": "ContentType", 131 | "id": "3o5klpTg9W6mssoMgeGMME", 132 | "revision": 1, 133 | "createdAt": "2015-07-06T15:10:18.572Z", 134 | "updatedAt": "2015-07-06T15:10:18.572Z" 135 | } 136 | } 137 | ] 138 | } --------------------------------------------------------------------------------