diff --git a/.gitignore b/.gitignore index 68fb68b2793d4f82646623398b8b5a0fbd754341..fdb0b633ee442629f8ea41a13fb4f7d4b33612da 100644 --- a/.gitignore +++ b/.gitignore @@ -24,18 +24,6 @@ local.properties .signing/ # User-specific configurations -.idea/libraries/ -.idea/workspace.xml -.idea/tasks.xml -.idea/.name -.idea/compiler.xml -.idea/encodings.xml -.idea/misc.xml -.idea/modules.xml -.idea/scopes/scope_settings.xml -.idea/vcs.xml -.idea/runConfigurations.xml -.idea/gradle.xml -.idea/caches/ +.idea/ *.iml diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml deleted file mode 100644 index f8b02f6243677a23a688b8ef9bfc9963e742cb24..0000000000000000000000000000000000000000 --- a/.idea/assetWizardSettings.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml deleted file mode 100644 index 8832b997e56d1706894019f5bdcf53f2dd3710b8..0000000000000000000000000000000000000000 --- a/.idea/codeStyleSettings.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 439e5b9e300fe20a04b2a680518c04aa486bcddd..0000000000000000000000000000000000000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c2b23e069e35ed634d687e17f731cc702..0000000000000000000000000000000000000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/copyright/Apache2.xml b/.idea/copyright/Apache2.xml deleted file mode 100644 index 75d18d28ec6149890c4e20e9aa6bcd7bf3e70e31..0000000000000000000000000000000000000000 --- a/.idea/copyright/Apache2.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index 53a32f12adee212e674e5300e590ab5bf8944193..0000000000000000000000000000000000000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/dictionaries/dictionary.xml b/.idea/dictionaries/dictionary.xml deleted file mode 100644 index 7db7138b1b13dfa42c4f215917cadf9a4840fc68..0000000000000000000000000000000000000000 --- a/.idea/dictionaries/dictionary.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - opentasks - subtask - subtasks - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index cc4c6fcb1aac3fd2481027d377858aeeccce4c91..0000000000000000000000000000000000000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index bd4a8dc1bf734df52b2f4acee9632ef4a1284b84..0000000000000000000000000000000000000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c395c3ecccbce4b934cd83e83698c4c7f6785e7c..0000000000000000000000000000000000000000 --- a/.travis.yml +++ /dev/null @@ -1,39 +0,0 @@ -language: android -sudo: false - -env: - - TZ=Europe/Berlin - -install: - - git config remote.origin.fetch +refs/heads/*:refs/remotes/origin/* - - git fetch --unshallow --tags - -android: - components: - - tools - - platform-tools - - tools - - build-tools-28.0.3 - - build-tools-29.0.2 - - build-tools-29.0.3 - - android-24 - - android-28 - - android-29 - - extra - - extra-android-m2repository - - sys-img-armeabi-v7a-android-24 - -# Emulator Management: Create, Start and Wait -before_script: - - android list targets - - echo no | android create avd --force -n test --target android-24 --abi armeabi-v7a - - QEMU_AUDIO_DRV=none emulator -avd test -no-window & - - android-wait-for-emulator - - adb shell input keyevent 82 & - -script: - - android list target - - ./gradlew check connectedAndroidTest - -after_script: - - cat /home/travis/build/dmfs/opentasks/opentasks/build/reports/lint-results.xml diff --git a/build.gradle b/build.gradle index 9c5ba578b0eb702b4eee51d6a28184bc476388f1..bec8b5aff6427739b8854787cac50ba60893fdc9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,35 @@ plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false + alias(libs.plugins.spotless) apply false } + +subprojects { + apply plugin: libs.plugins.spotless.get().pluginId + + spotless { + java { + target '**/src/**/*.java' + removeUnusedImports() + eclipse() + leadingSpacesToTabs(2) + leadingTabsToSpaces(4) + } + + format("xml") { + target("**/src/**/*.xml") + targetExclude("**/build/", ".idea/", "**/target/") + eclipseWtp('xml') + trimTrailingWhitespace() + leadingTabsToSpaces(4) + endWithNewline() + } + + groovyGradle { + target '*.gradle', '**/*.gradle', 'settings.gradle' + trimTrailingWhitespace() + leadingTabsToSpaces(4) + endWithNewline() + } + } +} \ No newline at end of file diff --git a/dmfs_eclipse_codestyle.xml b/dmfs_eclipse_codestyle.xml deleted file mode 100644 index ba19af5fd95164fbf76883be0a122792d9f7917e..0000000000000000000000000000000000000000 --- a/dmfs_eclipse_codestyle.xml +++ /dev/null @@ -1,579 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 553a6362c0438be3272c365eb50c2b10ddc17b42..e20b14747e6230f975efaf74296877d32fc0c375 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,6 +22,7 @@ retention-magic = "1.3" robolectric = "4.16" rxandroid = "2.1.1" rxjava = "2.2.21" +spotless = "8.1.0" xml-magic = "0.1.1" [libraries] @@ -57,3 +58,4 @@ xml-magic = { module = "org.dmfs:android-xml-magic", version.ref = "xml-magic" } [plugins] android-application = { id = "com.android.application", version.ref = "android-gradle-plugin" } android-library = { id = "com.android.library", version.ref = "android-gradle-plugin" } +spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } \ No newline at end of file diff --git a/gradlew b/gradlew index af6708ff229fda75da4f7cc4da4747217bac4d53..4f906e0c811fc9e230eb44819f509cd0627f2600 100755 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m"' +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -66,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -109,10 +126,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -138,19 +156,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 0f8d5937c4ad18feb44a19e55ad1e37cc159260f..ac1b06f93825db68fb0c0b5150917f340eaa5d02 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/opentasks-contract/build.gradle b/opentasks-contract/build.gradle index 2556a61cacf4aeeaa965c4539fbc47b940eac070..c618b1e08eb839ac9f18a611637f03bde4b334b0 100644 --- a/opentasks-contract/build.gradle +++ b/opentasks-contract/build.gradle @@ -13,17 +13,16 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { sourceCompatibility JavaVersion.VERSION_21 targetCompatibility JavaVersion.VERSION_21 } } - -dependencies { -} diff --git a/opentasks-contract/src/main/AndroidManifest.xml b/opentasks-contract/src/main/AndroidManifest.xml index 6506a14f9d62afecc05058f5c6054cd5e4242141..df350e743a509eb85bbaadf05f115037c3f46637 100644 --- a/opentasks-contract/src/main/AndroidManifest.xml +++ b/opentasks-contract/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/opentasks-contract/src/main/java/org/dmfs/tasks/contract/TaskContract.java b/opentasks-contract/src/main/java/org/dmfs/tasks/contract/TaskContract.java index 3ce329daaa1e0c36d02ac9cc6a5ae0b9dad3bb1c..aba42d2f631beeef4bcf768aa4c38228461ecf27 100644 --- a/opentasks-contract/src/main/java/org/dmfs/tasks/contract/TaskContract.java +++ b/opentasks-contract/src/main/java/org/dmfs/tasks/contract/TaskContract.java @@ -21,935 +21,931 @@ import android.content.Intent; import android.net.Uri; import android.provider.BaseColumns; import android.provider.SyncStateContract; - import java.util.ArrayList; import java.util.HashMap; import java.util.Map; - /** * Task contract. This class defines the interface to the task provider. + * *

* TODO: Add missing javadoc. - *

+ * *

* TODO: Specify extended properties - *

+ * *

* TODO: Add CONTENT_URI for the attachment store. - *

+ * *

* TODO: Also, we could use some refactoring... - *

* * @author Marten Gajda * @author Tobias Reinsch */ -public final class TaskContract -{ +public final class TaskContract { private static Map sUriFactories = new HashMap(4); - /** - * URI parameter to signal that the caller is a sync adapter. - */ + /** URI parameter to signal that the caller is a sync adapter. */ public static final String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter"; - /** - * URI parameter to signal the request of the extended properties of a task. - */ + /** URI parameter to signal the request of the extended properties of a task. */ public static final String LOAD_PROPERTIES = "load_properties"; - /** - * URI parameter to submit the account name of the account we operate on. - */ + /** URI parameter to submit the account name of the account we operate on. */ public static final String ACCOUNT_NAME = "account_name"; - /** - * URI parameter to submit the account type of the account we operate on. - */ + /** URI parameter to submit the account type of the account we operate on. */ public static final String ACCOUNT_TYPE = "account_type"; - /** - * Account name for local, unsynced task lists. - */ + /** Account name for local, unsynced task lists. */ public static final String LOCAL_ACCOUNT_NAME = "Local"; - /** - * Account type for local, unsynced task lists. - */ + /** Account type for local, unsynced task lists. */ public static final String LOCAL_ACCOUNT_TYPE = "org.dmfs.account.LOCAL"; /** - * Broadcast action that's sent when the task database has been initialized, either because the app was launched for the first time or because the app was + * Broadcast action that's sent when the task database has been initialized, + * either because the app was launched for the first time or because the app was * launched after the user cleared the app data. - *

- * The intent data represents the authority of the provider, the MIME type will be {@link #MIMETYPE_AUTHORITY}. + * + *

+ * The intent data represents the authority of the provider, the MIME type will + * be {@link #MIMETYPE_AUTHORITY}. */ public static final String ACTION_DATABASE_INITIALIZED = "org.dmfs.tasks.DATABASE_INITIALIZED"; /** - * A MIME type of an authority. Authorities itself don't seem to have a MIME type in Android, so we just use our own. + * A MIME type of an authority. Authorities itself don't seem to have a MIME + * type in Android, so we just use our own. */ - public static final String MIMETYPE_AUTHORITY = ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.org.dmfs.authority.mimetype"; + public static final String MIMETYPE_AUTHORITY = ContentResolver.CURSOR_DIR_BASE_TYPE + + "/vnd.org.dmfs.authority.mimetype"; /** - * The action of the broadcast that's send when a task becomes due. The intent data will be a {@link Uri} of the task that became due. + * The action of the broadcast that's send when a task becomes due. The intent + * data will be a {@link Uri} of the task that became due. */ public static final String ACTION_BROADCAST_TASK_DUE = "org.dmfs.android.tasks.TASK_DUE"; /** - * The action of the broadcast that's send when a task starts. The intent data will be a {@link Uri} of the task that has started. + * The action of the broadcast that's send when a task starts. The intent data + * will be a {@link Uri} of the task that has started. */ public static final String ACTION_BROADCAST_TASK_STARTING = "org.dmfs.android.tasks.TASK_START"; /** - * A Long extra that contains a timestamp of the event that's triggered. So this is either the timestamp of the start or due date of the task. + * A Long extra that contains a timestamp of the event that's triggered. So this + * is either the timestamp of the start or due date of the task. */ - public final static String EXTRA_TASK_TIMESTAMP = "org.dmfs.provider.tasks.extra.TIMESTAMP"; + public static final String EXTRA_TASK_TIMESTAMP = "org.dmfs.provider.tasks.extra.TIMESTAMP"; /** - * A Boolean extra to indicate that the event that was triggered is an all-day date. + * A Boolean extra to indicate that the event that was triggered is an all-day + * date. */ - public final static String EXTRA_TASK_ALLDAY = "org.dmfs.provider.tasks.extra.ALLDAY"; + public static final String EXTRA_TASK_ALLDAY = "org.dmfs.provider.tasks.extra.ALLDAY"; - /** - * A String extra containing the timezone id of the task. - */ - public final static String EXTRA_TASK_TIMEZONE = "org.dmfs.provider.tasks.extra.TIMEZONE"; + /** A String extra containing the timezone id of the task. */ + public static final String EXTRA_TASK_TIMEZONE = "org.dmfs.provider.tasks.extra.TIMEZONE"; - /** - * A String extra containing the title of the task. - */ - public final static String EXTRA_TASK_TITLE = "org.dmfs.provider.tasks.extra.TITLE"; + /** A String extra containing the title of the task. */ + public static final String EXTRA_TASK_TITLE = "org.dmfs.provider.tasks.extra.TITLE"; /** - * The name of the {@link Intent#ACTION_PROVIDER_CHANGED} extra that contains the {@link ArrayList} of {@link Uri}s that have been modified. This always - * goes along with an {@link #EXTRA_OPERATIONS} which contains a code for the operation executed on a Uri at the same index. + * The name of the {@link Intent#ACTION_PROVIDER_CHANGED} extra that contains + * the {@link ArrayList} of {@link Uri}s that have been modified. This always + * goes along with an {@link #EXTRA_OPERATIONS} which contains a code for the + * operation executed on a Uri at the same index. */ - public final static String EXTRA_OPERATIONS_URIS = "org.dmfs.tasks.OPERATIONS_URIS"; + public static final String EXTRA_OPERATIONS_URIS = "org.dmfs.tasks.OPERATIONS_URIS"; /** - * The name of the {@link Intent#ACTION_PROVIDER_CHANGED} extra that contains the {@link ArrayList} of provider operation codes. The following codes are + * The name of the {@link Intent#ACTION_PROVIDER_CHANGED} extra that contains + * the {@link ArrayList} of provider operation codes. The following codes are * used: + * *

    - *
  • 0 - for inserts
  • - *
  • 1 - for updates
  • - *
  • 2 - for deletes
  • + *
  • 0 - for inserts + *
  • 1 - for updates + *
  • 2 - for deletes *
*/ - public final static String EXTRA_OPERATIONS = "org.dmfs.tasks.OPERATIONS"; + public static final String EXTRA_OPERATIONS = "org.dmfs.tasks.OPERATIONS"; - - /** - * Private constructor to prevent instantiation. - */ - private TaskContract() - { + /** Private constructor to prevent instantiation. */ + private TaskContract() { } - /** - * A table provided for sync adapters to use for storing private sync state data. - *

- * Only sync adapters are allowed to access this table and they may access their own rows only. - *

- * Note that only one row per account will be stored. Updating or inserting a sync state for a specific account will override any previous sync state for + * A table provided for sync adapters to use for storing private sync state + * data. + * + *

+ * Only sync adapters are allowed to access this table and they may access their + * own rows only. + * + *

+ * Note that only one row per account will be stored. Updating or inserting a + * sync state for a specific account will override any previous sync state for * this account. */ - public static class SyncState implements SyncStateContract.Columns, BaseColumns - { - public final static String CONTENT_URI_PATH = "syncstate"; - + public static class SyncState implements SyncStateContract.Columns, BaseColumns { + public static final String CONTENT_URI_PATH = "syncstate"; /** * Get the sync state content {@link Uri} using the given authority. * * @param authority - * The authority. - * + * The authority. * @return A {@link Uri}. */ - public static Uri getContentUri(String authority) - { + public static Uri getContentUri(String authority) { return getUriFactory(authority).getUri(CONTENT_URI_PATH); } - } - /** * Get the base content {@link Uri} using the given authority. * * @param authority - * The authority. - * + * The authority. * @return A {@link Uri}. */ - public static Uri getContentUri(String authority) - { + public static Uri getContentUri(String authority) { return getUriFactory(authority).getUri(); } - /** - * A set of columns for synchronization purposes. These columns exist in {@link Tasks} and in {@link TaskLists} but have different meanings. Only sync + * A set of columns for synchronization purposes. These columns exist in + * {@link Tasks} and in {@link TaskLists} but have different meanings. Only sync * adapters are allowed to change these values. * * @author Marten Gajda */ - public interface CommonSyncColumns - { + public interface CommonSyncColumns { /** * A unique Sync ID as set by the sync adapter. + * *

* Value: String - *

*/ String _SYNC_ID = "_sync_id"; /** * Sync version as set by the sync adapter. + * *

* Value: String - *

*/ String SYNC_VERSION = "sync_version"; /** * Indicates that a task or a task list has been changed. + * *

* Value: Integer - *

*/ String _DIRTY = "_dirty"; /** * A general purpose column for the sync adapter. + * *

* Value: String - *

*/ String SYNC1 = "sync1"; /** * A general purpose column for the sync adapter. + * *

* Value: String - *

*/ String SYNC2 = "sync2"; /** * A general purpose column for the sync adapter. + * *

* Value: String - *

*/ String SYNC3 = "sync3"; /** * A general purpose column for the sync adapter. + * *

* Value: String - *

*/ String SYNC4 = "sync4"; /** * A general purpose column for the sync adapter. + * *

* Value: String - *

*/ String SYNC5 = "sync5"; /** * A general purpose column for the sync adapter. + * *

* Value: String - *

*/ String SYNC6 = "sync6"; /** * A general purpose column for the sync adapter. + * *

* Value: String - *

*/ String SYNC7 = "sync7"; /** * A general purpose column for the sync adapter. + * *

* Value: String - *

*/ String SYNC8 = "sync8"; - } - /** * Additional sync columns for task lists. * * @author Marten Gajda */ - public interface TaskListSyncColumns - { + public interface TaskListSyncColumns { /** * The name of the account this list belongs to. This field is write-once. + * *

* Value: String - *

*/ String ACCOUNT_NAME = "account_name"; /** * The type of the account this list belongs to. This field is write-once. + * *

* Value: String - *

*/ String ACCOUNT_TYPE = "account_type"; } - /** * Additional sync columns for tasks. * * @author Marten Gajda */ - public interface TaskSyncColumns - { + public interface TaskSyncColumns { /** * The UID of a task. This is field can be changed by a sync adapter only. + * *

* Value: String - *

*/ String _UID = "_uid"; /** - * Deleted flag of a task. This is set to 1 by the content provider when a task app deletes a task. The sync adapter has to remove the task - * again to finish the removal. This value is read-only. + * Deleted flag of a task. This is set to 1 by the content provider + * when a task app deletes a task. The sync adapter has to remove the task again + * to finish the removal. This value is read-only. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ String _DELETED = "_deleted"; } - /** * Data columns of task lists. * * @author Marten Gajda */ - public interface TaskListColumns - { + public interface TaskListColumns { /** * List ID. + * *

* Value: Long - *

+ * *

* read-only - *

*/ String _ID = "_id"; /** * The name of the task list. + * *

* Value: String - *

*/ String LIST_NAME = "list_name"; /** - * The color of this list as integer (0xaarrggbb). Only the sync adapter can change this. + * The color of this list as integer (0xaarrggbb). Only the sync adapter can + * change this. + * *

* Value: Integer - *

*/ String LIST_COLOR = "list_color"; /** - * The access level a user has on this list. This value is not used yet, sync adapters should set it to 0. + * The access level a user has on this list. This value is not used yet, + * sync adapters should set it to 0. + * *

* Value: Integer - *

*/ String ACCESS_LEVEL = "list_access_level"; /** * Indicates that a task list is set to be visible. + * *

* Value: Integer (0 or 1) - *

*/ String VISIBLE = "visible"; /** * Indicates that a task list is set to be synced. + * *

* Value: Integer (0 or 1) - *

*/ String SYNC_ENABLED = "sync_enabled"; /** * The email address of the list owner. + * *

* Value: String - *

*/ String OWNER = "list_owner"; - } - /** * The task list table holds one entry for each task list. * * @author Marten Gajda */ - public static final class TaskLists implements TaskListColumns, TaskListSyncColumns, CommonSyncColumns - { + public static final class TaskLists implements TaskListColumns, TaskListSyncColumns, CommonSyncColumns { public static final String CONTENT_URI_PATH = "tasklists"; - /** - * The default sort order. - */ + /** The default sort order. */ public static final String DEFAULT_SORT_ORDER = ACCOUNT_NAME + ", " + LIST_NAME; - /** - * An array of columns only a sync adapter is allowed to change. - */ - public static final String[] SYNC_ADAPTER_COLUMNS = new String[] { - ACCESS_LEVEL, _DIRTY, OWNER, SYNC1, SYNC2, SYNC3, SYNC4, SYNC5, SYNC6, SYNC7, SYNC8, - _SYNC_ID, SYNC_VERSION, }; - + /** An array of columns only a sync adapter is allowed to change. */ + public static final String[] SYNC_ADAPTER_COLUMNS = new String[]{ACCESS_LEVEL, _DIRTY, OWNER, SYNC1, SYNC2, + SYNC3, SYNC4, SYNC5, SYNC6, SYNC7, SYNC8, _SYNC_ID, SYNC_VERSION,}; /** * Get the task list content {@link Uri} using the given authority. * * @param authority - * The authority. - * + * The authority. * @return A {@link Uri}. */ - public static Uri getContentUri(String authority) - { + public static Uri getContentUri(String authority) { return getUriFactory(authority).getUri(CONTENT_URI_PATH); } - } - /** * Task data columns. Defines all the values a task can have at most once. * * @author Marten Gajda */ - public interface TaskColumns extends BaseColumns - { + public interface TaskColumns extends BaseColumns { /** * The row id of a task. This value is read-only + * *

* Value: Integer - *

*/ String _ID = "_id"; /** - * The local version number of this task. The only guarantee about the value is, it's incremented whenever the task changes (this includes any - * changes applied by sync adapters). + * The local version number of this task. The only guarantee about the value is, + * it's incremented whenever the task changes (this includes any changes applied + * by sync adapters). + * *

- * Note, there is no guarantee about how much it's incremented other than by at least 1. + * Note, there is no guarantee about how much it's incremented other than by at + * least 1. + * *

* Value: Integer + * *

* read-only */ String VERSION = "version"; /** - * The id of the list this task belongs to. This value is write-once and must not be null. + * The id of the list this task belongs to. This value is + * write-once and must not be null. + * *

* Value: Integer - *

*/ String LIST_ID = "list_id"; /** * The title of the task. + * *

* Value: String - *

*/ String TITLE = "title"; /** * The location of the task. + * *

* Value: String - *

*/ String LOCATION = "location"; /** - * A geographic location related to the task. The should be a string in the format "longitude,latitude". + * A geographic location related to the task. The should be a string in the + * format "longitude,latitude". + * *

* Value: String - *

*/ String GEO = "geo"; /** * The description of a task. + * *

* Value: String - *

*/ String DESCRIPTION = "description"; /** - * The URL iCalendar field for this task. Must be a valid URI if not null- + * The URL iCalendar field for this task. Must be a valid URI if not + * null- + * *

* Value: String - *

*/ String URL = "url"; /** * The email address of the organizer if any, {@code null} otherwise. + * *

* Value: String - *

*/ String ORGANIZER = "organizer"; /** - * The priority of a task. This is an Integer between zero and 9. Zero means there is no priority set. 1 is the highest priority and 9 the lowest. + * The priority of a task. This is an Integer between zero and 9. Zero means + * there is no priority set. 1 is the highest priority and 9 the lowest. + * *

* Value: Integer - *

*/ String PRIORITY = "priority"; - /** - * The default value of {@link #PRIORITY}. - */ + /** The default value of {@link #PRIORITY}. */ int PRIORITY_DEFAULT = 0; /** - * The classification of a task. This value must be either null or one of {@link #CLASSIFICATION_PUBLIC}, {@link #CLASSIFICATION_PRIVATE}, + * The classification of a task. This value must be either null or + * one of {@link #CLASSIFICATION_PUBLIC}, {@link #CLASSIFICATION_PRIVATE}, * {@link #CLASSIFICATION_CONFIDENTIAL}. + * *

* Value: Integer - *

*/ String CLASSIFICATION = "class"; - /** - * Classification value for public tasks. - */ + /** Classification value for public tasks. */ int CLASSIFICATION_PUBLIC = 0; - /** - * Classification value for private tasks. - */ + /** Classification value for private tasks. */ int CLASSIFICATION_PRIVATE = 1; - /** - * Classification value for confidential tasks. - */ + /** Classification value for confidential tasks. */ int CLASSIFICATION_CONFIDENTIAL = 2; - /** - * Default value of {@link #CLASSIFICATION}. - */ + /** Default value of {@link #CLASSIFICATION}. */ Integer CLASSIFICATION_DEFAULT = null; /** - * Date of completion of this task in milliseconds since the epoch or {@code null} if this task has not been completed yet. + * Date of completion of this task in milliseconds since the epoch or + * {@code null} if this task has not been completed yet. + * *

* Value: Long - *

*/ String COMPLETED = "completed"; /** * Indicates that the date of completion is an all-day date. + * *

* Value: Integer - *

*/ String COMPLETED_IS_ALLDAY = "completed_is_allday"; /** - * A number between 0 and 100 that indicates the progress of the task or null. + * A number between 0 and 100 that indicates the progress of the task or + * null. + * *

* Value: Integer (0-100) - *

*/ String PERCENT_COMPLETE = "percent_complete"; /** - * The status of this task. One of {@link #STATUS_NEEDS_ACTION},{@link #STATUS_IN_PROCESS}, {@link #STATUS_COMPLETED}, {@link #STATUS_CANCELLED}. + * The status of this task. One of + * {@link #STATUS_NEEDS_ACTION},{@link #STATUS_IN_PROCESS}, + * {@link #STATUS_COMPLETED}, {@link #STATUS_CANCELLED}. + * *

* Value: Integer - *

*/ String STATUS = "status"; - /** - * A specific status indicating that nothing has been done yet. - */ + /** A specific status indicating that nothing has been done yet. */ int STATUS_NEEDS_ACTION = 0; - /** - * A specific status indicating that some work has been done. - */ + /** A specific status indicating that some work has been done. */ int STATUS_IN_PROCESS = 1; - /** - * A specific status indicating that the task is completed. - */ + /** A specific status indicating that the task is completed. */ int STATUS_COMPLETED = 2; - /** - * A specific status indicating that the task has been cancelled. - */ + /** A specific status indicating that the task has been cancelled. */ int STATUS_CANCELLED = 3; - /** - * The default status is "needs action". - */ + /** The default status is "needs action". */ int STATUS_DEFAULT = STATUS_NEEDS_ACTION; /** - * A flag that indicates a task is new (i.e. not work has been done yet). This flag is read-only. Its value is 1 when - * {@link #STATUS} equals {@link #STATUS_NEEDS_ACTION} and 0 otherwise. + * A flag that indicates a task is new (i.e. not work has been done yet). This + * flag is read-only. Its value is 1 when + * {@link #STATUS} equals {@link #STATUS_NEEDS_ACTION} and 0 + * otherwise. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ String IS_NEW = "is_new"; /** - * A flag that indicates a task is closed (no more work has to be done). This flag is read-only. Its value is 1 when - * {@link #STATUS} equals {@link #STATUS_COMPLETED} or {@link #STATUS_CANCELLED} and 0 otherwise. + * A flag that indicates a task is closed (no more work has to be done). This + * flag is read-only. Its value is 1 when + * {@link #STATUS} equals {@link #STATUS_COMPLETED} or {@link #STATUS_CANCELLED} + * and 0 otherwise. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ String IS_CLOSED = "is_closed"; /** - * An individual color for this task in the format 0xaarrggbb or {@code null} to use {@link TaskListColumns#LIST_COLOR} instead. + * An individual color for this task in the format 0xaarrggbb or {@code null} to + * use {@link TaskListColumns#LIST_COLOR} instead. + * *

* Value: Integer - *

*/ String TASK_COLOR = "task_color"; /** * When this task starts in milliseconds since the epoch. + * *

* Value: Long - *

*/ String DTSTART = "dtstart"; - /** - * Boolean: flag that indicates that this is an all-day task. - */ + /** Boolean: flag that indicates that this is an all-day task. */ String IS_ALLDAY = "is_allday"; /** * When this task has been created in milliseconds since the epoch. + * *

* Value: Long - *

*/ String CREATED = "created"; /** - * When this task had been modified the last time in milliseconds since the epoch. + * When this task had been modified the last time in milliseconds since the + * epoch. + * *

* Value: Long - *

*/ String LAST_MODIFIED = "last_modified"; /** - * String: An Olson Id of the time zone of this task. If this value is null, it's automatically replaced by the local time zone. + * String: An Olson Id of the time zone of this task. If this value is + * null, it's automatically replaced by the local time zone. */ String TZ = "tz"; /** - * When this task is due in milliseconds since the epoch. Only one of {@link #DUE} or {@link #DURATION} must be supplied (or none of both if the task - * has no due date). + * When this task is due in milliseconds since the epoch. Only one of + * {@link #DUE} or {@link #DURATION} must be supplied (or none of both if the + * task has no due date). + * *

* Value: Long - *

*/ String DUE = "due"; /** - * The duration of this task. Only one of {@link #DUE} or {@link #DURATION} must be supplied (or none of both if the task has no due date). Setting a - * {@link #DURATION} is not allowed when {@link #DTSTART} is null. The Value must be a duration string as in RFC 5545 Section 3.3.6. + * The duration of this task. Only one of {@link #DUE} or {@link #DURATION} must + * be supplied (or none of both if the task has no due date). Setting a + * {@link #DURATION} is not allowed when {@link #DTSTART} is null. + * The Value must be a duration string as in + * RFC 5545 Section + * 3.3.6. + * *

* Value: String - *

*/ String DURATION = "duration"; /** - * A comma separated list of time Strings in RFC 5545 format (see RFC 5545 Section 3.3.4 - * and RFC 5545 Section 3.3.5) that contains dates of instances of e recurring task. - * All-day tasks must use the DATE format specified in section 3.3.4 of RFC 5545. + * A comma separated list of time Strings in RFC 5545 format (see + * RFC 5545 Section + * 3.3.4 and RFC + * 5545 Section 3.3.5) that contains dates of instances of e recurring task. + * All-day tasks must use the DATE format specified in section 3.3.4 of RFC + * 5545. + * *

* This value must be {@code null} for exception instances. + * *

* Value: String - *

*/ String RDATE = "rdate"; /** - * A comma separated list of time Strings in RFC 5545 format (see RFC 5545 Section 3.3.4 - * and RFC 5545 Section 3.3.5) that contains dates of exceptions of a recurring task. - * All-day tasks must use the DATE format specified in section 3.3.4 of RFC 5545. + * A comma separated list of time Strings in RFC 5545 format (see + * RFC 5545 Section + * 3.3.4 and RFC + * 5545 Section 3.3.5) that contains dates of exceptions of a recurring + * task. All-day tasks must use the DATE format specified in section 3.3.4 of + * RFC 5545. + * *

* This value must be {@code null} for exception instances. + * *

* Value: String - *

*/ String EXDATE = "exdate"; /** - * A recurrence rule as specified in RFC 5545 Section 3.3.10. + * A recurrence rule as specified in + * RFC 5545 Section + * 3.3.10. + * *

* This value must be {@code null} for exception instances. + * *

* Value: String - *

*/ String RRULE = "rrule"; /** - * The _sync_id of the original event if this is an exception, null otherwise. Only one of {@link #ORIGINAL_INSTANCE_SYNC_ID} or - * {@link #ORIGINAL_INSTANCE_ID} must be set if this task is an exception. The other one will be updated by the content provider. + * The _sync_id of the original event if this is an exception, null + * otherwise. Only one of {@link #ORIGINAL_INSTANCE_SYNC_ID} or + * {@link #ORIGINAL_INSTANCE_ID} must be set if this task is an exception. The + * other one will be updated by the content provider. + * *

* Value: String - *

*/ String ORIGINAL_INSTANCE_SYNC_ID = "original_instance_sync_id"; /** - * The row id of the original event if this is an exception, null otherwise. Only one of {@link #ORIGINAL_INSTANCE_SYNC_ID} or - * {@link #ORIGINAL_INSTANCE_ID} must be set if this task is an exception. The other one will be updated by the content provider. + * The row id of the original event if this is an exception, null + * otherwise. Only one of {@link #ORIGINAL_INSTANCE_SYNC_ID} or + * {@link #ORIGINAL_INSTANCE_ID} must be set if this task is an exception. The + * other one will be updated by the content provider. + * *

* Value: Long - *

*/ String ORIGINAL_INSTANCE_ID = "original_instance_id"; /** - * The time in milliseconds since the Epoch of the original instance that is overridden by this instance or null if this task is not a + * The time in milliseconds since the Epoch of the original instance that is + * overridden by this instance or null if this task is not a * recurring instance. + * *

* Value: Long - *

*/ String ORIGINAL_INSTANCE_TIME = "original_instance_time"; /** * A flag indicating that the original instance was an all-day task. + * *

* Value: Integer - *

*/ String ORIGINAL_INSTANCE_ALLDAY = "original_instance_allday"; /** - * The row id of the parent task. null if the task has no parent task. + * The row id of the parent task. null if the task has no parent + * task. + * *

- * Note, when writing this value the task {@link Property.Relation} properties are updated accordingly. Any parent or child relations which - * make this a child of another task are deleted and a new {@link Property.Relation#RELTYPE_PARENT} relation pointing to the new parent is created. - * Be aware that Siblings will be split, i.e. they are not moved to the new parent. Currently this might cause siblings to become orphans if they - * don't have a parent-child relationship. This behavior may change in future version. - *

+ * Note, when writing this value the task {@link Property.Relation} properties + * are updated accordingly. Any parent or child relations which make this a + * child of another task are deleted and a new + * {@link Property.Relation#RELTYPE_PARENT} relation pointing to the new parent + * is created. Be aware that Siblings will be split, i.e. they are not moved to + * the new parent. Currently this might cause siblings to become orphans if they + * don't have a parent-child relationship. This behavior may change in future + * version. * *

* Value: Long - *

*/ String PARENT_ID = "parent_id"; /** * The sorting of this task under it's parent task. + * *

* Value: String - *

*/ String SORTING = "sorting"; /** - * Indicates how many alarms a task has. 0 means the task has no alarms. This field is read only as it's set automatically. + * Indicates how many alarms a task has. 0 means the task has no + * alarms. This field is read only as it's set automatically. + * *

- * Value: Integer - *

- * Read-only + * Value: Integer Read-only */ String HAS_ALARMS = "has_alarms"; /** - * Indicates that this task has extended properties like attachments, alarms or relations. This field is read only as it's set automatically. + * Indicates that this task has extended properties like attachments, alarms or + * relations. This field is read only as it's set automatically. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ String HAS_PROPERTIES = "has_properties"; /** - * Indicates that this task has been pinned to the notification area. This flag is moved to the exception when an exception for the first instance of a - * recurring task is created. That means, if you edit a pinned recurring task, the pinned flag is moved to the exception and cleared from the master - * task. + * Indicates that this task has been pinned to the notification area. This flag + * is moved to the exception when an exception for the first instance of a + * recurring task is created. That means, if you edit a pinned recurring task, + * the pinned flag is moved to the exception and cleared from the master task. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ String PINNED = "pinned"; } - /** * Columns that are valid in a search query. * * @author Marten Gajda */ - public interface TaskSearchColumns - { + public interface TaskSearchColumns { /** - * The score of a task in a search result. It's an indicator for the relevance of the task. Value is in (0, 1.0] where 0 would be "no relevance" at all + * The score of a task in a search result. It's an indicator for the relevance + * of the task. Value is in (0, 1.0] where 0 would be "no relevance" at all * (though the result doesn't contain such tasks). + * *

* Value: Float - *

*/ String SCORE = "score"; } - /** * The task table stores the data of all tasks. * * @author Marten Gajda */ - public static final class Tasks implements TaskColumns, CommonSyncColumns, TaskSyncColumns, TaskSearchColumns - { + public static final class Tasks implements TaskColumns, CommonSyncColumns, TaskSyncColumns, TaskSearchColumns { /** - * The name of the account the task belongs to. This is auto-derived from the list the task belongs to. Do not write this value here. + * The name of the account the task belongs to. This is auto-derived from the + * list the task belongs to. Do not write this value here. + * *

* Value: String - *

+ * *

* read-only - *

*/ public static final String ACCOUNT_NAME = TaskLists.ACCOUNT_NAME; /** - * The type of the account the task belongs to. This is auto-derived from the list the task belongs to. Do not write this value here. + * The type of the account the task belongs to. This is auto-derived from the + * list the task belongs to. Do not write this value here. + * *

* Value: String - *

+ * *

* read-only - *

*/ public static final String ACCOUNT_TYPE = TaskLists.ACCOUNT_TYPE; /** - * The name of the list this task belongs to as integer (0xaarrggbb). This is auto-derived from the list the task belongs to. Do not write this value - * here. + * The name of the list this task belongs to as integer (0xaarrggbb). This is + * auto-derived from the list the task belongs to. Do not write this value here. + * *

* Value: String - *

+ * *

* read-only - *

*/ public static final String LIST_NAME = TaskLists.LIST_NAME; + /** - * The color of the list this task belongs to as integer (0xaarrggbb). This is auto-derived from the list the task belongs to. Do not write this value - * here. To change the color of an individual task use {@code TASK_COLOR} instead. + * The color of the list this task belongs to as integer (0xaarrggbb). This is + * auto-derived from the list the task belongs to. Do not write this value here. + * To change the color of an individual task use {@code TASK_COLOR} instead. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ public static final String LIST_COLOR = TaskLists.LIST_COLOR; /** - * The owner of the list this task belongs. This is auto-derived from the list the task belongs to. Do not write this value here. + * The owner of the list this task belongs. This is auto-derived from the list + * the task belongs to. Do not write this value here. + * *

* Value: String - *

+ * *

* read-only - *

*/ public static final String LIST_OWNER = TaskLists.OWNER; /** - * The access level of the list this task belongs. This is auto-derived from the list the task belongs to. Do not write this value here. + * The access level of the list this task belongs. This is auto-derived from the + * list the task belongs to. Do not write this value here. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ public static final String LIST_ACCESS_LEVEL = TaskLists.ACCESS_LEVEL; /** - * The visibility of the list this task belongs. This is auto-derived from the list the task belongs to. Do not write this value here. + * The visibility of the list this task belongs. This is auto-derived from the + * list the task belongs to. Do not write this value here. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ public static final String VISIBLE = "visible"; @@ -961,260 +957,370 @@ public final class TaskContract public static final String DEFAULT_SORT_ORDER = DUE; - public static final String[] SYNC_ADAPTER_COLUMNS = new String[] { - _DIRTY, SYNC1, SYNC2, SYNC3, SYNC4, SYNC5, SYNC6, SYNC7, SYNC8, _SYNC_ID, - SYNC_VERSION, }; - + public static final String[] SYNC_ADAPTER_COLUMNS = new String[]{_DIRTY, SYNC1, SYNC2, SYNC3, SYNC4, SYNC5, + SYNC6, SYNC7, SYNC8, _SYNC_ID, SYNC_VERSION,}; /** * Get the tasks content {@link Uri} using the given authority. * * @param authority - * The authority. - * + * The authority. * @return A {@link Uri}. */ - public static Uri getContentUri(String authority) - { + public static Uri getContentUri(String authority) { return getUriFactory(authority).getUri(CONTENT_URI_PATH); } - - public static Uri getSearchUri(String authority, String query) - { + public static Uri getSearchUri(String authority, String query) { Uri.Builder builder = getUriFactory(authority).getUri(SEARCH_URI_PATH).buildUpon(); builder.appendQueryParameter(SEARCH_QUERY_PARAMETER, Uri.encode(query)); return builder.build(); } } - /** * Columns of a task instance. * * @author Yannic Ahrens * @author Marten Gajda */ - public interface InstanceColumns - { + public interface InstanceColumns { /** * _ID of task this instance belongs to. + * *

* Value: Long - *

*/ String TASK_ID = "task_id"; /** - * The start date of an instance in milliseconds since the epoch or null if the instance has no start date. At present this is read only. + * The start date of an instance in milliseconds since the epoch or + * null if the instance has no start date. At present this is read + * only. + * *

* Value: Long - *

*/ String INSTANCE_START = "instance_start"; /** - * The due date of an instance in milliseconds since the epoch or null if the instance has no due date. At present this is read only. + * The due date of an instance in milliseconds since the epoch or + * null if the instance has no due date. At present this is read + * only. + * *

* Value: Long - *

*/ String INSTANCE_DUE = "instance_due"; /** - * This column should be used in an order clause to sort instances by start date. The only guarantee about the values in this column is the sort order. + * This column should be used in an order clause to sort instances by start + * date. The only guarantee about the values in this column is the sort order. * Don't make any other assumptions about the value. + * *

* Value: Long - *

+ * *

* read-only - *

*/ String INSTANCE_START_SORTING = "instance_start_sorting"; /** - * This column should be used in an order clause to sort instances by due date. The only guarantee about the values in this column is the sort order. - * Don't make any other assumptions about the value. + * This column should be used in an order clause to sort instances by due date. + * The only guarantee about the values in this column is the sort order. Don't + * make any other assumptions about the value. + * *

* Value: Long - *

+ * *

* read-only - *

*/ String INSTANCE_DUE_SORTING = "instance_due_sorting"; /** - * The duration of an instance in milliseconds or null if the instance has only one of start or due date or none of both. At present this + * The duration of an instance in milliseconds or null if the + * instance has only one of start or due date or none of both. At present this * is read only. + * *

* Value: Long - *

*/ String INSTANCE_DURATION = "instance_duration"; /** - * The start of the original instance as specified in the master task. For non-recurring task instances this is {@code null}. + * The start of the original instance as specified in the master task. For + * non-recurring task instances this is {@code null}. + * *

- * For recurring tasks, these are the timestamps which have been derived from the recurrence rule or dates, except those specified as exdates. + * For recurring tasks, these are the timestamps which have been derived from + * the recurrence rule or dates, except those specified as exdates. */ String INSTANCE_ORIGINAL_TIME = "instance_original_time"; /** - * The distance of the instance from the current one. For closed instances this is always {@code -1}, for the current instance this is {@code 0}. For - * the instance after the current one this is {@code 1}, for the instance after that one it's {@code 2}, etc.. + * The distance of the instance from the current one. For closed instances this + * is always {@code + * -1}, for the current instance this is {@code 0}. For the instance after the + * current one this is {@code 1}, for the instance after that one it's + * {@code 2}, etc.. + * *

* Value: Integer + * *

* read-only */ String DISTANCE_FROM_CURRENT = "distance_from_current"; } - /** - * A table containing one entry per task instance. This table is writable in order to allow modification of single instances of a task. Write operations to - * this table will be converted into operations on overrides and forwarded to the task table. + * A table containing one entry per task instance. This table is writable in + * order to allow modification of single instances of a task. Write operations + * to this table will be converted into operations on overrides and forwarded to + * the task table. + * *

- * Note: The {@link #DTSTART}, {@link #DUE} values of instances of recurring tasks represent the actual instance values, i.e. they are different for each + * Note: The {@link #DTSTART}, {@link #DUE} values of instances of recurring + * tasks represent the actual instance values, i.e. they are different for each * instance ({@link #DURATION} is always {@code null}). + * *

- * Also, none of the instances are recurring themselves, so {@link #RRULE}, {@link #RDATE} and {@link #EXDATE} are always {@code null}. + * Also, none of the instances are recurring themselves, so {@link #RRULE}, + * {@link #RDATE} and {@link #EXDATE} are always {@code null}. + * *

* TODO: Insert all instances of recurring tasks. + * *

* The following operations are supported: + * *

+ * *

Insert

+ * *

- * Note, the data of an insert must not contain the fields {@link #RRULE}, {@link #RDATE} or {@link #EXDATE}. If the new instance belongs to an existing - * task the data must contain the fields {@link #ORIGINAL_INSTANCE_ID} and {@link #ORIGINAL_INSTANCE_TIME}. Also note, this table supports writing {@link - * #DURATION} (if the instance has a {@link #DTSTART}), but reading it back will always return a {@code null} {@link #DURATION} and a non-{@code null} - * {@link #DUE} date. Reading the task in the tasks table will, however, return the original {@link #DURATION}. + * Note, the data of an insert must not contain the fields {@link #RRULE}, + * {@link #RDATE} or {@link #EXDATE}. If the new instance belongs to an existing + * task the data must contain the fields {@link #ORIGINAL_INSTANCE_ID} and + * {@link #ORIGINAL_INSTANCE_TIME}. Also note, this table supports writing + * {@link #DURATION} (if the instance has a {@link #DTSTART}), but reading it + * back will always return a {@code null} {@link #DURATION} and a + * non-{@code null} {@link #DUE} date. Reading the task in the tasks table will, + * however, return the original {@link #DURATION}. + * *

- * If there already is an instance (with or without override) for the given {@link #ORIGINAL_INSTANCE_ID} and {@link #ORIGINAL_INSTANCE_TIME} an exception - * is thrown. + * If there already is an instance (with or without override) for the given + * {@link #ORIGINAL_INSTANCE_ID} and {@link #ORIGINAL_INSTANCE_TIME} an + * exception is thrown. + * *

- * + * + * + * + * + * + *
ORIGINAL_INSTANCE_ID valueResult
absent or emptyA new non-recurring task is created with the given - * values.
a valid {@link Tasks} row {@code _ID}An {@link #RDATE} for the given {@link #ORIGINAL_INSTANCE_TIME} time is added to - * the given master task, any {@link #EXDATE} for this time is removed. The task is inserted as an override to the given master. No fields are inherited - * though. {@link #ORIGINAL_INSTANCE_ALLDAY} will be set to {@link #IS_ALLDAY} of the master. + * + * + * + * + * + * + * + * + * + * + * + * + *
ORIGINAL_INSTANCE_ID valueResult
absent or emptyA new non-recurring task is created with the given values.
a valid {@link Tasks} row {@code _ID}An {@link #RDATE} for the given {@link #ORIGINAL_INSTANCE_TIME} time is + * added to the given master task, any {@link #EXDATE} for this time is removed. + * The task is inserted as an override to the given master. No fields are + * inherited though. {@link #ORIGINAL_INSTANCE_ALLDAY} will be set to + * {@link #IS_ALLDAY} of the master. *

- * Note, if the given master is non-recurring, this operation will turn it into a recurring task.

invalid {@link Tasks} row {@code - * _ID}An exception is thrown.
+ * Note, if the given master is non-recurring, this operation will turn it into + * a recurring task.
invalid {@link Tasks} row {@code + * _ID}An exception is thrown.
+ * *

+ * *

Update

+ * *

- * Note, the data of an update must not contain any fields related to recurrence ({@link #RRULE}, {@link #RDATE}, {@link #EXDATE}, {@link - * #ORIGINAL_INSTANCE_ID}, {@link #ORIGINAL_INSTANCE_TIME} and {@link #ORIGINAL_INSTANCE_ALLDAY}). Also note, this table supports writing {@link #DURATION} - * (if the instance has a {@link #DTSTART}), but reading it back will always return a {@code null} {@link #DURATION} and a non-{@code null} {@link #DUE} - * date. Reading the task in the tasks table will, however, return the original {@link #DURATION}. + * Note, the data of an update must not contain any fields related to recurrence + * ({@link #RRULE}, {@link #RDATE}, {@link #EXDATE}, + * {@link #ORIGINAL_INSTANCE_ID}, {@link #ORIGINAL_INSTANCE_TIME} and + * {@link #ORIGINAL_INSTANCE_ALLDAY}). Also note, this table supports writing + * {@link #DURATION} (if the instance has a {@link #DTSTART}), but reading it + * back will always return a {@code null} {@link #DURATION} and a + * non-{@code null} {@link #DUE} date. Reading the task in the tasks table will, + * however, return the original {@link #DURATION}. + * *

- * - *
Target task typeResult
Recurring master taskA new override is created with the given data.

Note, - * any fields which are not provided are inherited from the master, except for {@link #DTSTART} and {@link #DUE} which will be inherited from the instance - * and {@link #DURATION}, {@link #RRULE}, {@link #RDATE} and {@link #EXDATE} which are set to {@code null}. {@link #ORIGINAL_INSTANCE_ID}, {@link - * #ORIGINAL_INSTANCE_TIME} and {@link #ORIGINAL_INSTANCE_ALLDAY} will be set accordingly.

Single instance taskThe task is - * updated with the given values.
Recurrence override with existing masterThe task is updated with the given values.
Recurrence override without existing masterThe task is updated with the given values.
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Target task typeResult
Recurring master taskA new override is created with the given data. + *

+ * Note, any fields which are not provided are inherited from the master, except + * for {@link #DTSTART} and {@link #DUE} which will be inherited from the + * instance and {@link #DURATION}, {@link #RRULE}, {@link #RDATE} and + * {@link #EXDATE} which are set to {@code null}. {@link #ORIGINAL_INSTANCE_ID}, + * {@link #ORIGINAL_INSTANCE_TIME} and {@link #ORIGINAL_INSTANCE_ALLDAY} will be + * set accordingly.

Single instance taskThe task is updated with the given values.
Recurrence override with existing masterThe task is updated with the given values.
Recurrence override without existing masterThe task is updated with the given values.
+ * *

+ * *

Delete

+ * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Target task typeResult
Recurring master taskAn {@link #EXDATE} for this instance is added, any {@link #RDATE} for + * this instance is removed. The instance row is removed. *

- * - * - *
Target task typeResult
Recurring master taskAn {@link #EXDATE} for this instance is added, any {@link - * #RDATE} for this instance is removed. The instance row is removed.

TODO: mark the task deleted if the remaining recurrence set is empty

Single instance taskThe {@link Tasks#_DELETED} flag of the task is set.
Recurrence override with existing - * masterThe {@link Tasks#_DELETED} flag of the override is set, an {@link #EXDATE} for this instance is added to the master, any {@link #RDATE} - * for this instance is removed from the master. TODO: mark the master deleted if the remaining recurrence set of the master is empty
Recurrence override without existing masterThe {@link Tasks#_DELETED} flag of the task is set.
+ * TODO: mark the task deleted if the remaining recurrence set is empty

Single instance taskThe {@link Tasks#_DELETED} flag of the task is set.
Recurrence override with existing masterThe {@link Tasks#_DELETED} flag of the override is set, an + * {@link #EXDATE} for this instance is added to the master, any {@link #RDATE} + * for this instance is removed from the master. TODO: mark the master deleted + * if the remaining recurrence set of the master is empty
Recurrence override without existing masterThe {@link Tasks#_DELETED} flag of the task is set.
* * @author Yannic Ahrens * @author Marten Gajda */ - public static final class Instances implements TaskColumns, InstanceColumns - { + public static final class Instances implements TaskColumns, InstanceColumns { /** - * The name of the account the task belongs to. This is auto-derived from the list the task belongs to. Do not write this value here. + * The name of the account the task belongs to. This is auto-derived from the + * list the task belongs to. Do not write this value here. + * *

* Value: String - *

+ * *

* read-only - *

*/ public static final String ACCOUNT_NAME = TaskLists.ACCOUNT_NAME; /** - * The type of the account the task belongs to. This is auto-derived from the list the task belongs to. Do not write this value here. + * The type of the account the task belongs to. This is auto-derived from the + * list the task belongs to. Do not write this value here. + * *

* Value: String - *

+ * *

* read-only - *

*/ public static final String ACCOUNT_TYPE = TaskLists.ACCOUNT_TYPE; /** - * The name of the list this task belongs to as integer (0xaarrggbb). This is auto-derived from the list the task belongs to. Do not write this value - * here. + * The name of the list this task belongs to as integer (0xaarrggbb). This is + * auto-derived from the list the task belongs to. Do not write this value here. + * *

* Value: String - *

+ * *

* read-only - *

*/ public static final String LIST_NAME = TaskLists.LIST_NAME; + /** - * The color of the list this task belongs to as integer (0xaarrggbb). This is auto-derived from the list the task belongs to. Do not write this value - * here. To change the color of an individual task use {@code TASK_COLOR} instead. + * The color of the list this task belongs to as integer (0xaarrggbb). This is + * auto-derived from the list the task belongs to. Do not write this value here. + * To change the color of an individual task use {@code TASK_COLOR} instead. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ public static final String LIST_COLOR = TaskLists.LIST_COLOR; /** - * The owner of the list this task belongs. This is auto-derived from the list the task belongs to. Do not write this value here. + * The owner of the list this task belongs. This is auto-derived from the list + * the task belongs to. Do not write this value here. + * *

* Value: String - *

+ * *

* read-only - *

*/ public static final String LIST_OWNER = TaskLists.OWNER; /** - * The access level of the list this task belongs. This is auto-derived from the list the task belongs to. Do not write this value here. + * The access level of the list this task belongs. This is auto-derived from the + * list the task belongs to. Do not write this value here. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ public static final String LIST_ACCESS_LEVEL = TaskLists.ACCESS_LEVEL; /** - * The visibility of the list this task belongs. This is auto-derived from the list the task belongs to. Do not write this value here. + * The visibility of the list this task belongs. This is auto-derived from the + * list the task belongs to. Do not write this value here. + * *

* Value: Integer - *

+ * *

* read-only - *

*/ public static final String VISIBLE = "visible"; /** * Flag indicating that ths is an instance of a recurring task. + * *

* Value: Integer + * *

* read-only */ @@ -1224,32 +1330,28 @@ public final class TaskContract public static final String DEFAULT_SORT_ORDER = INSTANCE_DUE_SORTING; - /** * Get the instances content {@link Uri} using the given authority. * * @param authority - * The authority. - * + * The authority. * @return A {@link Uri}. */ - public static Uri getContentUri(String authority) - { + public static Uri getContentUri(String authority) { return getUriFactory(authority).getUri(CONTENT_URI_PATH); } - } - /** * Available values in Categories. + * *

- * Categories are per account. It's up to the front-end to ensure consistency of category colors across accounts. + * Categories are per account. It's up to the front-end to ensure consistency of + * category colors across accounts. * * @author Marten Gajda */ - public interface CategoriesColumns - { + public interface CategoriesColumns { String _ID = "_id"; @@ -1262,33 +1364,25 @@ public final class TaskContract String COLOR = "color"; } - - public static final class Categories implements CategoriesColumns - { + public static final class Categories implements CategoriesColumns { public static final String CONTENT_URI_PATH = "categories"; public static final String DEFAULT_SORT_ORDER = NAME; - /** * Get the categories content {@link Uri} using the given authority. * * @param authority - * The authority. - * + * The authority. * @return A {@link Uri}. */ - public static Uri getContentUri(String authority) - { + public static Uri getContentUri(String authority) { return getUriFactory(authority).getUri(CONTENT_URI_PATH); } - } - - public interface AlarmsColumns - { + public interface AlarmsColumns { String ALARM_ID = "alarm_id"; String LAST_TRIGGER = "last_trigger"; @@ -1296,31 +1390,23 @@ public final class TaskContract String NEXT_TRIGGER = "next_trigger"; } - - public static final class Alarms implements AlarmsColumns - { + public static final class Alarms implements AlarmsColumns { public static final String CONTENT_URI_PATH = "alarms"; - /** * Get the alarms content {@link Uri} using the given authority. * * @param authority - * The authority. - * + * The authority. * @return A {@link Uri}. */ - public static Uri getContentUri(String authority) - { + public static Uri getContentUri(String authority) { return getUriFactory(authority).getUri(CONTENT_URI_PATH); } - } - - public interface PropertySyncColumns - { + public interface PropertySyncColumns { String SYNC1 = "prop_sync1"; String SYNC2 = "prop_sync2"; @@ -1338,9 +1424,7 @@ public final class TaskContract String SYNC8 = "prop_sync8"; } - - public interface PropertyColumns - { + public interface PropertyColumns { String PROPERTY_ID = "property_id"; @@ -1383,112 +1467,98 @@ public final class TaskContract String DATA15 = "data15"; } - - public static final class Properties implements PropertySyncColumns, PropertyColumns - { + public static final class Properties implements PropertySyncColumns, PropertyColumns { public static final String CONTENT_URI_PATH = "properties"; public static final String DEFAULT_SORT_ORDER = DATA0; - /** * Get the properties content {@link Uri} using the given authority. * * @param authority - * The authority. - * + * The authority. * @return A {@link Uri}. */ - public static Uri getContentUri(String authority) - { + public static Uri getContentUri(String authority) { return getUriFactory(authority).getUri(CONTENT_URI_PATH); } - } - - public interface Property - { + public interface Property { /** * Attached documents. + * *

- * Note: Attachments are write-once. To change an attachment you'll have to remove and re-add it. - *

+ * Note: Attachments are write-once. To change an attachment + * you'll have to remove and re-add it. * * @author Marten Gajda */ - interface Attachment extends PropertyColumns - { - /** - * The mime-type of this property. - */ + interface Attachment extends PropertyColumns { + /** The mime-type of this property. */ String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/attachment"; /** * URL of the attachment. This is the link that points to the attached resource. + * *

* Value: String - *

*/ String URL = DATA1; /** * The display name of the attachment, if any. + * *

* Value: String - *

*/ String DISPLAY_NAME = DATA2; /** * Content-type of the attachment. + * *

* Value: String - *

*/ String FORMAT = DATA3; /** * File size of the attachment or -1 if unknown. + * *

* Value: Long - *

*/ String SIZE = DATA4; /** - * A content {@link Uri} that can be used to retrieve the attachment. Sync adapters can set this field if they know how to download the attachment + * A content {@link Uri} that can be used to retrieve the attachment. Sync + * adapters can set this field if they know how to download the attachment * without going through the browser. + * *

* Value: String - *

*/ String CONTENT_URI = DATA5; - } - - interface Attendee extends PropertyColumns - { - /** - * The mime-type of this property. - */ + interface Attendee extends PropertyColumns { + /** The mime-type of this property. */ String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/attendee"; /** * Name of the contact, if known. + * *

* Value: String - *

*/ String NAME = DATA0; /** * Email address of the contact. + * *

* Value: String - *

*/ String EMAIL = DATA1; @@ -1499,76 +1569,67 @@ public final class TaskContract String RSVP = DATA4; } - /** - * Categories are immutable. For creation is either the category id or name necessary + * Categories are immutable. For creation is either the category id or name + * necessary */ - interface Category extends PropertyColumns - { - /** - * The mime-type of this property. - */ + interface Category extends PropertyColumns { + /** The mime-type of this property. */ String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/category"; /** * Row id of the category. + * *

* Value: Long - *

*/ String CATEGORY_ID = DATA0; /** * The name of the category + * *

* Value: String - *

*/ String CATEGORY_NAME = DATA1; /** * The decimal coded color of the category + * *

* Value: Integer - *

+ * *

* read-only - *

*/ String CATEGORY_COLOR = DATA2; } - - interface Comment extends PropertyColumns - { - /** - * The mime-type of this property. - */ + interface Comment extends PropertyColumns { + /** The mime-type of this property. */ String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/comment"; /** * Comment text. + * *

* Value: String - *

*/ String COMMENT = DATA0; /** - * Language code of the comment as defined in RFC5646 or null. + * Language code of the comment as defined in + * RFC5646 or + * null. + * *

* Value: String - *

*/ String LANGUAGE = DATA1; } - - interface Contact extends PropertyColumns - { - /** - * The mime-type of this property. - */ + interface Contact extends PropertyColumns { + /** The mime-type of this property. */ String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/contact"; String NAME = DATA0; @@ -1576,78 +1637,70 @@ public final class TaskContract String LANGUAGE = DATA1; } - /** * Relations of a task. + * *

- * When writing a relation, exactly one of {@link #RELATED_ID} or {@link #RELATED_UID} must be present. The missing value and {@link - * #RELATED_CONTENT_URI} will be populated automatically if possible. + * When writing a relation, exactly one of {@link #RELATED_ID} or + * {@link #RELATED_UID} must be present. The missing value and + * {@link #RELATED_CONTENT_URI} will be populated automatically if possible. + * *

* {@link Tasks#PARENT_ID} is updated automatically if possible. */ - interface Relation extends PropertyColumns - { - /** - * The mime-type of this property. - */ + interface Relation extends PropertyColumns { + /** The mime-type of this property. */ String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/relation"; /** - * The row id of the related task. May be -1 if the property doesn't refer to a task in this database or if it doesn't refer to a task - * at all. + * The row id of the related task. May be -1 if the property + * doesn't refer to a task in this database or if it doesn't refer to a task at + * all. + * *

* Value: long - *

*/ String RELATED_ID = DATA1; /** * The relation type. This must be one of the {@code RELTYPE_*} values. + * *

* Value: int - *

*/ String RELATED_TYPE = DATA2; /** * The UID of the related object. + * *

* Value: String - *

*/ String RELATED_UID = DATA3; /** - * The content Uri of a related object in another Android content provider, if found. + * The content Uri of a related object in another Android content provider, if + * found. + * *

* Value: String (URI) - *

+ * *

* This field is read-only. - *

*/ String RELATED_CONTENT_URI = DATA5; - /** - * The related object is the parent of the object owning this relation. - */ + /** The related object is the parent of the object owning this relation. */ int RELTYPE_PARENT = 0; - /** - * The related object is the child of the object owning this relation. - */ + /** The related object is the child of the object owning this relation. */ int RELTYPE_CHILD = 1; - /** - * The related object is a sibling of the object owning this relation. - */ + /** The related object is a sibling of the object owning this relation. */ int RELTYPE_SIBLING = 2; - } - - interface Alarm extends PropertyColumns - { + interface Alarm extends PropertyColumns { int ALARM_TYPE_NOTHING = 0; @@ -1663,53 +1716,51 @@ public final class TaskContract int ALARM_REFERENCE_START_DATE = 2; - /** - * The mime-type of this property. - */ + /** The mime-type of this property. */ String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/alarm"; /** - * Number of minutes from the reference date when the alarm goes off. If the value is < 0 the alarm will go off after the reference date. + * Number of minutes from the reference date when the alarm goes off. If the + * value is < 0 the alarm will go off after the reference date. + * *

* Value: Integer - *

*/ String MINUTES_BEFORE = DATA0; /** - * The reference date for the alarm. Either {@link #ALARM_REFERENCE_DUE_DATE} or {@link #ALARM_REFERENCE_START_DATE}. + * The reference date for the alarm. Either {@link #ALARM_REFERENCE_DUE_DATE} or + * {@link #ALARM_REFERENCE_START_DATE}. + * *

* Value: Integer - *

*/ String REFERENCE = DATA1; /** * A message that appears with the alarm. + * *

* Value: String - *

*/ String MESSAGE = DATA2; /** - * The type of the alarm. Use the provided alarm types {@link #ALARM_TYPE_MESSAGE}, {@link #ALARM_TYPE_SOUND}, {@link #ALARM_TYPE_NOTHING}, - * {@link #ALARM_TYPE_EMAIL} and {@link #ALARM_TYPE_SMS}. + * The type of the alarm. Use the provided alarm types + * {@link #ALARM_TYPE_MESSAGE}, {@link #ALARM_TYPE_SOUND}, + * {@link #ALARM_TYPE_NOTHING}, {@link #ALARM_TYPE_EMAIL} and + * {@link #ALARM_TYPE_SMS}. + * *

* Value: Integer - *

*/ String ALARM_TYPE = DATA3; } - } - - private static synchronized UriFactory getUriFactory(String authority) - { + private static synchronized UriFactory getUriFactory(String authority) { UriFactory uriFactory = sUriFactories.get(authority); - if (uriFactory == null) - { + if (uriFactory == null) { uriFactory = new UriFactory(authority); uriFactory.addUri(SyncState.CONTENT_URI_PATH); uriFactory.addUri(TaskLists.CONTENT_URI_PATH); @@ -1720,9 +1771,7 @@ public final class TaskContract uriFactory.addUri(Alarms.CONTENT_URI_PATH); uriFactory.addUri(Properties.CONTENT_URI_PATH); sUriFactories.put(authority, uriFactory); - } return uriFactory; } - } diff --git a/opentasks-contract/src/main/java/org/dmfs/tasks/contract/UriFactory.java b/opentasks-contract/src/main/java/org/dmfs/tasks/contract/UriFactory.java index 0092aca26ac777dd35c987ee402d257072336675..810a4c618edd212f1663540a935003267ddde755 100644 --- a/opentasks-contract/src/main/java/org/dmfs/tasks/contract/UriFactory.java +++ b/opentasks-contract/src/main/java/org/dmfs/tasks/contract/UriFactory.java @@ -17,41 +17,28 @@ package org.dmfs.tasks.contract; import android.net.Uri; - import java.util.HashMap; import java.util.Map; - -/** - * TODO - */ -public final class UriFactory -{ +/** TODO */ +public final class UriFactory { private final String mAuthority; private final Map mUriMap = new HashMap(16); - - UriFactory(String authority) - { + UriFactory(String authority) { mAuthority = authority; mUriMap.put(null, Uri.parse("content://" + authority)); } - - void addUri(String path) - { + void addUri(String path) { mUriMap.put(path, Uri.parse("content://" + mAuthority + "/" + path)); } - - Uri getUri() - { + Uri getUri() { return mUriMap.get(null); } - - Uri getUri(String path) - { + Uri getUri(String path) { return mUriMap.get(path); } } diff --git a/opentasks-provider/build.gradle b/opentasks-provider/build.gradle index 0ac44f88745014f94678c709a550812479a7a4ac..561b813d1951978ee51c27164d52c69fdc428ef1 100644 --- a/opentasks-provider/build.gradle +++ b/opentasks-provider/build.gradle @@ -9,20 +9,21 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 36 - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } + buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + compileOptions { sourceCompatibility JavaVersion.VERSION_21 targetCompatibility JavaVersion.VERSION_21 } + packagingOptions { exclude 'META-INF/NOTICE' exclude 'META-INF/LICENSE' diff --git a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderDetachInstancesTest.java b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderDetachInstancesTest.java index bd824a9a44f5bb0c2ee1841ff5d83c296d25d1a8..f8fba3567972248d57a22cfcf5610dd190cfcdbd 100644 --- a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderDetachInstancesTest.java +++ b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderDetachInstancesTest.java @@ -16,13 +16,19 @@ package org.dmfs.provider.tasks; +import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; +import static org.dmfs.jems.optional.elementary.Absent.absent; +import static org.junit.Assert.assertThat; + import android.accounts.Account; import android.content.ContentProviderClient; import android.content.Context; import android.content.OperationApplicationException; import android.os.Build; import android.os.RemoteException; - +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; +import java.util.TimeZone; import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.OperationsQueue; import org.dmfs.android.contentpal.RowSnapshot; @@ -73,32 +79,19 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.TimeZone; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; -import static org.dmfs.jems.optional.elementary.Absent.absent; -import static org.junit.Assert.assertThat; - - /** * Test {@link TaskProvider} for correctly detaching completed instances. * * @author Marten Gajda */ @RunWith(AndroidJUnit4.class) -public class TaskProviderDetachInstancesTest -{ +public class TaskProviderDetachInstancesTest { private String mAuthority; private ContentProviderClient mClient; private Account mTestAccount = new Account("testname", "testtype"); - @Before - public void setUp() throws Exception - { + public void setUp() throws Exception { Context context = InstrumentationRegistry.getTargetContext(); mAuthority = AuthorityUtil.taskAuthority(context); mClient = context.getContentResolver().acquireContentProviderClient(mAuthority); @@ -106,46 +99,44 @@ public class TaskProviderDetachInstancesTest // Assert that tables are empty: OperationsQueue queue = new BasicOperationsQueue(mClient); queue.flush(); - queue.enqueue(new Seq>( - new AssertEmptyTable<>(new TasksTable(mAuthority)), + queue.enqueue(new Seq>(new AssertEmptyTable<>(new TasksTable(mAuthority)), new AssertEmptyTable<>(new TaskListsTable(mAuthority)), new AssertEmptyTable<>(new InstanceTable(mAuthority)))); queue.flush(); } - @After - public void tearDown() throws Exception - { + public void tearDown() throws Exception { /* - TODO When Test Orchestration is available, there will be no need for clean up here and check in setUp(), every test method will run in separate instrumentation - https://android-developers.googleblog.com/2017/07/android-testing-support-library-10-is.html - https://developer.android.com/training/testing/junit-runner.html#using-android-test-orchestrator - */ + * TODO When Test Orchestration is available, there will be no need for clean up + * here and check in setUp(), every test method will run in separate + * instrumentation + * https://android-developers.googleblog.com/2017/07/android-testing-support- + * library-10-is.html + * https://developer.android.com/training/testing/junit-runner.html#using- + * android-test-orchestrator + */ // Clear the DB: BasicOperationsQueue queue = new BasicOperationsQueue(mClient); queue.enqueue(new SingletonIterable>(new BulkDelete<>(new LocalTaskListsTable(mAuthority)))); queue.flush(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mClient.close(); - } - else - { + } else { mClient.release(); } } - /** - * Test if the first instance of a task with a DTSTART, DUE and an RRULE is correctly detached when completed. + * Test if the first instance of a task with a DTSTART, DUE and an RRULE is + * correctly detached when completed. */ @Test - public void testRRule() throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException - { - RowSnapshot taskList = new VirtualRowSnapshot<>(new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); + public void testRRule() throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException { + RowSnapshot taskList = new VirtualRowSnapshot<>( + new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -164,62 +155,57 @@ public class TaskProviderDetachInstancesTest DateTime localDue = due.shiftTimeZone(TimeZone.getDefault()); OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))) - )); + queue.enqueue(new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, new Composite<>( + new TimeData<>(start, due), + new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))))); queue.flush(); assertThat(new Seq<>( - // update the first non-closed instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) - ), + // update the first non-closed instance + new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), + new AllOf<>(new ReferringTo<>( + Instances.TASK_ID, task), new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0)))), resultsIn(queue, /* - * We expect three tasks: - * - the original master with updated RRULE, DTSTART and DUE - * - a deleted instance - * - a detached task + * We expect three tasks: - the original master with updated RRULE, DTSTART and + * DUE - a deleted instance - a detached task */ // the original master new Assert<>(task, - new Composite<>( - new TimeData<>(start.addDuration(day), due.addDuration(day)), + new Composite<>(new TimeData<>(start.addDuration(day), due.addDuration(day)), new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=4"))), - // there is one instance referring to the master (the old second instance, now first) + // there is one instance referring to the master (the old second instance, now + // first) new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), // the detached task instance: - new Counted<>(1, new BulkAssert<>(new Synced<>(mTestAccount, instancesTable), - new Composite<>( - new InstanceTestData(localStart, localDue, absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), - new Not<>(new ReferringTo<>(Instances.TASK_ID, task)))), + new Counted<>(1, + new BulkAssert<>(new Synced<>(mTestAccount, instancesTable), + new Composite<>(new InstanceTestData(localStart, localDue, absent(), -1), + new CharSequenceRowData<>(Tasks.STATUS, + String.valueOf(Tasks.STATUS_COMPLETED))), + new Not<>(new ReferringTo<>(Instances.TASK_ID, task)))), // the deleted task (doesn't have an instance) - new Counted<>(1, new BulkAssert<>(new Synced<>(mTestAccount, new TasksTable(mAuthority)), - new Composite<>(new TimeData<>(start, due)), - new AllOf<>( - new ReferringTo<>(Tasks.ORIGINAL_INSTANCE_ID, task), - new EqArg<>(Tasks._DELETED, 1)))), + new Counted<>(1, + new BulkAssert<>(new Synced<>(mTestAccount, new TasksTable(mAuthority)), + new Composite<>(new TimeData<>(start, due)), + new AllOf<>(new ReferringTo<>(Tasks.ORIGINAL_INSTANCE_ID, task), + new EqArg<>(Tasks._DELETED, 1)))), // the former 2nd instance (now first) new AssertRelated<>(new Synced<>(mTestAccount, instancesTable), Instances.TASK_ID, task, new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 0), new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())))); } - /** - * Test if two instances of a task with a DTSTART, DUE and an RRULE are detached correctly. + * Test if two instances of a task with a DTSTART, DUE and an RRULE are detached + * correctly. */ @Test - public void testRRuleCompleteAll() throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException - { - RowSnapshot taskList = new VirtualRowSnapshot<>(new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); + public void testRRuleCompleteAll() + throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException { + RowSnapshot taskList = new VirtualRowSnapshot<>( + new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -238,89 +224,77 @@ public class TaskProviderDetachInstancesTest DateTime localDue = due.shiftTimeZone(TimeZone.getDefault()); OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TitleData("Test-Task"), - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=2", RecurrenceRule.RfcMode.RFC2445_LAX)))), - // complete the first non-closed instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) - )); + queue.enqueue( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + new Put<>(task, new Composite<>(new TitleData("Test-Task"), new TimeData<>(start, due), + new RRuleTaskData( + new RecurrenceRule("FREQ=DAILY;COUNT=2", RecurrenceRule.RfcMode.RFC2445_LAX)))), + // complete the first non-closed instance + new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), + new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), + new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))))); queue.flush(); Synced tasksTable = new Synced<>(mTestAccount, new TasksTable(mAuthority)); Synced syncedInstances = new Synced<>(mTestAccount, instancesTable); assertThat(new Seq<>( - // update the second instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) - ), + // update the second instance + new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), + new AllOf<>(new ReferringTo<>( + Instances.TASK_ID, task), new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0)))), resultsIn(queue, /* - * We expect five tasks: - * - the original master with updated RRULE, DTSTART and DUE, deleted - * - a completed and deleted overrides for the first and second instance - * - a detached first and second instance + * We expect five tasks: - the original master with updated RRULE, DTSTART and + * DUE, deleted - a completed and deleted overrides for the first and second + * instance - a detached first and second instance */ // the original master - new Assert<>(task, - new Composite<>( - // points to former second instance before being deleted - new TimeData<>(start.addDuration(day), due.addDuration(day)), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=1"), - new CharSequenceRowData<>(Tasks._DELETED, "1"))), - // there is no instance referring to the master because it has been fully completed (and deleted) + new Assert<>(task, new Composite<>( + // points to former second instance before being deleted + new TimeData<>(start.addDuration(day), due.addDuration(day)), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=1"), + new CharSequenceRowData<>(Tasks._DELETED, "1"))), + // there is no instance referring to the master because it has been fully + // completed (and + // deleted) new Counted<>(0, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), // the first detached task instance: - new Counted<>(1, new BulkAssert<>(syncedInstances, - new Composite<>( - new InstanceTestData(localStart, localDue, absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), - new AllOf<>( - new EqArg<>(Instances.INSTANCE_START, start.getTimestamp()), - new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), + new Counted<>(1, + new BulkAssert<>(syncedInstances, + new Composite<>(new InstanceTestData(localStart, localDue, absent(), -1), + new CharSequenceRowData<>(Tasks.STATUS, + String.valueOf(Tasks.STATUS_COMPLETED))), + new AllOf<>(new EqArg<>(Instances.INSTANCE_START, start.getTimestamp()), + new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // the second detached task instance: - new Counted<>(1, new BulkAssert<>(syncedInstances, - new Composite<>( - new InstanceTestData(second, second.addDuration(new Duration(1, 0, 3600)), absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), - new AllOf<>( - new EqArg<>(Instances.INSTANCE_START, second.getTimestamp()), + new Counted<>(1, new BulkAssert<>(syncedInstances, new Composite<>( + new InstanceTestData(second, second.addDuration(new Duration(1, 0, 3600)), absent(), + -1), + new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), + new AllOf<>(new EqArg<>(Instances.INSTANCE_START, second.getTimestamp()), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // two instances total, both completed new Counted<>(2, - new BulkAssert<>( - syncedInstances, + new BulkAssert<>(syncedInstances, new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED)), new AnyOf<>())), // five tasks in total - new Counted<>(5, - new BulkAssert<>( - tasksTable, - new TitleData("Test-Task"), - new AnyOf<>())), + new Counted<>(5, new BulkAssert<>(tasksTable, new TitleData("Test-Task"), new AnyOf<>())), // three deleted tasks in total - new Counted<>(3, - new BulkAssert<>( - tasksTable, - new TitleData("Test-Task"), - new EqArg<>(Tasks._DELETED, 1))))); + new Counted<>(3, new BulkAssert<>(tasksTable, new TitleData("Test-Task"), + new EqArg<>(Tasks._DELETED, 1))))); } - /** - * Test if two instances of a task with a DTSTART, DUE, RRULE and RDATE are detached correctly. + * Test if two instances of a task with a DTSTART, DUE, RRULE and RDATE are + * detached correctly. */ @Test - public void testRRuleRDateCompleteFirstTwo() throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException - { - RowSnapshot taskList = new VirtualRowSnapshot<>(new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); + public void testRRuleRDateCompleteFirstTwo() + throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException { + RowSnapshot taskList = new VirtualRowSnapshot<>( + new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -339,110 +313,91 @@ public class TaskProviderDetachInstancesTest DateTime localDue = due.shiftTimeZone(TimeZone.getDefault()); OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), + queue.enqueue(new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, - new Composite<>( - new TitleData("Test-Task"), - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=2", RecurrenceRule.RfcMode.RFC2445_LAX)), - new RDatesTaskData( - new Seq<>( - DateTime.parse("20180103T123456Z"), - DateTime.parse("20180105T123456Z"), - DateTime.parse("20180107T123456Z"))))), + new Composite<>(new TitleData("Test-Task"), new TimeData<>(start, due), + new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=2", + RecurrenceRule.RfcMode.RFC2445_LAX)), + new RDatesTaskData(new Seq<>(DateTime.parse("20180103T123456Z"), + DateTime.parse("20180105T123456Z"), DateTime.parse("20180107T123456Z"))))), // update the first non-closed instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) - )); + new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), new AllOf<>( + new ReferringTo<>(Instances.TASK_ID, task), new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))))); queue.flush(); Synced tasksTable = new Synced<>(mTestAccount, new TasksTable(mAuthority)); Synced syncedInstances = new Synced<>(mTestAccount, instancesTable); assertThat(new Seq<>( - // update the second instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) - ), + // update the second instance + new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), + new AllOf<>(new ReferringTo<>( + Instances.TASK_ID, task), new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0)))), resultsIn(queue, /* - * We expect five tasks: - * - the original master with updated RRULE, RDATES, DTSTART and DUE, deleted - * - completed and deleted overrides for the first and second instance - * - a detached first and second instance + * We expect five tasks: - the original master with updated RRULE, RDATES, + * DTSTART and DUE, deleted - completed and deleted overrides for the first and + * second instance - a detached first and second instance */ // the first detached task instance: - new Counted<>(1, new BulkAssert<>(syncedInstances, - new Composite<>( - new InstanceTestData(DateTime.parse("20180103T123456Z"), DateTime.parse("20180103T133456Z"), absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), + new Counted<>(1, new BulkAssert<>(syncedInstances, new Composite<>( + new InstanceTestData(DateTime.parse("20180103T123456Z"), + DateTime.parse("20180103T133456Z"), absent(), -1), + new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), new AllOf<>( - new EqArg<>(Instances.INSTANCE_START, DateTime.parse("20180103T123456Z").getTimestamp()), + new EqArg<>(Instances.INSTANCE_START, + DateTime.parse("20180103T123456Z").getTimestamp()), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // the original master has been updated - new Assert<>(task, - new Composite<>( - // points to former third instance before being deleted - new TimeData<>(start.addDuration(day).addDuration(day), due.addDuration(day).addDuration(day)), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;INTERVAL=2;COUNT=1"), - new CharSequenceRowData<>(Tasks._DELETED, "0"), - new RDatesTaskData( - new Seq<>( - DateTime.parse("20180105T123456Z"), - DateTime.parse("20180107T123456Z"))))), + new Assert<>(task, new Composite<>( + // points to former third instance before being deleted + new TimeData<>(start.addDuration(day).addDuration(day), + due.addDuration(day).addDuration(day)), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;INTERVAL=2;COUNT=1"), + new CharSequenceRowData<>(Tasks._DELETED, "0"), + new RDatesTaskData(new Seq<>(DateTime.parse("20180105T123456Z"), + DateTime.parse("20180107T123456Z"))))), // there is one instance referring to the master - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new CharSequenceRowData<>(Instances.INSTANCE_ORIGINAL_TIME, - String.valueOf(DateTime.parse("20180105T123456Z").getTimestamp())))), + new Counted<>(1, + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new CharSequenceRowData<>(Instances.INSTANCE_ORIGINAL_TIME, + String.valueOf(DateTime.parse("20180105T123456Z").getTimestamp())))), // the second detached task instance: - new Counted<>(1, new BulkAssert<>(syncedInstances, - new Composite<>( - new InstanceTestData(start, due, absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), - new AllOf<>( - new EqArg<>(Instances.INSTANCE_START, start.getTimestamp()), - new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), + new Counted<>(1, + new BulkAssert<>(syncedInstances, + new Composite<>(new InstanceTestData(start, due, absent(), -1), + new CharSequenceRowData<>(Tasks.STATUS, + String.valueOf(Tasks.STATUS_COMPLETED))), + new AllOf<>(new EqArg<>(Instances.INSTANCE_START, start.getTimestamp()), + new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // two completed instances, neither of them referring to the master new Counted<>(2, - new BulkAssert<>( - syncedInstances, + new BulkAssert<>(syncedInstances, new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED)), - new AllOf<>( - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, -1), + new AllOf<>(new EqArg<>(Instances.DISTANCE_FROM_CURRENT, -1), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // one incomplete instance , the first instance of the new master - new Counted<>(1, - new BulkAssert<>( - syncedInstances, - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_NEEDS_ACTION)), - new AllOf<>( - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0), - new ReferringTo<>(Instances.TASK_ID, task)))), - // five tasks in total (two deleted overrides, two detached ones and the new master) - new Counted<>(5, - new BulkAssert<>( - tasksTable, - new TitleData("Test-Task"), - new AnyOf<>())), + new Counted<>(1, new BulkAssert<>(syncedInstances, + new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_NEEDS_ACTION)), + new AllOf<>(new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0), + new ReferringTo<>(Instances.TASK_ID, task)))), + // five tasks in total (two deleted overrides, two detached ones and the new + // master) + new Counted<>(5, new BulkAssert<>(tasksTable, new TitleData("Test-Task"), new AnyOf<>())), // two deleted tasks in total (the old overrides) - new Counted<>(2, - new BulkAssert<>( - tasksTable, - new TitleData("Test-Task"), - new EqArg<>(Tasks._DELETED, 1))))); + new Counted<>(2, new BulkAssert<>(tasksTable, new TitleData("Test-Task"), + new EqArg<>(Tasks._DELETED, 1))))); } - /** - * Test if two instances of a task with a DTSTART, DUE, RRULE, RDATE and EXDATE are detached correctly. + * Test if two instances of a task with a DTSTART, DUE, RRULE, RDATE and EXDATE + * are detached correctly. */ @Test - public void testRRuleRDateCompleteWithExdates() throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException - { - RowSnapshot taskList = new VirtualRowSnapshot<>(new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); + public void testRRuleRDateCompleteWithExdates() + throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException { + RowSnapshot taskList = new VirtualRowSnapshot<>( + new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -461,94 +416,77 @@ public class TaskProviderDetachInstancesTest DateTime localDue = due.shiftTimeZone(TimeZone.getDefault()); OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TitleData("Test-Task"), - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=2", RecurrenceRule.RfcMode.RFC2445_LAX)), - new RDatesTaskData( - new Seq<>( - DateTime.parse("20180105T123456Z"), - DateTime.parse("20180107T123456Z"))), - new ExDatesTaskData( - new Seq<>( - DateTime.parse("20180104T123456Z"), - DateTime.parse("20180105T123456Z"))))), + queue.enqueue(new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, new Composite<>( + new TitleData("Test-Task"), new TimeData<>(start, due), + new RRuleTaskData( + new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=2", RecurrenceRule.RfcMode.RFC2445_LAX)), + new RDatesTaskData(new Seq<>(DateTime.parse("20180105T123456Z"), DateTime.parse("20180107T123456Z"))), + new ExDatesTaskData( + new Seq<>(DateTime.parse("20180104T123456Z"), DateTime.parse("20180105T123456Z"))))), // update the first non-closed instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) - )); + new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), new AllOf<>( + new ReferringTo<>(Instances.TASK_ID, task), new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))))); queue.flush(); Synced tasksTable = new Synced<>(mTestAccount, new TasksTable(mAuthority)); Synced syncedInstances = new Synced<>(mTestAccount, instancesTable); assertThat(new Seq<>( - // update the second instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) - ), + // update the second instance + new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), + new AllOf<>(new ReferringTo<>( + Instances.TASK_ID, task), new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0)))), resultsIn(queue, /* - * We expect five tasks: - * - the original master deleted - * - completed and deleted overrides for the first and second instance - * - detached first and second instances + * We expect five tasks: - the original master deleted - completed and deleted + * overrides for the first and second instance - detached first and second + * instances */ // the first detached task instance: - new Counted<>(1, new BulkAssert<>(syncedInstances, - new Composite<>( - new InstanceTestData(DateTime.parse("20180106T123456Z"), DateTime.parse("20180106T133456Z"), absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), + new Counted<>(1, new BulkAssert<>(syncedInstances, new Composite<>( + new InstanceTestData(DateTime.parse("20180106T123456Z"), + DateTime.parse("20180106T133456Z"), absent(), -1), + new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), new AllOf<>( - new EqArg<>(Instances.INSTANCE_START, DateTime.parse("20180106T123456Z").getTimestamp()), + new EqArg<>(Instances.INSTANCE_START, + DateTime.parse("20180106T123456Z").getTimestamp()), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // the original master has been deleted new Counted<>(0, new Assert<>(task, new Composite<>(new EmptyRowData<>()))), // there is no instance referring to the master new Counted<>(0, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), // the second detached task instance: - new Counted<>(1, new BulkAssert<>(syncedInstances, - new Composite<>( - new InstanceTestData(DateTime.parse("20180107T123456Z"), DateTime.parse("20180107T133456Z"), absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), + new Counted<>(1, new BulkAssert<>(syncedInstances, new Composite<>( + new InstanceTestData(DateTime.parse("20180107T123456Z"), + DateTime.parse("20180107T133456Z"), absent(), -1), + new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), new AllOf<>( - new EqArg<>(Instances.INSTANCE_START, DateTime.parse("20180107T123456Z").getTimestamp()), + new EqArg<>(Instances.INSTANCE_START, + DateTime.parse("20180107T123456Z").getTimestamp()), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // two completed instances, neither of them referring to the master new Counted<>(2, - new BulkAssert<>( - syncedInstances, + new BulkAssert<>(syncedInstances, new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED)), - new AllOf<>( - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, -1), + new AllOf<>(new EqArg<>(Instances.DISTANCE_FROM_CURRENT, -1), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), - // five tasks in total (two deleted overrides, two detached ones and the old master) - new Counted<>(5, - new BulkAssert<>( - tasksTable, - new TitleData("Test-Task"), - new AnyOf<>())), + // five tasks in total (two deleted overrides, two detached ones and the old + // master) + new Counted<>(5, new BulkAssert<>(tasksTable, new TitleData("Test-Task"), new AnyOf<>())), // three deleted tasks in total (the old overrides and the old master) - new Counted<>(3, - new BulkAssert<>( - tasksTable, - new TitleData("Test-Task"), - new EqArg<>(Tasks._DELETED, 1))))); + new Counted<>(3, new BulkAssert<>(tasksTable, new TitleData("Test-Task"), + new EqArg<>(Tasks._DELETED, 1))))); } - /** - * Test if two instances of a task with a DTSTART, DUE, RRULE, RDATE and EXDATE are detached correctly. + * Test if two instances of a task with a DTSTART, DUE, RRULE, RDATE and EXDATE + * are detached correctly. */ @Test - public void testRRuleRDateCompleteOnlyRRuleInstances() throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException - { - RowSnapshot taskList = new VirtualRowSnapshot<>(new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); + public void testRRuleRDateCompleteOnlyRRuleInstances() + throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException { + RowSnapshot taskList = new VirtualRowSnapshot<>( + new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -567,98 +505,84 @@ public class TaskProviderDetachInstancesTest DateTime localDue = due.shiftTimeZone(TimeZone.getDefault()); OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TitleData("Test-Task"), - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=2", RecurrenceRule.RfcMode.RFC2445_LAX)), - new RDatesTaskData( - new Seq<>( - DateTime.parse("20180105T123456Z"), - DateTime.parse("20180107T123456Z"))), - new ExDatesTaskData( - new Seq<>( - DateTime.parse("20180104T123456Z"))))) -/* // update the first non-closed instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0)))*/ + queue.enqueue(new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, new Composite<>( + new TitleData("Test-Task"), new TimeData<>(start, due), + new RRuleTaskData( + new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=2", RecurrenceRule.RfcMode.RFC2445_LAX)), + new RDatesTaskData(new Seq<>(DateTime.parse("20180105T123456Z"), DateTime.parse("20180107T123456Z"))), + new ExDatesTaskData(new Seq<>(DateTime.parse("20180104T123456Z"))))) + /* + * // update the first non-closed instance new BulkUpdate<>(instancesTable, new + * StatusData<>(Tasks.STATUS_COMPLETED), new AllOf<>(new + * ReferringTo<>(Instances.TASK_ID, task), new + * EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) + */ )); queue.flush(); Synced tasksTable = new Synced<>(mTestAccount, new TasksTable(mAuthority)); Synced syncedInstances = new Synced<>(mTestAccount, instancesTable); assertThat(new Seq<>( - // update the second instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) - ), + // update the second instance + new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), + new AllOf<>(new ReferringTo<>( + Instances.TASK_ID, task), new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0)))), resultsIn(queue, /* - * We expect five tasks: - * - the original master deleted - * - completed and deleted overrides for the first and second instance - * - detached first and second instances + * We expect five tasks: - the original master deleted - completed and deleted + * overrides for the first and second instance - detached first and second + * instances */ // the first detached task instance: - new Counted<>(1, new BulkAssert<>(syncedInstances, - new Composite<>( - new InstanceTestData(DateTime.parse("20180105T123456Z"), DateTime.parse("20180105T133456Z"), absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), + new Counted<>(1, new BulkAssert<>(syncedInstances, new Composite<>( + new InstanceTestData(DateTime.parse("20180105T123456Z"), + DateTime.parse("20180105T133456Z"), absent(), -1), + new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), new AllOf<>( - new EqArg<>(Instances.INSTANCE_START, DateTime.parse("20180105T123456Z").getTimestamp()), + new EqArg<>(Instances.INSTANCE_START, + DateTime.parse("20180105T123456Z").getTimestamp()), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // the original master has been updated new Assert<>(task, new Composite<>( - new TimeData<>(DateTime.parse("20180106T123456Z"), DateTime.parse("20180106T133456Z")), + new TimeData<>(DateTime.parse("20180106T123456Z"), + DateTime.parse("20180106T133456Z")), new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;INTERVAL=2;COUNT=1"), new CharSequenceRowData<>(Tasks._DELETED, "0"), - new RDatesTaskData( - new Seq<>( - DateTime.parse("20180107T123456Z"))))), + new RDatesTaskData(new Seq<>(DateTime.parse("20180107T123456Z"))))), // the second detached task instance: - /* new Counted<>(1, new BulkAssert<>(syncedInstances, - new Composite<>( - new InstanceTestData(DateTime.parse("20180106T123456Z"), DateTime.parse("20180106T133456Z"), absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), - new AllOf<>( - new EqArg<>(Instances.INSTANCE_START, DateTime.parse("20180106T123456Z").getTimestamp()), - new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))),*/ + /* + * new Counted<>(1, new BulkAssert<>(syncedInstances, new Composite<>( new + * InstanceTestData(DateTime.parse("20180106T123456Z"), + * DateTime.parse("20180106T133456Z"), absent(), -1), new + * CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), + * new AllOf<>( new EqArg<>(Instances.INSTANCE_START, + * DateTime.parse("20180106T123456Z").getTimestamp()), new Not<>(new + * ReferringTo<>(Instances.TASK_ID, task))))), + */ // one completed instance, not referring to the master new Counted<>(1, - new BulkAssert<>( - syncedInstances, + new BulkAssert<>(syncedInstances, new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED)), - new AllOf<>( - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, -1), + new AllOf<>(new EqArg<>(Instances.DISTANCE_FROM_CURRENT, -1), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // three tasks in total (one deleted override, one detached one and the master) - new Counted<>(3, - new BulkAssert<>( - tasksTable, - new TitleData("Test-Task"), - new AnyOf<>())), + new Counted<>(3, new BulkAssert<>(tasksTable, new TitleData("Test-Task"), new AnyOf<>())), // three deleted tasks in total (the old overrides and the old master) - new Counted<>(1, - new BulkAssert<>( - tasksTable, - new TitleData("Test-Task"), - new EqArg<>(Tasks._DELETED, 1))))); + new Counted<>(1, new BulkAssert<>(tasksTable, new TitleData("Test-Task"), + new EqArg<>(Tasks._DELETED, 1))))); } - /** - * Test if two all-day instances of a task with a DTSTART, DUE, RRULE, RDATE and EXDATE are detached correctly. + * Test if two all-day instances of a task with a DTSTART, DUE, RRULE, RDATE and + * EXDATE are detached correctly. */ @Test - public void testRRuleRDateCompleteWithExdatesAllDay() throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException - { - RowSnapshot taskList = new VirtualRowSnapshot<>(new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); + public void testRRuleRDateCompleteWithExdatesAllDay() + throws InvalidRecurrenceRuleException, RemoteException, OperationApplicationException { + RowSnapshot taskList = new VirtualRowSnapshot<>( + new Synced<>(mTestAccount, new TaskListsTable(mAuthority))); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -669,84 +593,64 @@ public class TaskProviderDetachInstancesTest Duration day = new Duration(1, 1, 0); OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TitleData("Test-Task"), - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=2", RecurrenceRule.RfcMode.RFC2445_LAX)), - new RDatesTaskData( - new Seq<>( - DateTime.parse("20180105"), - DateTime.parse("20180107"))), - new ExDatesTaskData( - new Seq<>( - DateTime.parse("20180104"), - DateTime.parse("20180105"))))), + queue.enqueue(new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, + new Composite<>(new TitleData("Test-Task"), new TimeData<>(start, due), + new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=2", + RecurrenceRule.RfcMode.RFC2445_LAX)), + new RDatesTaskData(new Seq<>(DateTime.parse("20180105"), DateTime.parse("20180107"))), + new ExDatesTaskData(new Seq<>(DateTime.parse("20180104"), DateTime.parse("20180105"))))), // update the first non-closed instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) - )); + new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), new AllOf<>( + new ReferringTo<>(Instances.TASK_ID, task), new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))))); queue.flush(); Synced tasksTable = new Synced<>(mTestAccount, new TasksTable(mAuthority)); Synced syncedInstances = new Synced<>(mTestAccount, instancesTable); assertThat(new Seq<>( - // update the second instance - new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0))) - ), + // update the second instance + new BulkUpdate<>(instancesTable, new StatusData<>(Tasks.STATUS_COMPLETED), + new AllOf<>(new ReferringTo<>( + Instances.TASK_ID, task), new EqArg<>(Instances.DISTANCE_FROM_CURRENT, 0)))), resultsIn(queue, /* - * We expect five tasks: - * - the original master deleted - * - completed and deleted overrides for the first and second instance - * - detached first and second instances + * We expect five tasks: - the original master deleted - completed and deleted + * overrides for the first and second instance - detached first and second + * instances */ // the first detached task instance: - new Counted<>(1, new BulkAssert<>(syncedInstances, - new Composite<>( - new InstanceTestData(DateTime.parse("20180106"), DateTime.parse("20180107"), absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), + new Counted<>(1, new BulkAssert<>(syncedInstances, new Composite<>( + new InstanceTestData(DateTime.parse("20180106"), DateTime.parse("20180107"), absent(), + -1), + new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), new AllOf<>( - new EqArg<>(Instances.INSTANCE_START, DateTime.parse("20180106").getTimestamp()), + new EqArg<>(Instances.INSTANCE_START, + DateTime.parse("20180106").getTimestamp()), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // the original master has been deleted new Counted<>(0, new Assert<>(task, new Composite<>(new EmptyRowData<>()))), // there is no instance referring to the master new Counted<>(0, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), // the second detached task instance: - new Counted<>(1, new BulkAssert<>(syncedInstances, - new Composite<>( - new InstanceTestData(DateTime.parse("20180107"), DateTime.parse("20180108"), absent(), -1), - new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), + new Counted<>(1, new BulkAssert<>(syncedInstances, new Composite<>( + new InstanceTestData(DateTime.parse("20180107"), DateTime.parse("20180108"), absent(), + -1), + new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED))), new AllOf<>( - new EqArg<>(Instances.INSTANCE_START, DateTime.parse("20180107").getTimestamp()), + new EqArg<>(Instances.INSTANCE_START, + DateTime.parse("20180107").getTimestamp()), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), // two completed instances, neither of them referring to the master new Counted<>(2, - new BulkAssert<>( - syncedInstances, + new BulkAssert<>(syncedInstances, new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED)), - new AllOf<>( - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, -1), + new AllOf<>(new EqArg<>(Instances.DISTANCE_FROM_CURRENT, -1), new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), - // five tasks in total (two deleted overrides, two detached ones and the old master) - new Counted<>(5, - new BulkAssert<>( - tasksTable, - new TitleData("Test-Task"), - new AnyOf<>())), + // five tasks in total (two deleted overrides, two detached ones and the old + // master) + new Counted<>(5, new BulkAssert<>(tasksTable, new TitleData("Test-Task"), new AnyOf<>())), // three deleted tasks in total (the old overrides and the old master) - new Counted<>(3, - new BulkAssert<>( - tasksTable, - new TitleData("Test-Task"), - new EqArg<>(Tasks._DELETED, 1))))); + new Counted<>(3, new BulkAssert<>(tasksTable, new TitleData("Test-Task"), + new EqArg<>(Tasks._DELETED, 1))))); } - } diff --git a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderInstancesTest.java b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderInstancesTest.java index af12ef365988b7422e13cd56b06c513e83cf9a0e..d3902b39a98d079c7338267cb02e0879038c1b60 100644 --- a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderInstancesTest.java +++ b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderInstancesTest.java @@ -16,6 +16,9 @@ package org.dmfs.provider.tasks; +import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; +import static org.junit.Assert.assertThat; + import android.content.ContentProviderClient; import android.content.Context; import android.content.OperationApplicationException; @@ -23,7 +26,6 @@ import android.os.Build; import android.os.RemoteException; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; - import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.OperationsQueue; import org.dmfs.android.contentpal.RowSnapshot; @@ -62,73 +64,61 @@ import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; -import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; -import static org.junit.Assert.assertThat; - - /** - * Tests for {@link TaskProvider}. These tests check various operations on the instances table. + * Tests for {@link TaskProvider}. These tests check various operations on the + * instances table. * * @author Gabor Keszthelyi * @author Marten Gajda */ @RunWith(AndroidJUnit4.class) -public class TaskProviderInstancesTest -{ +public class TaskProviderInstancesTest { private String mAuthority; private Context mContext; private ContentProviderClient mClient; - @Before - public void setUp() throws Exception - { + public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); mAuthority = AuthorityUtil.taskAuthority(mContext); mClient = mContext.getContentResolver().acquireContentProviderClient(mAuthority); // Assert that tables are empty: OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new AssertEmptyTable<>(new TasksTable(mAuthority)), + queue.enqueue(new Seq>(new AssertEmptyTable<>(new TasksTable(mAuthority)), new AssertEmptyTable<>(new TaskListsTable(mAuthority)), new AssertEmptyTable<>(new InstanceTable(mAuthority)))); queue.flush(); } - @After - public void tearDown() throws Exception - { + public void tearDown() throws Exception { /* - TODO When Test Orchestration is available, there will be no need for clean up here and check in setUp(), every test method will run in separate instrumentation - https://android-developers.googleblog.com/2017/07/android-testing-support-library-10-is.html - https://developer.android.com/training/testing/junit-runner.html#using-android-test-orchestrator - */ + * TODO When Test Orchestration is available, there will be no need for clean up + * here and check in setUp(), every test method will run in separate + * instrumentation + * https://android-developers.googleblog.com/2017/07/android-testing-support- + * library-10-is.html + * https://developer.android.com/training/testing/junit-runner.html#using- + * android-test-orchestrator + */ // Clear the DB: BasicOperationsQueue queue = new BasicOperationsQueue(mClient); queue.enqueue(new SingletonIterable>(new BulkDelete<>(new LocalTaskListsTable(mAuthority)))); queue.flush(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mClient.close(); - } - else - { + } else { mClient.release(); } } - - /** - * Create a single instance. - */ + /** Create a single instance. */ @Ignore("Inserting instances is currently unsupported.") @Test - public void testInsertSingleInstance() - { + public void testInsertSingleInstance() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot instance = new VirtualRowSnapshot<>(new InstanceTable(mAuthority)); @@ -136,30 +126,23 @@ public class TaskProviderInstancesTest // create a local list new Put<>(taskList, new NameData("list1")), // insert a new task straight into the instances table - new Put<>(instance, new Referring<>(Tasks.LIST_ID, taskList, new CharSequenceRowData<>(Tasks.TITLE, "task1"))) - - ), resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - // the task list contains exactly one task with the title "task1" - new Counted<>(1, new BulkAssert<>(new TasksTable(mAuthority))), - new AssertRelated<>(new TasksTable(mAuthority), Tasks.LIST_ID, taskList, - new Composite<>( - new CharSequenceRowData<>(Tasks.TITLE, "task1"))), - // the instances table contains one instance - new Counted<>(1, new BulkAssert<>(new InstanceTable(mAuthority))), - // the instances table contains the given instance - new Assert<>(instance, new Composite<>( - new InstanceTestData(0), - new CharSequenceRowData<>(Tasks.TITLE, "task1"))))); + new Put<>(instance, + new Referring<>(Tasks.LIST_ID, taskList, new CharSequenceRowData<>(Tasks.TITLE, "task1")))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + // the task list contains exactly one task with the title "task1" + new Counted<>(1, new BulkAssert<>(new TasksTable(mAuthority))), + new AssertRelated<>(new TasksTable(mAuthority), Tasks.LIST_ID, taskList, + new Composite<>(new CharSequenceRowData<>(Tasks.TITLE, "task1"))), + // the instances table contains one instance + new Counted<>(1, new BulkAssert<>(new InstanceTable(mAuthority))), + // the instances table contains the given instance + new Assert<>(instance, new Composite<>(new InstanceTestData(0), + new CharSequenceRowData<>(Tasks.TITLE, "task1"))))); } - - /** - * Create a single instance and update it. - */ + /** Create a single instance and update it. */ @Test - public void testUpdateSingleInstance() - { + public void testUpdateSingleInstance() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TasksTable(mAuthority)); @@ -167,37 +150,29 @@ public class TaskProviderInstancesTest // create a local list new Put<>(taskList, new NameData("list1")), // insert a new task straight into the instances table - new Put<>(task, new Referring<>(Tasks.LIST_ID, taskList, new CharSequenceRowData<>(Tasks.TITLE, "task1"))), + new Put<>(task, + new Referring<>(Tasks.LIST_ID, taskList, new CharSequenceRowData<>(Tasks.TITLE, "task1"))), // update the instance - new BulkUpdate<>( - new InstanceTable(mAuthority), - new CharSequenceRowData<>(Tasks.TITLE, "Updated"), - new ReferringTo<>(Instances.TASK_ID, task)) - ), resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - // the task list contains exactly one task with the title "Updated" - new Counted<>(1, new BulkAssert<>(new TasksTable(mAuthority))), - new AssertRelated<>(new TasksTable(mAuthority), Tasks.LIST_ID, taskList, - new Composite<>( - new CharSequenceRowData<>(Tasks.TITLE, "Updated"))), - // the instances table contains one instance - new Counted<>(1, new BulkAssert<>(new InstanceTable(mAuthority))), - // the instances table contains the given instance - new Counted<>(1, new BulkAssert<>( - new InstanceTable(mAuthority), - new Composite<>( - new InstanceTestData(0), - new CharSequenceRowData<>(Tasks.TITLE, "Updated")), - new ReferringTo<>(Instances.TASK_ID, task))))); + new BulkUpdate<>(new InstanceTable(mAuthority), new CharSequenceRowData<>(Tasks.TITLE, "Updated"), + new ReferringTo<>(Instances.TASK_ID, task))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + // the task list contains exactly one task with the title "Updated" + new Counted<>(1, new BulkAssert<>(new TasksTable(mAuthority))), + new AssertRelated<>(new TasksTable(mAuthority), Tasks.LIST_ID, taskList, + new Composite<>(new CharSequenceRowData<>(Tasks.TITLE, "Updated"))), + // the instances table contains one instance + new Counted<>(1, new BulkAssert<>(new InstanceTable(mAuthority))), + // the instances table contains the given instance + new Counted<>(1, + new BulkAssert<>(new InstanceTable(mAuthority), + new Composite<>(new InstanceTestData(0), + new CharSequenceRowData<>(Tasks.TITLE, "Updated")), + new ReferringTo<>(Instances.TASK_ID, task))))); } - - /** - * Create a single instance and complete it. - */ + /** Create a single instance and complete it. */ @Test - public void testCompleteSingleInstance() - { + public void testCompleteSingleInstance() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TasksTable(mAuthority)); @@ -205,37 +180,30 @@ public class TaskProviderInstancesTest // create a local list new Put<>(taskList, new NameData("list1")), // insert a new task straight into the instances table - new Put<>(task, new Referring<>(Tasks.LIST_ID, taskList, new CharSequenceRowData<>(Tasks.TITLE, "task1"))), + new Put<>(task, + new Referring<>(Tasks.LIST_ID, taskList, new CharSequenceRowData<>(Tasks.TITLE, "task1"))), // update the instance status - new BulkUpdate<>( - new InstanceTable(mAuthority), + new BulkUpdate<>(new InstanceTable(mAuthority), (transactionContext, builder) -> builder.withValue(Tasks.STATUS, Tasks.STATUS_COMPLETED), - new ReferringTo<>(Instances.TASK_ID, task)) - ), resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - // the task list contains exactly one task with the title "Updated" - new Counted<>(1, new BulkAssert<>(new TasksTable(mAuthority))), - new AssertRelated<>(new TasksTable(mAuthority), Tasks.LIST_ID, taskList, - new Composite<>( - new CharSequenceRowData<>(Tasks.TITLE, "task1"))), - // the instances table contains one instance - new Counted<>(1, new BulkAssert<>(new InstanceTable(mAuthority))), - // the instances table contains the given instance - new Counted<>(1, new BulkAssert<>( - new InstanceTable(mAuthority), - new Composite<>( - new InstanceTestData(-1), - new CharSequenceRowData<>(Tasks.TITLE, "task1")), - new ReferringTo<>(Instances.TASK_ID, task))))); + new ReferringTo<>(Instances.TASK_ID, task))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + // the task list contains exactly one task with the title "Updated" + new Counted<>(1, new BulkAssert<>(new TasksTable(mAuthority))), + new AssertRelated<>(new TasksTable(mAuthority), Tasks.LIST_ID, taskList, + new Composite<>(new CharSequenceRowData<>(Tasks.TITLE, "task1"))), + // the instances table contains one instance + new Counted<>(1, new BulkAssert<>(new InstanceTable(mAuthority))), + // the instances table contains the given instance + new Counted<>(1, + new BulkAssert<>(new InstanceTable(mAuthority), + new Composite<>(new InstanceTestData(-1), + new CharSequenceRowData<>(Tasks.TITLE, "task1")), + new ReferringTo<>(Instances.TASK_ID, task))))); } - - /** - * Create a single instance and delete it. - */ + /** Create a single instance and delete it. */ @Test - public void testDeleteSingleInstance() - { + public void testDeleteSingleInstance() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TasksTable(mAuthority)); @@ -243,24 +211,22 @@ public class TaskProviderInstancesTest // create a local list new Put<>(taskList, new NameData("list1")), // insert a new task - new Put<>(task, new Referring<>(Tasks.LIST_ID, taskList, new CharSequenceRowData<>(Tasks.TITLE, "task1"))), + new Put<>(task, + new Referring<>(Tasks.LIST_ID, taskList, new CharSequenceRowData<>(Tasks.TITLE, "task1"))), // delete the instance - new BulkDelete<>(new InstanceTable(mAuthority), new ReferringTo<>(Instances.TASK_ID, task)) - ), resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - // the list does not contain a single task - new AssertEmptyTable<>(new TasksTable(mAuthority)), - new AssertEmptyTable<>(new InstanceTable(mAuthority)))); - + new BulkDelete<>(new InstanceTable(mAuthority), new ReferringTo<>(Instances.TASK_ID, task))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + // the list does not contain a single task + new AssertEmptyTable<>(new TasksTable(mAuthority)), + new AssertEmptyTable<>(new InstanceTable(mAuthority)))); } - /** - * Create a single instance and insert an override for exactly the same instance. + * Create a single instance and insert an override for exactly the same + * instance. */ @Test(expected = IllegalArgumentException.class) - public void testInsertSingleInstanceTwice() throws RemoteException, OperationApplicationException - { + public void testInsertSingleInstanceTwice() throws RemoteException, OperationApplicationException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TasksTable(mAuthority)); RowSnapshot instance = new VirtualRowSnapshot<>(new InstanceTable(mAuthority)); @@ -271,33 +237,29 @@ public class TaskProviderInstancesTest new BaseTransaction().with(new Seq<>( // create a local list new Put<>(taskList, new NameData("list1")), - // insert a new task into the tasks table (we insert a task to get a RowReference to the new row) + // insert a new task into the tasks table (we insert a task to get a + // RowReference to + // the new row) new Put<>(task, - new Composite<>( - new Referring<>(Tasks.LIST_ID, taskList), - new TimeData<>(dateTime), + new Composite<>(new Referring<>(Tasks.LIST_ID, taskList), new TimeData<>(dateTime), new TitleData("task1"))), - new Put<>(instance, - new Composite<>( - new Referring<>(Tasks.LIST_ID, taskList), - new CharSequenceRowData<>(Tasks.DTSTART, "1234"), - // insert an instance which would override the original instance, which already exists - new Referring<>(Tasks.ORIGINAL_INSTANCE_ID, task), - new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_TIME, dtstart), - new CharSequenceRowData<>(Tasks.TZ, "UTC"), - new CharSequenceRowData<>(Tasks.TITLE, "task1"))) - - )).commit(mClient); + new Put<>(instance, new Composite<>(new Referring<>(Tasks.LIST_ID, taskList), + new CharSequenceRowData<>(Tasks.DTSTART, "1234"), + // insert an instance which would override the original instance, which + // already exists + new Referring<>(Tasks.ORIGINAL_INSTANCE_ID, task), + new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_TIME, dtstart), + new CharSequenceRowData<>(Tasks.TZ, "UTC"), new CharSequenceRowData<>(Tasks.TITLE, "task1"))))) + .commit(mClient); } - /** - * Create a single instance and insert an override for a new instance, turning the event into a recurring event. + * Create a single instance and insert an override for a new instance, turning + * the event into a recurring event. */ @Ignore("Inserting instances is currently not supported.") @Test - public void testInsertSingleInstanceAddAnother() - { + public void testInsertSingleInstanceAddAnother() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TasksTable(mAuthority)); RowSnapshot instance = new VirtualRowSnapshot<>(new InstanceTable(mAuthority)); @@ -310,53 +272,52 @@ public class TaskProviderInstancesTest assertThat(new Seq<>( // create a local list new Put<>(taskList, new NameData("list1")), - // insert a new task into the tasks table (we insert a task to get a RowReference to the new row) + // insert a new task into the tasks table (we insert a task to get a + // RowReference to the + // new row) new Put<>(task, - new Composite( - new Referring<>(Tasks.LIST_ID, taskList), - new TimeData(dateTimeOriginal), + new Composite(new Referring<>(Tasks.LIST_ID, taskList), new TimeData(dateTimeOriginal), new TitleData("task1"))), new Put<>(instance, - new Composite( - new Referring<>(Tasks.LIST_ID, taskList), + new Composite(new Referring<>(Tasks.LIST_ID, taskList), new CharSequenceRowData<>(Tasks.DTSTART, "1234"), new CharSequenceRowData<>(Tasks.IS_ALLDAY, "0"), // insert an override instance new Referring<>(Tasks.ORIGINAL_INSTANCE_ID, task), new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_TIME, startOverride), new CharSequenceRowData<>(Tasks.TZ, "UTC"), - new CharSequenceRowData<>(Tasks.TITLE, "task override"))) - - ), resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - // the task list contains exactly two tasks - new Counted<>(2, new BulkAssert<>(new TasksTable(mAuthority))), - // check that the original task has RDATES now, one for the original start and one for the new override - new Assert<>(task, - new Composite( - new Referring<>(Tasks.LIST_ID, taskList), - new TimeData(dateTimeOriginal), - new CharSequenceRowData<>(Tasks.RDATE, "20180110T224500Z,20180111T224500Z"), - new TitleData("task1"))), - // and check there is a task for the override - new AssertRelated<>(new TasksTable(mAuthority), Tasks.ORIGINAL_INSTANCE_ID, task, - new Composite( - new Referring<>(Tasks.LIST_ID, taskList), - new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_TIME, startOverride), - new TimeData(new DateTime(1234)), - new TitleData("task override"))) + new CharSequenceRowData<>(Tasks.TITLE, "task override")))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + // the task list contains exactly two tasks + new Counted<>(2, new BulkAssert<>(new TasksTable(mAuthority))), + // check that the original task has RDATES now, one for the original start and + // one for + // the new override + new Assert<>(task, + new Composite(new Referring<>(Tasks.LIST_ID, taskList), + new TimeData(dateTimeOriginal), + new CharSequenceRowData<>(Tasks.RDATE, "20180110T224500Z,20180111T224500Z"), + new TitleData("task1"))), + // and check there is a task for the override + new AssertRelated<>(new TasksTable(mAuthority), Tasks.ORIGINAL_INSTANCE_ID, task, + new Composite(new Referring<>(Tasks.LIST_ID, taskList), + new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_TIME, startOverride), + new TimeData(new DateTime(1234)), new TitleData("task override"))) // TODO: enable tests below once recurrence has been implemented -// // the instances table contains two instances as well -// new Counted<>(2, new BulkAssert<>(new InstanceTable(mAuthority))), -// // one instance is related to the task -// new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, -// new Composite<>( -// new InstanceTestData(new Present<>(dateTimeOriginal), new Absent<>(), new Present<>(dateTimeOriginal), 0), -// new CharSequenceRowData<>(Tasks.TITLE, "task1"))), -// // the other instance is for the override -// new Assert<>(instance, new Composite<>( -// new InstanceTestData(new Present<>(new DateTime(1234)), new Absent<>(), new Present<>(dateTimeOverride), 0), -// new CharSequenceRowData<>(Tasks.TITLE, "task override"))) - )); + // // the instances table contains two instances as well + // new Counted<>(2, new BulkAssert<>(new InstanceTable(mAuthority))), + // // one instance is related to the task + // new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, + // task, + // new Composite<>( + // new InstanceTestData(new Present<>(dateTimeOriginal), + // new Absent<>(), new Present<>(dateTimeOriginal), 0), + // new CharSequenceRowData<>(Tasks.TITLE, "task1"))), + // // the other instance is for the override + // new Assert<>(instance, new Composite<>( + // new InstanceTestData(new Present<>(new DateTime(1234)), new + // Absent<>(), new Present<>(dateTimeOverride), 0), + // new CharSequenceRowData<>(Tasks.TITLE, "task override"))) + )); } } diff --git a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderObserverTest.java b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderObserverTest.java index 4784e53f9fdf362bcb1890f525eefe27f4f03d6d..a8c3fe84c9fc7e4f51da0c81453f2fabc5502bdf 100644 --- a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderObserverTest.java +++ b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderObserverTest.java @@ -16,13 +16,26 @@ package org.dmfs.provider.tasks; +import static org.dmfs.android.contentpal.testing.android.uri.UriMatcher.hasParam; +import static org.dmfs.provider.tasks.matchers.NotifiesMatcher.notifies; +import static org.dmfs.provider.tasks.matchers.UriMatcher.authority; +import static org.dmfs.provider.tasks.matchers.UriMatcher.path; +import static org.dmfs.provider.tasks.matchers.UriMatcher.scheme; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.emptyIterable; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.startsWith; + import android.accounts.Account; import android.content.ContentProviderClient; import android.content.Context; import android.content.OperationApplicationException; import android.os.Build; import android.os.RemoteException; - +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.OperationsQueue; import org.dmfs.android.contentpal.RowSnapshot; @@ -48,192 +61,112 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import static org.dmfs.android.contentpal.testing.android.uri.UriMatcher.hasParam; -import static org.dmfs.provider.tasks.matchers.NotifiesMatcher.notifies; -import static org.dmfs.provider.tasks.matchers.UriMatcher.authority; -import static org.dmfs.provider.tasks.matchers.UriMatcher.path; -import static org.dmfs.provider.tasks.matchers.UriMatcher.scheme; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.emptyIterable; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.startsWith; - - /** * Tests for {@link TaskProvider}. * * @author Marten Gajda */ @RunWith(AndroidJUnit4.class) -public class TaskProviderObserverTest -{ +public class TaskProviderObserverTest { private String mAuthority; private Context mContext; private ContentProviderClient mClient; private final Account testAccount = new Account("foo", "bar"); - @Before - public void setUp() throws Exception - { + public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); mAuthority = AuthorityUtil.taskAuthority(mContext); mClient = mContext.getContentResolver().acquireContentProviderClient(mAuthority); // Assert that tables are empty: OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new AssertEmptyTable<>(new TasksTable(mAuthority)), + queue.enqueue(new Seq>(new AssertEmptyTable<>(new TasksTable(mAuthority)), new AssertEmptyTable<>(new TaskListsTable(mAuthority)), new AssertEmptyTable<>(new InstanceTable(mAuthority)))); queue.flush(); } - @After - public void tearDown() throws Exception - { + public void tearDown() throws Exception { /* - TODO When Test Orchestration is available, there will be no need for clean up here and check in setUp(), every test method will run in separate instrumentation - https://android-developers.googleblog.com/2017/07/android-testing-support-library-10-is.html - https://developer.android.com/training/testing/junit-runner.html#using-android-test-orchestrator - */ + * TODO When Test Orchestration is available, there will be no need for clean up + * here and check in setUp(), every test method will run in separate + * instrumentation + * https://android-developers.googleblog.com/2017/07/android-testing-support- + * library-10-is.html + * https://developer.android.com/training/testing/junit-runner.html#using- + * android-test-orchestrator + */ // Clear the DB: BasicOperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new BulkDelete<>(new LocalTaskListsTable(mAuthority)), + queue.enqueue(new Seq>(new BulkDelete<>(new LocalTaskListsTable(mAuthority)), new BulkDelete<>(new Synced<>(testAccount, new TaskListsTable(mAuthority))))); queue.flush(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mClient.close(); - } - else - { + } else { mClient.release(); } } - - /** - * Test notifications for creating one task list and task. - */ + /** Test notifications for creating one task list and task. */ @Test - public void testSingleInsert() throws RemoteException, OperationApplicationException - { + public void testSingleInsert() throws RemoteException, OperationApplicationException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); OperationsQueue queue = new BasicOperationsQueue(mClient); - assertThat(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(task, new TitleData("task1"))), - notifies( - TaskContract.getContentUri(mAuthority), - queue, - containsInAnyOrder( - allOf( - scheme("content"), - authority(mAuthority), - path(is("/tasks")) - ), - allOf( - scheme("content"), - authority(mAuthority), - path(startsWith("/tasks/")) - ), - allOf( - scheme("content"), - authority(mAuthority), - path(startsWith("/instances")) - ), - allOf( - scheme("content"), - authority(mAuthority), - path(startsWith("/tasklists/")) - ), - allOf( - scheme("content"), - authority(mAuthority), - path(is("/tasklists")), + assertThat(new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(task, new TitleData("task1"))), + notifies(TaskContract.getContentUri(mAuthority), queue, + containsInAnyOrder(allOf(scheme("content"), authority(mAuthority), path(is("/tasks"))), + allOf(scheme("content"), authority(mAuthority), path(startsWith("/tasks/"))), + allOf(scheme("content"), authority(mAuthority), path(startsWith("/instances"))), + allOf(scheme("content"), authority(mAuthority), path(startsWith("/tasklists/"))), + allOf(scheme("content"), authority(mAuthority), path(is("/tasklists")), hasParam(TaskContract.CALLER_IS_SYNCADAPTER, "true"), hasParam(TaskContract.ACCOUNT_NAME, TaskContract.LOCAL_ACCOUNT_NAME), - hasParam(TaskContract.ACCOUNT_TYPE, TaskContract.LOCAL_ACCOUNT_TYPE) - )))); + hasParam(TaskContract.ACCOUNT_TYPE, TaskContract.LOCAL_ACCOUNT_TYPE))))); } - - /** - * Update a task and check the notifications. - */ + /** Update a task and check the notifications. */ @Test - public void testSingleUpdate() throws RemoteException, OperationApplicationException - { + public void testSingleUpdate() throws RemoteException, OperationApplicationException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue( - new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(task, new TitleData("task1")))); + queue.enqueue(new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(task, new TitleData("task1")))); queue.flush(); - assertThat(new Seq<>( - new Put<>(task, new TitleData("task1b"))), - notifies( - TaskContract.getContentUri(mAuthority), - queue, - // taskprovider should notity the tasks URI iself, the task diretory and the instances directory - containsInAnyOrder( - allOf( - scheme("content"), - authority(mAuthority), - path(is("/tasks")) - ), - allOf( - scheme("content"), - authority(mAuthority), - path(startsWith("/tasks/")) - ), - allOf( - scheme("content"), - authority(mAuthority), - path(is("/instances")) - )))); + assertThat(new Seq<>(new Put<>(task, new TitleData("task1b"))), + notifies(TaskContract.getContentUri(mAuthority), queue, + // taskprovider should notity the tasks URI iself, the task diretory and the + // instances + // directory + containsInAnyOrder(allOf(scheme("content"), authority(mAuthority), path(is("/tasks"))), + allOf(scheme("content"), authority(mAuthority), path(startsWith("/tasks/"))), + allOf(scheme("content"), authority(mAuthority), path(is("/instances")))))); } - /** - * Test that an update that doesn't change anything doesn't trigger a notification. + * Test that an update that doesn't change anything doesn't trigger a + * notification. */ @Test - public void testNoOpUpdate() throws RemoteException, OperationApplicationException - { + public void testNoOpUpdate() throws RemoteException, OperationApplicationException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue( - new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(task, new TitleData("task1")))); + queue.enqueue(new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(task, new TitleData("task1")))); queue.flush(); - assertThat(new Seq<>( - new Put<>(task, new TitleData("task1"))), - notifies( - TaskContract.getContentUri(mAuthority), - queue, + assertThat(new Seq<>(new Put<>(task, new TitleData("task1"))), + notifies(TaskContract.getContentUri(mAuthority), queue, // there should no notification emptyIterable())); } - } diff --git a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderRecurrenceTest.java b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderRecurrenceTest.java index 727bf5328180576ab03eda58c82fb1a0e2c233e1..b313739a62426d0a0927ee2fcfa9f810eeaaf307 100644 --- a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderRecurrenceTest.java +++ b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderRecurrenceTest.java @@ -16,10 +16,16 @@ package org.dmfs.provider.tasks; +import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; +import static org.dmfs.optional.Absent.absent; +import static org.junit.Assert.assertThat; + import android.content.ContentProviderClient; import android.content.Context; import android.os.Build; - +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; +import java.util.TimeZone; import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.OperationsQueue; import org.dmfs.android.contentpal.RowSnapshot; @@ -74,77 +80,58 @@ import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.TimeZone; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; -import static org.dmfs.optional.Absent.absent; -import static org.junit.Assert.assertThat; - - /** * Recurrence Tests for {@link TaskProvider}. * * @author Marten Gajda */ @RunWith(AndroidJUnit4.class) -public class TaskProviderRecurrenceTest -{ +public class TaskProviderRecurrenceTest { private String mAuthority; private Context mContext; private ContentProviderClient mClient; - @Before - public void setUp() throws Exception - { + public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); mAuthority = AuthorityUtil.taskAuthority(mContext); mClient = mContext.getContentResolver().acquireContentProviderClient(mAuthority); // Assert that tables are empty: OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new AssertEmptyTable<>(new TasksTable(mAuthority)), + queue.enqueue(new Seq>(new AssertEmptyTable<>(new TasksTable(mAuthority)), new AssertEmptyTable<>(new TaskListsTable(mAuthority)), new AssertEmptyTable<>(new InstanceTable(mAuthority)))); queue.flush(); } - @After - public void tearDown() throws Exception - { + public void tearDown() throws Exception { /* - TODO When Test Orchestration is available, there will be no need for clean up here and check in setUp(), every test method will run in separate instrumentation - https://android-developers.googleblog.com/2017/07/android-testing-support-library-10-is.html - https://developer.android.com/training/testing/junit-runner.html#using-android-test-orchestrator - */ + * TODO When Test Orchestration is available, there will be no need for clean up + * here and check in setUp(), every test method will run in separate + * instrumentation + * https://android-developers.googleblog.com/2017/07/android-testing-support- + * library-10-is.html + * https://developer.android.com/training/testing/junit-runner.html#using- + * android-test-orchestrator + */ // Clear the DB: BasicOperationsQueue queue = new BasicOperationsQueue(mClient); queue.enqueue(new SingletonIterable>(new BulkDelete<>(new LocalTaskListsTable(mAuthority)))); queue.flush(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mClient.close(); - } - else - { + } else { mClient.release(); } } - - /** - * Test if instances of a task with a DTSTART, DUE and an RRULE. - */ + /** Test if instances of a task with a DTSTART, DUE and an RRULE. */ @Test - public void testRRule() throws InvalidRecurrenceRuleException - { + public void testRRule() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -163,52 +150,57 @@ public class TaskProviderRecurrenceTest DateTime localDue = due.shiftTimeZone(TimeZone.getDefault()); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), -// new Counted<>(5, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*, - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 3rd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 4), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp())) */) - ); + new Composite<>(new TimeData<>(start, due), + new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", + RecurrenceRule.RfcMode.RFC2445_LAX))))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), + // new Counted<>(5, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start + .getTimestamp())) /* + * , // 2nd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(second, + * second.addDuration(hour), new Present<>(second), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * second.getTimestamp())), // 3rd instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(third, third.addDuration(hour), new + * Present<>(third), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fifth, fifth.addDuration(hour), new + * Present<>(fifth), 4), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - /** - * Test if instances of a task with a timed DTSTART, DUE and a floating RRULE UNTIL. + * Test if instances of a task with a timed DTSTART, DUE and a floating RRULE + * UNTIL. + * *

- * Note, this combination should not be accepted by the provider. For the time being, however, it should be tolerated instead of causing a crash. + * Note, this combination should not be accepted by the provider. For the time + * being, however, it should be tolerated instead of causing a crash. */ @Test - public void testRRuleWithFloatingMismatch() throws InvalidRecurrenceRuleException - { + public void testRRuleWithFloatingMismatch() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -227,50 +219,50 @@ public class TaskProviderRecurrenceTest DateTime localDue = due.shiftTimeZone(TimeZone.getDefault()); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;UNTIL=20180106", RecurrenceRule.RfcMode.RFC2445_LAX)))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;UNTIL=20180106"))), -// new Counted<>(5, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*, - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 3rd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 4), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp())) */) - ); + new Composite<>(new TimeData<>(start, due), + new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;UNTIL=20180106", + RecurrenceRule.RfcMode.RFC2445_LAX))))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;UNTIL=20180106"))), + // new Counted<>(5, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start + .getTimestamp())) /* + * , // 2nd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(second, + * second.addDuration(hour), new Present<>(second), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * second.getTimestamp())), // 3rd instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(third, third.addDuration(hour), new + * Present<>(third), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fifth, fifth.addDuration(hour), new + * Present<>(fifth), 4), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - - /** - * Test if instances of a task with an all-day DTSTART, DUE and an RRULE. - */ + /** Test if instances of a task with an all-day DTSTART, DUE and an RRULE. */ @Test - public void testAllDayRRule() throws InvalidRecurrenceRuleException - { + public void testAllDayRRule() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -289,52 +281,57 @@ public class TaskProviderRecurrenceTest DateTime localDue = due; - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), -// new Counted<>(5, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*, - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 3rd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 4), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp())) */) - ); + new Composite<>(new TimeData<>(start, due), + new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", + RecurrenceRule.RfcMode.RFC2445_LAX))))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), + // new Counted<>(5, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start + .getTimestamp())) /* + * , // 2nd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(second, + * second.addDuration(hour), new Present<>(second), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * second.getTimestamp())), // 3rd instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(third, third.addDuration(hour), new + * Present<>(third), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fifth, fifth.addDuration(hour), new + * Present<>(fifth), 4), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - /** - * Test if instances of a task with an all-day DTSTART, DUE and an RRULE with an absolute UNTIL + * Test if instances of a task with an all-day DTSTART, DUE and an RRULE with an + * absolute UNTIL + * *

- * Note, this combination should not be accepted by the provider. For the time being, however, it should be tolerated instead of causing a crash. + * Note, this combination should not be accepted by the provider. For the time + * being, however, it should be tolerated instead of causing a crash. */ @Test - public void testAllDayRRuleFloatingMismatch() throws InvalidRecurrenceRuleException - { + public void testAllDayRRuleFloatingMismatch() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -353,50 +350,50 @@ public class TaskProviderRecurrenceTest DateTime localDue = due; - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;UNTIL=20180106T120000Z", RecurrenceRule.RfcMode.RFC2445_LAX)))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;UNTIL=20180106T120000Z"))), -// new Counted<>(5, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*, - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 3rd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 4), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp())) */) - ); + new Composite<>(new TimeData<>(start, due), + new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;UNTIL=20180106T120000Z", + RecurrenceRule.RfcMode.RFC2445_LAX))))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;UNTIL=20180106T120000Z"))), + // new Counted<>(5, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start + .getTimestamp())) /* + * , // 2nd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(second, + * second.addDuration(hour), new Present<>(second), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * second.getTimestamp())), // 3rd instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(third, third.addDuration(hour), new + * Present<>(third), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fifth, fifth.addDuration(hour), new + * Present<>(fifth), 4), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - - /** - * Test if instances of a task with a DUE and an RRULE but no DTSTART. - */ + /** Test if instances of a task with a DUE and an RRULE but no DTSTART. */ @Test - public void testRRuleNoDtStart() throws InvalidRecurrenceRuleException - { + public void testRRuleNoDtStart() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -412,50 +409,50 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, - new Composite<>( - new DueData<>(due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new DueData<>(due), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), -// new Counted<>(5, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(absent(), new Present<>(localDue), new Present<>(due), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, due.getTimestamp()))/*, - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(absent(), new Present<>(second), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 3rd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(absent(), new Present<>(third), new Present<>(third), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(absent(), new Present<>(fourth), new Present<>(fourth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(absent(), new Present<>(fifth), new Present<>(fifth), 4), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp()))*/) - ); + new Composite<>(new DueData<>(due), + new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", + RecurrenceRule.RfcMode.RFC2445_LAX))))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new DueData<>(due), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), + // new Counted<>(5, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(absent(), new Present<>(localDue), new Present<>(due), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, due + .getTimestamp())) /* + * , // 2nd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(absent(), + * new Present<>(second), new Present<>(second), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * second.getTimestamp())), // 3rd instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(absent(), new Present<>(third), new + * Present<>(third), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(absent(), new Present<>(fourth), new + * Present<>(fourth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(absent(), new Present<>(fifth), new + * Present<>(fifth), 4), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - - /** - * Test if instances of a task with a DTSTART and an RRULE but no DUE - */ + /** Test if instances of a task with a DTSTART and an RRULE but no DUE */ @Test - public void testRRuleNoDue() throws InvalidRecurrenceRuleException - { + public void testRRuleNoDue() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -471,51 +468,51 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, - new Composite<>( - new TimeData<>(start), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), -// new Counted<>(5, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(new Present<>(localStart), absent(), new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*, - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(new Present<>(second), absent(), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 3rd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(new Present<>(third), absent(), new Present<>(third), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(new Present<>(fourth), absent(), new Present<>(fourth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(new Present<>(fifth), absent(), new Present<>(fifth), 4), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp()))*/) - ); + new Composite<>(new TimeData<>(start), + new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", + RecurrenceRule.RfcMode.RFC2445_LAX))))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), + // new Counted<>(5, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(new Present<>(localStart), absent(), new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start + .getTimestamp())) /* + * , // 2nd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(new + * Present<>(second), absent(), new Present<>(second), 1), + * new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * second.getTimestamp())), // 3rd instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(new Present<>(third), absent(), new + * Present<>(third), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(new Present<>(fourth), absent(), new + * Present<>(fourth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(new Present<>(fifth), absent(), new + * Present<>(fifth), 4), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - - /** - * Remove an instance from a task with an RRULE. - */ + /** Remove an instance from a task with an RRULE. */ @Ignore("Test tries to delete 3rd instance which has not been created because currently only 1 instance is expanded") @Test - public void testRRuleRemoveInstance() throws InvalidRecurrenceRuleException - { + public void testRRuleRemoveInstance() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -534,53 +531,46 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + new Put<>(task, new Composite<>(new TimeData<>(start, due), + new RRuleTaskData( + new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))), // remove the third instance new BulkDelete<>(instancesTable, - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp()))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), + new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())))), + resultsIn(mClient, new Assert<>(task, + new Composite<>(new TimeData<>(start, due), new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"), new CharSequenceRowData<>(Tasks.EXDATE, "20180106T123456Z"))), - new Counted<>(4, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp())), - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 4th instance (now 3rd): - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance (now 4th): - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp()))) - ); + new Counted<>(4, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp())), + // 2nd instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), + // 4th instance (now 3rd): + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 2), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), + // 5th instance (now 4th): + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 3), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp())))); } - - /** - * Test RRULE with overridden instance (inserted into the tasks table) - */ + /** Test RRULE with overridden instance (inserted into the tasks table) */ @Test - public void testRRuleWithOverride() throws InvalidRecurrenceRuleException - { + public void testRRuleWithOverride() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskOverride = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskOverride = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); Duration hour = new Duration(1, 0, 3600 /* 1 hour */); DateTime start = DateTime.parse("20180104T123456Z"); @@ -596,68 +586,73 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new TitleData("original"), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + new Put<>(task, new Composite<>(new TimeData<>(start, due), new TitleData("original"), + new RRuleTaskData( + new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))), // the override moves the instance by an hour - new Put<>(taskOverride, new Composite<>( - new TimeData<>(third.addDuration(hour), third.addDuration(hour).addDuration(hour)), - new TitleData("override"), - new OriginalInstanceData(task, third))) - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.TITLE, "original"), + new Put<>(taskOverride, + new Composite<>( + new TimeData<>(third.addDuration(hour), + third.addDuration(hour).addDuration(hour)), + new TitleData("override"), new OriginalInstanceData(task, third)))), + resultsIn(mClient, new Assert<>(task, + new Composite<>(new TimeData<>(start, due), new CharSequenceRowData<>(Tasks.TITLE, "original"), new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), - new Assert<>(taskOverride, - new Composite<>( - new TimeData<>(third.addDuration(hour), third.addDuration(hour).addDuration(hour)), - new CharSequenceRowData<>(Tasks.TITLE, "override"), - new OriginalInstanceData(task, third))), -// new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, taskOverride)), - new Counted<>(0, new AssertRelated<>(instancesTable, Instances.TASK_ID, taskOverride)), -// new Counted<>(4, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*, - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 3th instance (the overridden one): - new AssertRelated<>(instancesTable, Instances.TASK_ID, taskOverride, - new InstanceTestData(third.addDuration(hour), third.addDuration(hour).addDuration(hour), new Present<>(third), - 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 4), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp()))*/) - ); + new Assert<>(taskOverride, + new Composite<>( + new TimeData<>(third.addDuration(hour), third.addDuration(hour) + .addDuration(hour)), + new CharSequenceRowData<>(Tasks.TITLE, "override"), + new OriginalInstanceData(task, third))), + // new Counted<>(1, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, taskOverride)), + new Counted<>(0, new AssertRelated<>(instancesTable, Instances.TASK_ID, taskOverride)), + // new Counted<>(4, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start + .getTimestamp())) /* + * , // 2nd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(second, + * second.addDuration(hour), new Present<>(second), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * second.getTimestamp())), // 3th instance (the overridden + * one): new AssertRelated<>(instancesTable, + * Instances.TASK_ID, taskOverride, new + * InstanceTestData(third.addDuration(hour), + * third.addDuration(hour).addDuration(hour), new + * Present<>(third), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fifth, fifth.addDuration(hour), new + * Present<>(fifth), 4), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - /** - * Test RRULE with overridden instance (inserted into the tasks table) and a completed 1st instance. + * Test RRULE with overridden instance (inserted into the tasks table) and a + * completed 1st instance. */ @Test - public void testRRuleWith2ndOverrideAndCompleted1st() throws InvalidRecurrenceRuleException - { + public void testRRuleWith2ndOverrideAndCompleted1st() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskOverride = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskOverride = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); Duration hour = new Duration(1, 0, 3600 /* 1 hour */); DateTime start = DateTime.parse("20180104T123456Z"); @@ -673,54 +668,52 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new TitleData("original"), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + new Put<>(task, new Composite<>(new TimeData<>(start, due), new TitleData("original"), + new RRuleTaskData( + new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))), // the override moves the instance by an hour - new Put<>(taskOverride, new Composite<>( - new TimeData<>(second.addDuration(hour), second.addDuration(hour).addDuration(hour)), - new TitleData("override"), - new OriginalInstanceData(task, second))), - new Put<>(task, new StatusData<>(Tasks.STATUS_COMPLETED))), - resultsIn(mClient, - new Assert<>(task, + new Put<>(taskOverride, new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.TITLE, "original"), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"), - new StatusData<>(Tasks.STATUS_COMPLETED))), + new TimeData<>(second.addDuration(hour), + second.addDuration(hour).addDuration(hour)), + new TitleData("override"), new OriginalInstanceData(task, second))), + new Put<>(task, new StatusData<>(Tasks.STATUS_COMPLETED))), + resultsIn(mClient, new Assert<>(task, + new Composite<>(new TimeData<>(start, due), new CharSequenceRowData<>(Tasks.TITLE, "original"), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"), + new StatusData<>(Tasks.STATUS_COMPLETED))), new Assert<>(taskOverride, new Composite<>( - new TimeData<>(second.addDuration(hour), second.addDuration(hour).addDuration(hour)), + new TimeData<>(second.addDuration(hour), + second.addDuration(hour).addDuration(hour)), new CharSequenceRowData<>(Tasks.TITLE, "override"), new OriginalInstanceData(task, second))), // 1st (completed) instance: - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), -1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))), + new Counted<>(1, + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), -1), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))), // 2nd instance (now the current one): - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, taskOverride, - new InstanceTestData( - second.addDuration(hour), - second.addDuration(hour).addDuration(hour), - new Present<>(second), 0))))); + new Counted<>(1, + new AssertRelated<>(instancesTable, Instances.TASK_ID, taskOverride, + new InstanceTestData(second.addDuration(hour), + second.addDuration(hour).addDuration(hour), new Present<>(second), + 0))))); } - /** - * Test RRULE with overridden instance (inserted into the tasks table) and a deleted 1st instance. + * Test RRULE with overridden instance (inserted into the tasks table) and a + * deleted 1st instance. */ @Test - public void testRRuleWith2ndOverrideAndDeleted1st() throws InvalidRecurrenceRuleException - { + public void testRRuleWith2ndOverrideAndDeleted1st() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskOverride = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskOverride = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); Duration hour = new Duration(1, 0, 3600 /* 1 hour */); DateTime start = DateTime.parse("20180104T123456Z"); @@ -736,54 +729,51 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new TitleData("original"), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + new Put<>(task, new Composite<>(new TimeData<>(start, due), new TitleData("original"), + new RRuleTaskData( + new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))), // the override moves the instance by an hour - new Put<>(taskOverride, new Composite<>( - new TimeData<>(second.addDuration(hour), second.addDuration(hour).addDuration(hour)), - new TitleData("override"), - new OriginalInstanceData(task, second))), - // delete 1st instance - new BulkDelete<>(instancesTable, new AllOf<>( - new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.DISTANCE_FROM_CURRENT, "0")))), - resultsIn(mClient, - new Assert<>(task, + new Put<>(taskOverride, new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.TITLE, "original"), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"), - new CharSequenceRowData<>(Tasks.EXDATE, start.toString()), - new StatusData<>(Tasks.STATUS_DEFAULT))), + new TimeData<>(second.addDuration(hour), + second.addDuration(hour).addDuration(hour)), + new TitleData("override"), new OriginalInstanceData(task, second))), + // delete 1st instance + new BulkDelete<>(instancesTable, + new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), + new EqArg<>(Instances.DISTANCE_FROM_CURRENT, "0")))), + resultsIn(mClient, new Assert<>(task, + new Composite<>(new TimeData<>(start, due), new CharSequenceRowData<>(Tasks.TITLE, "original"), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"), + new CharSequenceRowData<>(Tasks.EXDATE, start.toString()), + new StatusData<>(Tasks.STATUS_DEFAULT))), new Assert<>(taskOverride, new Composite<>( - new TimeData<>(second.addDuration(hour), second.addDuration(hour).addDuration(hour)), + new TimeData<>(second.addDuration(hour), + second.addDuration(hour).addDuration(hour)), new CharSequenceRowData<>(Tasks.TITLE, "override"), new OriginalInstanceData(task, second))), // no instances point to the original task new Counted<>(0, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), // 2nd instance (now the current one): - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, taskOverride, - new InstanceTestData( - second.addDuration(hour), - second.addDuration(hour).addDuration(hour), - new Present<>(second), 0))))); + new Counted<>(1, + new AssertRelated<>(instancesTable, Instances.TASK_ID, taskOverride, + new InstanceTestData(second.addDuration(hour), + second.addDuration(hour).addDuration(hour), new Present<>(second), + 0))))); } - /** - * Test RRULE with overridden instance (via update on the instances table). This time we don't override the date time fields and expect the instance to - * inherit the original instance start and due (instead of the master start and due) + * Test RRULE with overridden instance (via update on the instances table). This + * time we don't override the date time fields and expect the instance to + * inherit the original instance start and due (instead of the master start and + * due) */ @Ignore("Test tries to override the 3rd instance which has not been created because we currently only expand one instance.") @Test - public void testRRuleWithOverride2() throws InvalidRecurrenceRuleException - { + public void testRRuleWithOverride2() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table tasksTable = new TasksTable(mAuthority); Table instancesTable = new InstanceTable(mAuthority); @@ -803,62 +793,56 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new TitleData("original"), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + new Put<>(task, new Composite<>(new TimeData<>(start, due), new TitleData("original"), + new RRuleTaskData( + new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)))), // the override just changes the title new BulkUpdate<>(instancesTable, - new Composite<>( - new CharSequenceRowData(Tasks.TITLE, "override")), - new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp()))) - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.TITLE, "original"), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), - new AssertRelated<>(tasksTable, Tasks.ORIGINAL_INSTANCE_ID, task, - new Composite<>( + new Composite<>(new CharSequenceRowData(Tasks.TITLE, "override")), + new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), + new CharSequenceRowData<>(Tasks.TITLE, "original"), new CharSequenceRowData<>( + Tasks.RRULE, "FREQ=DAILY;COUNT=5"))), + new AssertRelated<>(tasksTable, Tasks.ORIGINAL_INSTANCE_ID, task, new Composite<>( // note the task table contains the original time zone, not the default one - new TimeData<>(third.shiftTimeZone(start.getTimeZone()), third.shiftTimeZone(start.getTimeZone()).addDuration(hour)), + new TimeData<>(third.shiftTimeZone(start.getTimeZone()), + third.shiftTimeZone(start.getTimeZone()).addDuration(hour)), new CharSequenceRowData<>(Tasks.TITLE, "override"), new OriginalInstanceData(task, third))), - new Counted<>(4, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.ORIGINAL_INSTANCE_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp())), - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 3th instance (the overridden one). We don't have a row reference to this row, so we select it by the ORIGINAL_INSTANCE-ID - new AssertRelated<>(instancesTable, Tasks.ORIGINAL_INSTANCE_ID, task, - new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 4), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp()))) - ); + new Counted<>(4, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.ORIGINAL_INSTANCE_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp())), + // 2nd instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), + // 3th instance (the overridden one). We don't have a row reference to this row, + // so we + // select it by the ORIGINAL_INSTANCE-ID + new AssertRelated<>(instancesTable, Tasks.ORIGINAL_INSTANCE_ID, task, + new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 2), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), + // 4th instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 3), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), + // 5th instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 4), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp())))); } - - /** - * Test if instances of a task with a DTSTART, an RRULE and EXDATEs. - */ + /** Test if instances of a task with a DTSTART, an RRULE and EXDATEs. */ @Test - public void testRRuleWithExDates() throws InvalidRecurrenceRuleException - { + public void testRRuleWithExDates() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -877,44 +861,41 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)), - new ExDatesTaskData(new Seq<>(third, fifth)))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"), - new CharSequenceRowData<>(Tasks.EXDATE, "20180106T123456Z,20180108T123456Z"))), -// new Counted<>(3, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*, - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 4th instance (now 3rd): - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp()))*/) - ); + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + new Put<>(task, new Composite<>(new TimeData<>(start, due), + new RRuleTaskData( + new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX)), + new ExDatesTaskData(new Seq<>(third, fifth))))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), + new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;COUNT=5"), + new CharSequenceRowData<>(Tasks.EXDATE, "20180106T123456Z,20180108T123456Z"))), + // new Counted<>(3, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start + .getTimestamp())) /* + * , // 2nd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(second, + * second.addDuration(hour), new Present<>(second), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * second.getTimestamp())), // 4th instance (now 3rd): new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())) + */)); } - - /** - * Test if instances of a task with a DTSTART and RDATEs. - */ + /** Test if instances of a task with a DTSTART and RDATEs. */ @Test - public void testRDate() throws InvalidRecurrenceRuleException - { + public void testRDate() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -933,56 +914,53 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new RDatesTaskData(new Seq<>(start, second, third, fourth, fifth)))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.RDATE, - "20180104T123456Z," + - "20180105T123456Z," + - "20180106T123456Z," + - "20180107T123456Z," + - "20180108T123456Z" - ))), -// new Counted<>(5, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*, - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 3rd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 4), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp()))*/) - ); + new Composite<>(new TimeData<>(start, due), + new RDatesTaskData(new Seq<>(start, second, third, fourth, fifth))))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), + new CharSequenceRowData<>(Tasks.RDATE, + "20180104T123456Z," + "20180105T123456Z," + "20180106T123456Z," + + "20180107T123456Z," + "20180108T123456Z"))), + // new Counted<>(5, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start + .getTimestamp())) /* + * , // 2nd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(second, + * second.addDuration(hour), new Present<>(second), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * second.getTimestamp())), // 3rd instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(third, third.addDuration(hour), new + * Present<>(third), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fifth, fifth.addDuration(hour), new + * Present<>(fifth), 4), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - /** * Test if instances of a task with a DTSTART and RDATEs, add exdate afterwards. */ @Test - public void testRDateAddExDate() throws InvalidRecurrenceRuleException - { + public void testRDateAddExDate() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -1001,65 +979,59 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, - new Composite<>( - new TimeData<>(start, due), + new Composite<>(new TimeData<>(start, due), new RDatesTaskData(new Seq<>(start, second, third, fourth, fifth)))), // the third instance becomed an exdate now - new Put<>(task, - new Composite<>( - new ExDatesTaskData(new Seq<>(third)))) - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.RDATE, - "20180104T123456Z," + - "20180105T123456Z," + - "20180106T123456Z," + - "20180107T123456Z," + - "20180108T123456Z"), - new CharSequenceRowData<>(Tasks.EXDATE, - "20180106T123456Z" - ))), -// new Counted<>(4, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(localStart, localDue, new Present<>(start), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*, - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())), - // 3rd instance: -// new AssertRelated<>(instancesTable, Instances.TASK_ID, task, -// new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 2), -// new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp()))*/) - ); + new Put<>(task, new Composite<>(new ExDatesTaskData(new Seq<>(third))))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), + new CharSequenceRowData<>(Tasks.RDATE, + "20180104T123456Z," + "20180105T123456Z," + "20180106T123456Z," + + "20180107T123456Z," + "20180108T123456Z"), + new CharSequenceRowData<>(Tasks.EXDATE, "20180106T123456Z"))), + // new Counted<>(4, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(localStart, localDue, new Present<>(start), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start + .getTimestamp())) /* + * , // 2nd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(second, + * second.addDuration(hour), new Present<>(second), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * second.getTimestamp())), // 3rd instance: // new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * // new InstanceTestData(third, third.addDuration(hour), + * new Present<>(third), 2), // new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fifth, fifth.addDuration(hour), new + * Present<>(fifth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - - /** - * Test if instances of a task with a DTSTART and RDATEs, complete first. - */ + /** Test if instances of a task with a DTSTART and RDATEs, complete first. */ @Test - public void testRDateFirstComplete() throws InvalidRecurrenceRuleException - { + public void testRDateFirstComplete() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot override = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot override = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); Duration hour = new Duration(1, 0, 3600 /* 1 hour */); DateTime start = DateTime.parse("20180104T123456Z"); @@ -1075,68 +1047,63 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - // first insert new task, - new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new RDatesTaskData(new Seq<>(start, second, third, fourth, fifth)))), - // next, insert override - new Put<>(override, - new Composite<>( - new TimeData<>(start, due), - new OriginalInstanceData(task, start), - new StatusData<>(Tasks.STATUS_COMPLETED))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new CharSequenceRowData<>(Tasks.RDATE, - "20180104T123456Z," + - "20180105T123456Z," + - "20180106T123456Z," + - "20180107T123456Z," + - "20180108T123456Z" - ))), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, override)), -// new Counted<>(4, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, override, - new InstanceTestData(localStart, localDue, new Present<>(start), -1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp())), - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp()))/*, - // 3rd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp()))*/) - ); + assertThat(new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + // first insert new task, + new Put<>(task, + new Composite<>(new TimeData<>(start, due), + new RDatesTaskData(new Seq<>(start, second, third, fourth, fifth)))), + // next, insert override + new Put<>(override, + new Composite<>(new TimeData<>(start, due), new OriginalInstanceData(task, start), + new StatusData<>(Tasks.STATUS_COMPLETED)))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), + new CharSequenceRowData<>(Tasks.RDATE, + "20180104T123456Z," + "20180105T123456Z," + "20180106T123456Z," + + "20180107T123456Z," + "20180108T123456Z"))), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, override)), + // new Counted<>(4, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, override, + new InstanceTestData(localStart, localDue, new Present<>(start), -1), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp())), + // 2nd instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second + .getTimestamp())) /* + * , // 3rd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(third, + * third.addDuration(hour), new Present<>(third), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fifth, fifth.addDuration(hour), new + * Present<>(fifth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - /** - * Test if instances of a task with a DTSTART and RDATEs, complete first inserted first. + * Test if instances of a task with a DTSTART and RDATEs, complete first + * inserted first. */ @Test - public void testRDateFirstCompleteFirstInserted() throws InvalidRecurrenceRuleException - { + public void testRDateFirstCompleteFirstInserted() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot override = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot override = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); Duration hour = new Duration(1, 0, 3600 /* 1 hour */); DateTime start = DateTime.parse("20180104T123456Z"); @@ -1152,71 +1119,62 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - // first insert override - new Put<>(override, - new Composite<>( - new TimeData<>(start, due), + assertThat(new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + // first insert override + new Put<>(override, + new Composite<>(new TimeData<>(start, due), new OriginalInstanceSyncIdData("xyz", start), + new StatusData<>(Tasks.STATUS_COMPLETED))), + // then insert task + new Put<>(task, + new Composite<>(new SyncIdData("xyz"), new TimeData<>(start, due), + new RDatesTaskData(new Seq<>(start, second, third, fourth, fifth))))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), new SyncIdData("xyz"), + new CharSequenceRowData<>(Tasks.RDATE, + "20180104T123456Z," + "20180105T123456Z," + "20180106T123456Z," + + "20180107T123456Z," + "20180108T123456Z"))), + new Assert<>(override, + new Composite<>(new TimeData<>(start, due), new OriginalInstanceSyncIdData("xyz", start), new StatusData<>(Tasks.STATUS_COMPLETED))), - // then insert task - new Put<>(task, - new Composite<>( - new SyncIdData("xyz"), - new TimeData<>(start, due), - new RDatesTaskData(new Seq<>(start, second, third, fourth, fifth)))) - - ), resultsIn(mClient, - new Assert<>(task, - new Composite<>( - new TimeData<>(start, due), - new SyncIdData("xyz"), - new CharSequenceRowData<>(Tasks.RDATE, - "20180104T123456Z," + - "20180105T123456Z," + - "20180106T123456Z," + - "20180107T123456Z," + - "20180108T123456Z" - ))), - new Assert<>(override, - new Composite<>( - new TimeData<>(start, due), - new OriginalInstanceSyncIdData("xyz", start), - new StatusData<>(Tasks.STATUS_COMPLETED))), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, override)), -// new Counted<>(4, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), - // 1st instance, overridden and completed - new AssertRelated<>(instancesTable, Instances.TASK_ID, override, - new InstanceTestData(localStart, localDue, new Present<>(start), -1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp())), - // 2nd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp()))/*, - // 3rd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp()))*/) - ); + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, override)), + // new Counted<>(4, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // 1st instance, overridden and completed + new AssertRelated<>(instancesTable, Instances.TASK_ID, override, + new InstanceTestData(localStart, localDue, new Present<>(start), -1), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp())), + // 2nd instance: + new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second + .getTimestamp())) /* + * , // 3rd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(third, + * third.addDuration(hour), new Present<>(third), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fifth, fifth.addDuration(hour), new + * Present<>(fifth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - /** - * Test if instances of a task with a DTSTART and RDATEs, complete first via instances table. + * Test if instances of a task with a DTSTART and RDATEs, complete first via + * instances table. */ @Test - public void testRDateFirstCompleteViaInstances() throws InvalidRecurrenceRuleException - { + public void testRDateFirstCompleteViaInstances() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table tasksTable = new TasksTable(mAuthority); Table instancesTable = new InstanceTable(mAuthority); @@ -1236,70 +1194,71 @@ public class TaskProviderRecurrenceTest DateTime fourth = third.addDuration(day); DateTime fifth = fourth.addDuration(day); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - // first insert the task - new Put<>(task, - new Composite<>( - new TimeData<>(start, due), - new RDatesTaskData(start, second, third, fourth, fifth))), - // then complete the first instance - new BulkUpdate<>(instancesTable, new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED)), - new AllOf<>( - new ReferringTo<>(Instances.TASK_ID, task), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp())))), + assertThat(new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + // first insert the task + new Put<>(task, + new Composite<>(new TimeData<>(start, due), + new RDatesTaskData(start, second, third, fourth, fifth))), + // then complete the first instance + new BulkUpdate<>(instancesTable, + new CharSequenceRowData<>(Tasks.STATUS, String.valueOf(Tasks.STATUS_COMPLETED)), + new AllOf<>(new ReferringTo<>(Instances.TASK_ID, task), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp())))), resultsIn(mClient, - // we've already closed the first instance which has been detached, the master now points to the second instance - new Counted<>(1, - new Assert<>(task, - new Composite<>( - new TimeData<>(DateTime.parse("20180105T123456Z"), DateTime.parse("20180105T133456Z")), - new RDatesTaskData( - // "20180104T123456Z" // the detached instance - DateTime.parse("20180105T123456Z"), - DateTime.parse("20180106T123456Z"), - DateTime.parse("20180107T123456Z"), - DateTime.parse("20180108T123456Z"))))), - // there must be one task which is not equal to the original task, it's the detached instance - new Counted<>(1, - new BulkAssert<>(tasksTable, - new Composite<>( - new TimeData<>(start, due), - new StatusData<>(Tasks.STATUS_COMPLETED), - new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_ID, null), - new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_SYNC_ID, null), - new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_TIME, null)), - new Not<>(new ReferringTo<>(Tasks._ID, task)))), + // we've already closed the first instance which has been detached, the master + // now + // points to the second instance + new Counted<>(1, new Assert<>(task, new Composite<>( + new TimeData<>(DateTime.parse("20180105T123456Z"), DateTime.parse("20180105T133456Z")), + new RDatesTaskData( + // "20180104T123456Z" // the detached instance + DateTime.parse("20180105T123456Z"), DateTime.parse("20180106T123456Z"), + DateTime.parse("20180107T123456Z"), DateTime.parse("20180108T123456Z"))))), + // there must be one task which is not equal to the original task, it's the + // detached + // instance + new Counted<>(1, new BulkAssert<>(tasksTable, + new Composite<>(new TimeData<>(start, due), new StatusData<>(Tasks.STATUS_COMPLETED), + new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_ID, null), + new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_SYNC_ID, null), + new CharSequenceRowData<>(Tasks.ORIGINAL_INSTANCE_TIME, null)), + new Not<>(new ReferringTo<>(Tasks._ID, task)))), // and one instance which doesn't refer to the original task - new Counted<>(1, new BulkAssert<>(instancesTable, new Not<>(new ReferringTo<>(Instances.TASK_ID, task)))), + new Counted<>(1, + new BulkAssert<>(instancesTable, + new Not<>(new ReferringTo<>(Instances.TASK_ID, task)))), // but 4 instances of that original task -// new Counted<>(4, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), + // new Counted<>(4, new AssertRelated<>(instancesTable, + // Instances.TASK_ID, task)), new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)), // 1st instance, detached and completed - new Counted<>(1, new BulkAssert<>(instancesTable, - new Composite<>( - new InstanceTestData(localStart, localDue, absent(), -1)), - new AllOf<>( - new IsNull<>(Instances.INSTANCE_ORIGINAL_TIME), // the detached instance has no INSTANCE_ORIGINAL_TIME - new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), - // 2nd instance: new Counted<>(1, - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 0), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())))/*, - // 3rd instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 1), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())), - // 4th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 2), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())), - // 5th instance: - new AssertRelated<>(instancesTable, Instances.TASK_ID, task, - new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 3), - new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp()))*/) - ); + new BulkAssert<>(instancesTable, + new Composite<>(new InstanceTestData(localStart, localDue, absent(), -1)), + new AllOf<>(new IsNull<>(Instances.INSTANCE_ORIGINAL_TIME), // the detached + // instance has no + // INSTANCE_ORIGINAL_TIME + new Not<>(new ReferringTo<>(Instances.TASK_ID, task))))), + // 2nd instance: + new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task, + new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 0), + new EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, second + .getTimestamp()))) /* + * , // 3rd instance: new AssertRelated<>(instancesTable, + * Instances.TASK_ID, task, new InstanceTestData(third, + * third.addDuration(hour), new Present<>(third), 1), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * third.getTimestamp())), // 4th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fourth, fourth.addDuration(hour), + * new Present<>(fourth), 2), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fourth.getTimestamp())), // 5th instance: new + * AssertRelated<>(instancesTable, Instances.TASK_ID, task, + * new InstanceTestData(fifth, fifth.addDuration(hour), new + * Present<>(fifth), 3), new + * EqArg<>(Instances.INSTANCE_ORIGINAL_TIME, + * fifth.getTimestamp())) + */)); } - } diff --git a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderRelatingTest.java b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderRelatingTest.java index f7595805fb478535e9e98848768913de87032f42..14e62e6c896202cf695ef8053910f3da7e09fab0 100644 --- a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderRelatingTest.java +++ b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderRelatingTest.java @@ -16,12 +16,16 @@ package org.dmfs.provider.tasks; +import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; +import static org.junit.Assert.assertThat; + import android.accounts.Account; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; import android.os.Build; - +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.OperationsQueue; import org.dmfs.android.contentpal.RowSnapshot; @@ -58,31 +62,21 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; -import static org.junit.Assert.assertThat; - - /** * Tests for {@link TaskProvider} reparenting feature. * * @author Marten Gajda */ @RunWith(AndroidJUnit4.class) -public class TaskProviderRelatingTest -{ +public class TaskProviderRelatingTest { private ContentResolver mResolver; private String mAuthority; private Context mContext; private ContentProviderClient mClient; private final Account testAccount = new Account("foo", "bar"); - @Before - public void setUp() throws Exception - { + public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); mResolver = mContext.getContentResolver(); mAuthority = AuthorityUtil.taskAuthority(mContext); @@ -90,95 +84,88 @@ public class TaskProviderRelatingTest // Assert that tables are empty: OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new AssertEmptyTable<>(new TasksTable(mAuthority)), + queue.enqueue(new Seq>(new AssertEmptyTable<>(new TasksTable(mAuthority)), new AssertEmptyTable<>(new TaskListsTable(mAuthority)), new AssertEmptyTable<>(new PropertiesTable(mAuthority)), new AssertEmptyTable<>(new InstanceTable(mAuthority)))); queue.flush(); } - @After - public void tearDown() throws Exception - { + public void tearDown() throws Exception { /* - TODO When Test Orchestration is available, there will be no need for clean up here and check in setUp(), every test method will run in separate instrumentation - https://android-developers.googleblog.com/2017/07/android-testing-support-library-10-is.html - https://developer.android.com/training/testing/junit-runner.html#using-android-test-orchestrator - */ + * TODO When Test Orchestration is available, there will be no need for clean up + * here and check in setUp(), every test method will run in separate + * instrumentation + * https://android-developers.googleblog.com/2017/07/android-testing-support- + * library-10-is.html + * https://developer.android.com/training/testing/junit-runner.html#using- + * android-test-orchestrator + */ // Clear the DB: BasicOperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new BulkDelete<>(new LocalTaskListsTable(mAuthority)), + queue.enqueue(new Seq>(new BulkDelete<>(new LocalTaskListsTable(mAuthority)), new BulkDelete<>(new PropertiesTable(mAuthority)), new BulkDelete<>(new Synced<>(testAccount, new TaskListsTable(mAuthority))))); queue.flush(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mClient.close(); - } - else - { + } else { mClient.release(); } } - /** - * Create 1 local task list, then create a child Task, related to a parent UID and finally the parent. + * Create 1 local task list, then create a child Task, related to a parent UID + * and finally the parent. */ @Test - public void testRelateTask() - { - RowSnapshot taskList = new VirtualRowSnapshot<>(new Synced<>(testAccount, new TaskListsTable(mAuthority))); - RowSnapshot taskChild = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new Synced<>(testAccount, new TasksTable(mAuthority)))); - RowSnapshot taskParent = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new Synced<>(testAccount, new TasksTable(mAuthority)))); - - assertThat(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(taskChild, new Composite<>( - new TitleData("child"), - new CharSequenceRowData<>(Tasks._UID, "childUID"))), + public void testRelateTask() { + RowSnapshot taskList = new VirtualRowSnapshot<>( + new Synced<>(testAccount, new TaskListsTable(mAuthority))); + RowSnapshot taskChild = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new Synced<>(testAccount, new TasksTable(mAuthority)))); + RowSnapshot taskParent = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new Synced<>(testAccount, new TasksTable(mAuthority)))); + + assertThat( + new Seq<>(new Put<>(taskList, new NameData("list1")), + new Put<>( + taskChild, + new Composite<>(new TitleData("child"), + new CharSequenceRowData<>(Tasks._UID, "childUID"))), new Insert<>(new PropertiesTable(mAuthority), new Composite<>( - new CharSequenceRowData<>(TaskContract.Property.Relation.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new CharSequenceRowData<>(TaskContract.Property.Relation.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), new Referring<>(TaskContract.Property.Relation.TASK_ID, taskChild), new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_UID, "parentUID"), - new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)) - )), - new Put<>(taskParent, new Composite<>( - new TitleData("parent"), - new CharSequenceRowData<>(Tasks._UID, "parentUID"))) - ), - resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - new Assert<>(taskChild, new Composite<>( - new TitleData("child"), - new CharSequenceRowData<>(Tasks._UID, "childUID"), + new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, + String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)))), + new Put<>(taskParent, + new Composite<>(new TitleData("parent"), + new CharSequenceRowData<>(Tasks._UID, "parentUID")))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), new Assert<>(taskChild, + new Composite<>(new TitleData("child"), new CharSequenceRowData<>(Tasks._UID, "childUID"), new Referring<>(Tasks.PARENT_ID, taskParent))), - new Assert<>(taskParent, new Composite<>( - new CharSequenceRowData<>(Tasks._UID, "parentUID"), - new TitleData("parent"))), - new Counted<>(1, new BulkAssert<>( - new PropertiesTable(mAuthority), - new Composite<>( - new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, - String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)), - new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_UID, "parentUID"), - new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskParent) - ), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild) - ))), - new Counted<>(0, new BulkAssert<>( - new PropertiesTable(mAuthority), + new Assert<>(taskParent, + new Composite<>(new CharSequenceRowData<>(Tasks._UID, "parentUID"), + new TitleData("parent"))), + new Counted<>(1, new BulkAssert<>(new PropertiesTable(mAuthority), new Composite<>( + new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, + String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)), + new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_UID, "parentUID"), + new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskParent)), new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent) - ))) - )); + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild)))), + new Counted<>(0, + new BulkAssert<>(new PropertiesTable(mAuthority), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent)))))); } } diff --git a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderReparentingTest.java b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderReparentingTest.java index 57eedc1fda205bf5bc9dfe8d6d22362726f29d40..0c8fb6ca3d4883399548058c4168840472d4f22b 100644 --- a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderReparentingTest.java +++ b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderReparentingTest.java @@ -16,12 +16,16 @@ package org.dmfs.provider.tasks; +import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; +import static org.junit.Assert.assertThat; + import android.accounts.Account; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; import android.os.Build; - +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.OperationsQueue; import org.dmfs.android.contentpal.RowSnapshot; @@ -58,31 +62,21 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; -import static org.junit.Assert.assertThat; - - /** * Tests for {@link TaskProvider} reparenting feature. * * @author Marten Gajda */ @RunWith(AndroidJUnit4.class) -public class TaskProviderReparentingTest -{ +public class TaskProviderReparentingTest { private ContentResolver mResolver; private String mAuthority; private Context mContext; private ContentProviderClient mClient; private final Account testAccount = new Account("foo", "bar"); - @Before - public void setUp() throws Exception - { + public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); mResolver = mContext.getContentResolver(); mAuthority = AuthorityUtil.taskAuthority(mContext); @@ -90,303 +84,263 @@ public class TaskProviderReparentingTest // Assert that tables are empty: OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new AssertEmptyTable<>(new TasksTable(mAuthority)), + queue.enqueue(new Seq>(new AssertEmptyTable<>(new TasksTable(mAuthority)), new AssertEmptyTable<>(new TaskListsTable(mAuthority)), new AssertEmptyTable<>(new PropertiesTable(mAuthority)), new AssertEmptyTable<>(new InstanceTable(mAuthority)))); queue.flush(); } - @After - public void tearDown() throws Exception - { + public void tearDown() throws Exception { /* - TODO When Test Orchestration is available, there will be no need for clean up here and check in setUp(), every test method will run in separate instrumentation - https://android-developers.googleblog.com/2017/07/android-testing-support-library-10-is.html - https://developer.android.com/training/testing/junit-runner.html#using-android-test-orchestrator - */ + * TODO When Test Orchestration is available, there will be no need for clean up + * here and check in setUp(), every test method will run in separate + * instrumentation + * https://android-developers.googleblog.com/2017/07/android-testing-support- + * library-10-is.html + * https://developer.android.com/training/testing/junit-runner.html#using- + * android-test-orchestrator + */ // Clear the DB: BasicOperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new BulkDelete<>(new LocalTaskListsTable(mAuthority)), + queue.enqueue(new Seq>(new BulkDelete<>(new LocalTaskListsTable(mAuthority)), new BulkDelete<>(new PropertiesTable(mAuthority)), new BulkDelete<>(new Synced<>(testAccount, new TaskListsTable(mAuthority))))); queue.flush(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mClient.close(); - } - else - { + } else { mClient.release(); } } - - /** - * Create 1 local task list and a parent and a child task. - */ + /** Create 1 local task list and a parent and a child task. */ @Test - public void testRelateTask() - { + public void testRelateTask() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); - RowSnapshot taskChild = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskParent = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - - assertThat(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(taskParent, new TitleData("parent")), - new Put<>(taskChild, new Composite<>( - new TitleData("child"), - new Referring<>(Tasks.PARENT_ID, taskParent))) - ), - resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - new Assert<>(taskChild, new Composite<>( - new TitleData("child"), - new Referring<>(Tasks.PARENT_ID, taskParent))), - new Assert<>(taskParent, new Composite<>( - new TitleData("parent"))), - new Counted<>(1, new BulkAssert<>( - new PropertiesTable(mAuthority), - new Composite<>( - new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, - String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)), - new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskParent) - ), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild) - ))), - new Counted<>(0, new BulkAssert<>( - new PropertiesTable(mAuthority), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent) - ))) - )); + RowSnapshot taskChild = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskParent = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + + assertThat( + new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(taskParent, new TitleData("parent")), + new Put<>(taskChild, + new Composite<>(new TitleData("child"), new Referring<>(Tasks.PARENT_ID, taskParent)))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + new Assert<>(taskChild, + new Composite<>(new TitleData("child"), new Referring<>(Tasks.PARENT_ID, taskParent))), + new Assert<>(taskParent, new Composite<>(new TitleData("parent"))), + new Counted<>(1, + new BulkAssert<>(new PropertiesTable(mAuthority), + new Composite<>( + new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, + String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)), + new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskParent)), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild)))), + new Counted<>(0, + new BulkAssert<>(new PropertiesTable(mAuthority), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent)))))); } - /** - * Create 1 local task list and 2 tasks, in a second operation make the second one parent of the first one. + * Create 1 local task list and 2 tasks, in a second operation make the second + * one parent of the first one. */ @Test - public void testAdoptTask() - { + public void testAdoptTask() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); - RowSnapshot taskChild = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskParent = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskChild = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskParent = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); - assertThat(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(taskChild, new TitleData("child")), + assertThat( + new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(taskChild, new TitleData("child")), new Put<>(taskParent, new TitleData("parent")), - new Put<>(taskChild, new Referring<>(Tasks.PARENT_ID, taskParent)) - ), - resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - new Assert<>(taskChild, new Composite<>( - new TitleData("child"), - new Referring<>(Tasks.PARENT_ID, taskParent))), - new Assert<>(taskParent, new Composite<>( - new TitleData("parent"))), - new Counted<>(1, new BulkAssert<>( - new PropertiesTable(mAuthority), - new Composite<>( - new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, - String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)), - new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskParent) - ), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild) - ))), - new Counted<>(0, new BulkAssert<>( - new PropertiesTable(mAuthority), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent) - ))) - )); + new Put<>(taskChild, new Referring<>(Tasks.PARENT_ID, taskParent))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + new Assert<>(taskChild, + new Composite<>(new TitleData("child"), new Referring<>(Tasks.PARENT_ID, taskParent))), + new Assert<>(taskParent, new Composite<>(new TitleData("parent"))), + new Counted<>(1, + new BulkAssert<>(new PropertiesTable(mAuthority), + new Composite<>( + new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, + String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)), + new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskParent)), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild)))), + new Counted<>(0, + new BulkAssert<>(new PropertiesTable(mAuthority), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent)))))); } - /** - * Create 1 local task list and 3 tasks, create parent child relationship and change it afterwards + * Create 1 local task list and 3 tasks, create parent child relationship and + * change it afterwards */ @Test - public void testReparentTask() - { + public void testReparentTask() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); - RowSnapshot taskChild = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskParent = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskNewParent = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - - assertThat(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(taskParent, new TitleData("parent")), - new Put<>(taskChild, new Composite<>( - new TitleData("child"), - new Referring<>(Tasks.PARENT_ID, taskParent))), + RowSnapshot taskChild = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskParent = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskNewParent = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + + assertThat( + new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(taskParent, new TitleData("parent")), + new Put<>(taskChild, + new Composite<>(new TitleData("child"), new Referring<>(Tasks.PARENT_ID, taskParent))), new Put<>(taskNewParent, new TitleData("newParent")), - new Put<>(taskChild, new Referring<>(Tasks.PARENT_ID, taskNewParent)) - ), - resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - new Assert<>(taskChild, new Composite<>( - new TitleData("child"), - new Referring<>(Tasks.PARENT_ID, taskNewParent))), - new Assert<>(taskParent, new Composite<>( - new TitleData("parent"))), - new Assert<>(taskNewParent, new Composite<>( - new TitleData("newParent"))), - - new Counted<>(1, new BulkAssert<>( - new PropertiesTable(mAuthority), - new Composite<>( + new Put<>(taskChild, new Referring<>(Tasks.PARENT_ID, taskNewParent))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + new Assert<>(taskChild, + new Composite<>(new TitleData("child"), + new Referring<>(Tasks.PARENT_ID, taskNewParent))), + new Assert<>(taskParent, new Composite<>(new TitleData("parent"))), + new Assert<>(taskNewParent, new Composite<>(new TitleData("newParent"))), + new Counted<>(1, + new BulkAssert<>(new PropertiesTable(mAuthority), new Composite<>( new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)), - new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskNewParent) - ), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild) - ))), - new Counted<>(0, new BulkAssert<>( - new PropertiesTable(mAuthority), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent) - ))), - new Counted<>(0, new BulkAssert<>( - new PropertiesTable(mAuthority), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskNewParent) - ))) - )); + new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskNewParent)), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild)))), + new Counted<>(0, + new BulkAssert<>(new PropertiesTable(mAuthority), new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent)))), + new Counted<>(0, + new BulkAssert<>(new PropertiesTable(mAuthority), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskNewParent)))))); } - /** - * Create 1 local task list and 4 tasks, create parent child relationship with a sibling and change it afterwards + * Create 1 local task list and 4 tasks, create parent child relationship with a + * sibling and change it afterwards */ @Test - public void testReparentTaskWithSibling() - { + public void testReparentTaskWithSibling() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); - RowSnapshot taskChild = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskParent = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskNewParent = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskSibling = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - - assertThat(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(taskParent, new TitleData("parent")), - new Put<>(taskChild, new Composite<>( - new TitleData("child"), - new Referring<>(Tasks.PARENT_ID, taskParent))), + RowSnapshot taskChild = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskParent = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskNewParent = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskSibling = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + + assertThat( + new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(taskParent, new TitleData("parent")), + new Put<>(taskChild, + new Composite<>(new TitleData("child"), new Referring<>(Tasks.PARENT_ID, taskParent))), new Put<>(taskNewParent, new TitleData("newParent")), new Put<>(taskSibling, new TitleData("sibling")), - new Insert<>(new PropertiesTable(mAuthority), new Composite<>( - new CharSequenceRowData<>(TaskContract.Property.Relation.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new Referring<>(TaskContract.Property.Relation.TASK_ID, taskSibling), - new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskChild), - new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, String.valueOf( - TaskContract.Property.Relation.RELTYPE_SIBLING)) - )), - new Put<>(taskChild, new Referring<>(Tasks.PARENT_ID, taskNewParent)) - ), - resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - new Assert<>(taskChild, new Composite<>( - new TitleData("child"), - new Referring<>(Tasks.PARENT_ID, taskNewParent))), - new Assert<>(taskParent, new Composite<>( - new TitleData("parent"))), - new Assert<>(taskNewParent, new Composite<>( - new TitleData("newParent"))), - new Assert<>(taskSibling, new Composite<>( - new TitleData("sibling"))), - - new Counted<>(1, new BulkAssert<>( - new PropertiesTable(mAuthority), + new Insert<>(new PropertiesTable(mAuthority), new Composite<>( + new CharSequenceRowData<>(TaskContract.Property.Relation.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new Referring<>(TaskContract.Property.Relation.TASK_ID, taskSibling), + new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskChild), + new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, + String.valueOf(TaskContract.Property.Relation.RELTYPE_SIBLING)))), + new Put<>(taskChild, new Referring<>(Tasks.PARENT_ID, taskNewParent))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + new Assert<>(taskChild, + new Composite<>(new TitleData("child"), + new Referring<>(Tasks.PARENT_ID, taskNewParent))), + new Assert<>(taskParent, new Composite<>(new TitleData("parent"))), + new Assert<>(taskNewParent, new Composite<>(new TitleData("newParent"))), + new Assert<>(taskSibling, new Composite<>(new TitleData("sibling"))), + new Counted<>(1, + new BulkAssert<>(new PropertiesTable(mAuthority), new Composite<>( new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_TYPE, String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)), - new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskNewParent) - ), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild) - ))), - new Counted<>(0, new BulkAssert<>( - new PropertiesTable(mAuthority), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent) - ))), - // yikes the sibling became an orphan because it has no relation to its parent anymore. + new Referring<>(TaskContract.Property.Relation.RELATED_ID, taskNewParent)), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild)))), + new Counted<>(0, + new BulkAssert<>(new PropertiesTable(mAuthority), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent)))), + // yikes the sibling became an orphan because it has no relation to its parent + // anymore. // this should be fixed, see https://github.com/dmfs/opentasks/issues/932 - new Counted<>(0, new BulkAssert<>( - new PropertiesTable(mAuthority), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskSibling) - ))), - new Counted<>(0, new BulkAssert<>( - new PropertiesTable(mAuthority), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskNewParent) - ))) - )); + new Counted<>(0, + new BulkAssert<>(new PropertiesTable(mAuthority), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskSibling)))), + new Counted<>(0, + new BulkAssert<>(new PropertiesTable(mAuthority), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskNewParent)))))); } - /** - * Create 1 local task list and 2 tasks, create parent child relationship and remove it + * Create 1 local task list and 2 tasks, create parent child relationship and + * remove it */ @Test - public void testOrphanTask() - { + public void testOrphanTask() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); - RowSnapshot taskChild = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - RowSnapshot taskParent = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - - assertThat(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(taskParent, new TitleData("parent")), - new Put<>(taskChild, new Composite<>( - new TitleData("child"), - new Referring<>(Tasks.PARENT_ID, taskParent))), - new Put<>(taskChild, new CharSequenceRowData<>(Tasks.PARENT_ID, null)) - ), - resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - new Assert<>(taskChild, new Composite<>( - new TitleData("child"), - new CharSequenceRowData<>(Tasks.PARENT_ID, null))), - new Assert<>(taskParent, new Composite<>( - new TitleData("parent"))), - - new Counted<>(0, new BulkAssert<>( - new PropertiesTable(mAuthority), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild) - ))), - new Counted<>(0, new BulkAssert<>( - new PropertiesTable(mAuthority), - new AllOf<>( - new EqArg<>(TaskContract.Properties.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent) - ))) - )); + RowSnapshot taskChild = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + RowSnapshot taskParent = new VirtualRowSnapshot<>( + new TaskListScoped(taskList, new TasksTable(mAuthority))); + + assertThat( + new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(taskParent, new TitleData("parent")), + new Put<>(taskChild, + new Composite<>(new TitleData("child"), new Referring<>(Tasks.PARENT_ID, taskParent))), + new Put<>(taskChild, new CharSequenceRowData<>(Tasks.PARENT_ID, null))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + new Assert<>(taskChild, + new Composite<>(new TitleData("child"), + new CharSequenceRowData<>(Tasks.PARENT_ID, null))), + new Assert<>(taskParent, new Composite<>(new TitleData("parent"))), + new Counted<>(0, + new BulkAssert<>(new PropertiesTable(mAuthority), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskChild)))), + new Counted<>(0, + new BulkAssert<>(new PropertiesTable(mAuthority), + new AllOf<>( + new EqArg<>(TaskContract.Properties.MIMETYPE, + TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + new ReferringTo<>(TaskContract.Properties.TASK_ID, taskParent)))))); } } diff --git a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderTest.java b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderTest.java index 47a8d9d3e8a44a97c10d6ae763a171e3d8d5fc70..4adea98b520d195879409bb7bde157779e6bfe3f 100644 --- a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderTest.java +++ b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/TaskProviderTest.java @@ -16,13 +16,19 @@ package org.dmfs.provider.tasks; +import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; +import static org.dmfs.optional.Absent.absent; +import static org.junit.Assert.assertThat; + import android.accounts.Account; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.os.Build; - +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; +import java.util.TimeZone; import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.OperationsQueue; import org.dmfs.android.contentpal.RowSnapshot; @@ -72,16 +78,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.TimeZone; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import static org.dmfs.android.contenttestpal.ContentMatcher.resultsIn; -import static org.dmfs.optional.Absent.absent; -import static org.junit.Assert.assertThat; - - /** * Tests for {@link TaskProvider}. * @@ -90,18 +86,15 @@ import static org.junit.Assert.assertThat; * @author Marten Gajda */ @RunWith(AndroidJUnit4.class) -public class TaskProviderTest -{ +public class TaskProviderTest { private ContentResolver mResolver; private String mAuthority; private Context mContext; private ContentProviderClient mClient; private final Account testAccount = new Account("foo", "bar"); - @Before - public void setUp() throws Exception - { + public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); mResolver = mContext.getContentResolver(); mAuthority = AuthorityUtil.taskAuthority(mContext); @@ -109,101 +102,78 @@ public class TaskProviderTest // Assert that tables are empty: OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new AssertEmptyTable<>(new TasksTable(mAuthority)), + queue.enqueue(new Seq>(new AssertEmptyTable<>(new TasksTable(mAuthority)), new AssertEmptyTable<>(new TaskListsTable(mAuthority)), new AssertEmptyTable<>(new InstanceTable(mAuthority)))); queue.flush(); } - @After - public void tearDown() throws Exception - { + public void tearDown() throws Exception { /* - TODO When Test Orchestration is available, there will be no need for clean up here and check in setUp(), every test method will run in separate instrumentation - https://android-developers.googleblog.com/2017/07/android-testing-support-library-10-is.html - https://developer.android.com/training/testing/junit-runner.html#using-android-test-orchestrator - */ + * TODO When Test Orchestration is available, there will be no need for clean up + * here and check in setUp(), every test method will run in separate + * instrumentation + * https://android-developers.googleblog.com/2017/07/android-testing-support- + * library-10-is.html + * https://developer.android.com/training/testing/junit-runner.html#using- + * android-test-orchestrator + */ // Clear the DB: BasicOperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new BulkDelete<>(new LocalTaskListsTable(mAuthority)), + queue.enqueue(new Seq>(new BulkDelete<>(new LocalTaskListsTable(mAuthority)), new BulkDelete<>(new Synced<>(testAccount, new TaskListsTable(mAuthority))))); queue.flush(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { mClient.close(); - } - else - { + } else { mClient.release(); } } - /** - * Create 1 local task list and 1 task, check values in TaskLists, Tasks, Instances tables. + * Create 1 local task list and 1 task, check values in TaskLists, Tasks, + * Instances tables. */ @Test - public void testSingleInsert() - { + public void testSingleInsert() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); - assertThat(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(task, new TitleData("task1")) - - ), resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - new Assert<>(task, new Composite<>( - new TitleData("task1"), - new VersionData(0))), - new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData(0), - new CharSequenceRowData<>(Tasks.TZ, null)) - ))); + assertThat(new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(task, new TitleData("task1"))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + new Assert<>(task, new Composite<>(new TitleData("task1"), new VersionData(0))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite(new InstanceTestData(0), + new CharSequenceRowData<>(Tasks.TZ, null))))); } - /** - * Create 1 local task list and 1 task, update task via instances table and check values in TaskLists, Tasks, Instances tables. + * Create 1 local task list and 1 task, update task via instances table and + * check values in TaskLists, Tasks, Instances tables. */ @Test - public void testSingleInsertUpdateInstance() - { + public void testSingleInsertUpdateInstance() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); Table instancesTable = new InstanceTable(mAuthority); - assertThat(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(task, new TitleData("task1")), - new BulkUpdate<>(instancesTable, new CharSequenceRowData<>(Tasks.TITLE, "task updated"), new ReferringTo<>(Instances.TASK_ID, task)) - - ), resultsIn(mClient, - new Assert<>(taskList, new NameData("list1")), - new Assert<>(task, new Composite<>( - new TitleData("task updated"), - new VersionData(1))), - new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData(0), - new CharSequenceRowData<>(Tasks.TZ, null)) - ))); + assertThat( + new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(task, new TitleData("task1")), + new BulkUpdate<>(instancesTable, new CharSequenceRowData<>(Tasks.TITLE, "task updated"), + new ReferringTo<>(Instances.TASK_ID, task))), + resultsIn(mClient, new Assert<>(taskList, new NameData("list1")), + new Assert<>(task, new Composite<>(new TitleData("task updated"), new VersionData(1))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite(new InstanceTestData(0), + new CharSequenceRowData<>(Tasks.TZ, null))))); } - - /** - * Create 2 task list and 3 tasks, check values. - */ + /** Create 2 task list and 3 tasks, check values. */ @Test - public void testMultipleInserts() - { + public void testMultipleInserts() { Table taskListsTable = new LocalTaskListsTable(mAuthority); RowSnapshot taskList1 = new VirtualRowSnapshot<>(taskListsTable); RowSnapshot taskList2 = new VirtualRowSnapshot<>(taskListsTable); @@ -211,50 +181,29 @@ public class TaskProviderTest RowSnapshot task2 = new VirtualRowSnapshot<>(new TaskListScoped(taskList1, new TasksTable(mAuthority))); RowSnapshot task3 = new VirtualRowSnapshot<>(new TaskListScoped(taskList2, new TasksTable(mAuthority))); - assertThat(new Seq<>( - new Put<>(taskList1, new NameData("list1")), - new Put<>(taskList2, new NameData("list2")), - new Put<>(task1, new TitleData("task1")), - new Put<>(task2, new TitleData("task2")), - new Put<>(task3, new TitleData("task3")) - - ), resultsIn(mClient, - new Assert<>(taskList1, new NameData("list1")), - new Assert<>(taskList2, new NameData("list2")), - new Assert<>(task1, new Composite<>( - new TitleData("task1"), - new VersionData(0))), - new Assert<>(task2, new Composite<>( - new TitleData("task2"), - new VersionData(0))), - new Assert<>(task3, new Composite<>( - new TitleData("task3"), - new VersionData(0))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task1, - new Composite( - new InstanceTestData(0), - new CharSequenceRowData<>(Tasks.TZ, null))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task2, - new Composite( - new InstanceTestData(0), - new CharSequenceRowData<>(Tasks.TZ, null))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task3, - new Composite( - new InstanceTestData(0), - new CharSequenceRowData<>(Tasks.TZ, null)) - ))); + assertThat( + new Seq<>(new Put<>(taskList1, new NameData("list1")), new Put<>(taskList2, new NameData("list2")), + new Put<>(task1, new TitleData("task1")), new Put<>(task2, new TitleData("task2")), + new Put<>(task3, new TitleData("task3"))), + resultsIn(mClient, new Assert<>(taskList1, new NameData("list1")), + new Assert<>(taskList2, new NameData("list2")), + new Assert<>(task1, new Composite<>(new TitleData("task1"), new VersionData(0))), + new Assert<>(task2, new Composite<>(new TitleData("task2"), new VersionData(0))), + new Assert<>(task3, new Composite<>(new TitleData("task3"), new VersionData(0))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task1, + new Composite(new InstanceTestData(0), + new CharSequenceRowData<>(Tasks.TZ, null))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task2, + new Composite(new InstanceTestData(0), + new CharSequenceRowData<>(Tasks.TZ, null))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task3, + new Composite(new InstanceTestData(0), + new CharSequenceRowData<>(Tasks.TZ, null))))); } - - /** - * Create 2 task list and 3 tasks with updates, check values. - */ + /** Create 2 task list and 3 tasks with updates, check values. */ @Test - public void testMultipleInsertsAndUpdates() - { + public void testMultipleInsertsAndUpdates() { Table taskListsTable = new LocalTaskListsTable(mAuthority); RowSnapshot taskList1 = new VirtualRowSnapshot<>(taskListsTable); RowSnapshot taskList2 = new VirtualRowSnapshot<>(taskListsTable); @@ -262,193 +211,135 @@ public class TaskProviderTest RowSnapshot task2 = new VirtualRowSnapshot<>(new TaskListScoped(taskList1, new TasksTable(mAuthority))); RowSnapshot task3 = new VirtualRowSnapshot<>(new TaskListScoped(taskList2, new TasksTable(mAuthority))); - assertThat(new Seq<>( - new Put<>(taskList1, new NameData("list1")), - new Put<>(taskList2, new NameData("list2")), - new Put<>(task1, new TitleData("task1a")), - new Put<>(task2, new TitleData("task2a")), - new Put<>(task3, new TitleData("task3a")), - // update task 1 and 2 - new Put<>(task1, new TitleData("task1b")), - new Put<>(task2, new TitleData("task2b")), - // update task 1 once more - new Put<>(task1, new TitleData("task1c")) - - ), resultsIn(mClient, - new Assert<>(taskList1, new NameData("list1")), - new Assert<>(taskList2, new NameData("list2")), - new Assert<>(task1, new Composite<>( - new TitleData("task1c"), - new VersionData(2))), - new Assert<>(task2, new Composite<>( - new TitleData("task2b"), - new VersionData(1))), - new Assert<>(task3, new Composite<>( - new TitleData("task3a"), - new VersionData(0))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task1, - new Composite( - new InstanceTestData(0), - new CharSequenceRowData<>(Tasks.TZ, null))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task2, - new Composite( - new InstanceTestData(0), - new CharSequenceRowData<>(Tasks.TZ, null))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task3, - new Composite( - new InstanceTestData(0), - new CharSequenceRowData<>(Tasks.TZ, null)) - ))); + assertThat( + new Seq<>(new Put<>(taskList1, new NameData("list1")), new Put<>(taskList2, new NameData("list2")), + new Put<>(task1, new TitleData("task1a")), new Put<>(task2, new TitleData("task2a")), + new Put<>(task3, new TitleData("task3a")), + // update task 1 and 2 + new Put<>(task1, new TitleData("task1b")), new Put<>(task2, new TitleData("task2b")), + // update task 1 once more + new Put<>(task1, new TitleData("task1c"))), + resultsIn(mClient, new Assert<>(taskList1, new NameData("list1")), + new Assert<>(taskList2, new NameData("list2")), + new Assert<>(task1, new Composite<>(new TitleData("task1c"), new VersionData(2))), + new Assert<>(task2, new Composite<>(new TitleData("task2b"), new VersionData(1))), + new Assert<>(task3, new Composite<>(new TitleData("task3a"), new VersionData(0))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task1, + new Composite(new InstanceTestData(0), + new CharSequenceRowData<>(Tasks.TZ, null))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task2, + new Composite(new InstanceTestData(0), + new CharSequenceRowData<>(Tasks.TZ, null))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task3, + new Composite(new InstanceTestData(0), + new CharSequenceRowData<>(Tasks.TZ, null))))); } - /** - * Create task with start and due, check datetime values including generated duration. + * Create task with start and due, check datetime values including generated + * duration. */ @Test - public void testInsertTaskWithStartAndDue() - { + public void testInsertTaskWithStartAndDue() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); DateTime start = DateTime.now(); DateTime due = start.addDuration(new Duration(1, 1, 0)); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData()), - new Put<>(task, new TimeData<>(start, due)) - - ), resultsIn(mClient, - new Assert<>(task, new Composite<>( - new TimeData<>(start, due), - new VersionData(0))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData( - start.shiftTimeZone(TimeZone.getDefault()), - due.shiftTimeZone(TimeZone.getDefault()), - absent(), - 0), - new CharSequenceRowData<>(Tasks.TZ, "UTC")) - ))); + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData()), + new Put<>(task, new TimeData<>(start, due))), + resultsIn(mClient, new Assert<>(task, new Composite<>(new TimeData<>(start, due), new VersionData(0))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite( + new InstanceTestData(start.shiftTimeZone(TimeZone.getDefault()), + due.shiftTimeZone(TimeZone.getDefault()), absent(), 0), + new CharSequenceRowData<>(Tasks.TZ, "UTC"))))); } - - /** - * Create task with start and due, check datetime values including generated duration. + * Create task with start and due, check datetime values including generated + * duration. */ @Test - public void testInsertTaskWithAlldayStartAndDue() - { + public void testInsertTaskWithAlldayStartAndDue() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); DateTime start = DateTime.now().toAllDay(); DateTime due = start.addDuration(new Duration(1, 2, 0)); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData()), - new Put<>(task, new TimeData<>(start, due)) - - ), resultsIn(mClient, - new Assert<>(task, new Composite<>( - new TimeData<>(start, due), - new VersionData(0))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData( - start, - due, - absent(), - 0), - new CharSequenceRowData<>(Tasks.TZ, "UTC")) - ))); + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData()), + new Put<>(task, new TimeData<>(start, due))), + resultsIn(mClient, new Assert<>(task, new Composite<>(new TimeData<>(start, due), new VersionData(0))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite(new InstanceTestData(start, due, absent(), 0), + new CharSequenceRowData<>(Tasks.TZ, "UTC"))))); } - /** - * Create task with start and due, check datetime and INSTANCE_STATUS values after updating the status. + * Create task with start and due, check datetime and INSTANCE_STATUS values + * after updating the status. */ @Test - public void testInsertTaskWithStartAndDueUpdateStatus() - { + public void testInsertTaskWithStartAndDueUpdateStatus() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); DateTime start = DateTime.now(); DateTime due = start.addDuration(new Duration(1, 1, 0)); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, new TimeData<>(start, due)), + assertThat(new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, new TimeData<>(start, due)), // update the status of the new task - new Put<>(task, new StatusData<>(Tasks.STATUS_COMPLETED)) - ), resultsIn(mClient, - new Assert<>(task, new Composite<>( - new TimeData<>(start, due), - new VersionData(1))), // task has been updated once - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData( - start.shiftTimeZone(TimeZone.getDefault()), - due.shiftTimeZone(TimeZone.getDefault()), - absent(), - -1), - new CharSequenceRowData<>(Tasks.TZ, "UTC")) - ))); + new Put<>(task, new StatusData<>(Tasks.STATUS_COMPLETED))), + resultsIn(mClient, new Assert<>(task, new Composite<>(new TimeData<>(start, due), new VersionData(1))), // task + // has + // been + // updated + // once + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite( + new InstanceTestData(start.shiftTimeZone(TimeZone.getDefault()), + due.shiftTimeZone(TimeZone.getDefault()), absent(), -1), + new CharSequenceRowData<>(Tasks.TZ, "UTC"))))); } - /** - * Create task with start and due, check datetime and INSTANCE_STATUS values after updating the task twice. + * Create task with start and due, check datetime and INSTANCE_STATUS values + * after updating the task twice. */ @Test - public void testInsertTaskWithStartAndDueUpdateTwice() - { + public void testInsertTaskWithStartAndDueUpdateTwice() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); DateTime start = DateTime.now(); DateTime due = start.addDuration(new Duration(1, 1, 0)); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, new TimeData<>(start, due)), + assertThat(new Seq<>(new Put<>(taskList, new EmptyRowData<>()), new Put<>(task, new TimeData<>(start, due)), // update the status of the new task new Put<>(task, new StatusData<>(Tasks.STATUS_COMPLETED)), // update the title of the new task - new Put<>(task, new TitleData("Task Title")) - ), resultsIn(mClient, - new Assert<>(task, new Composite<>( - new TimeData<>(start, due), - new TitleData("Task Title"), - new VersionData(2))), // task has been updated twice - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData( - start.shiftTimeZone(TimeZone.getDefault()), - due.shiftTimeZone(TimeZone.getDefault()), - absent(), - -1), - new CharSequenceRowData<>(Tasks.TZ, "UTC")) - ))); + new Put<>(task, new TitleData("Task Title"))), + resultsIn(mClient, + new Assert<>(task, + new Composite<>(new TimeData<>(start, due), new TitleData("Task Title"), + new VersionData(2))), // task has been updated twice + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite( + new InstanceTestData(start.shiftTimeZone(TimeZone.getDefault()), + due.shiftTimeZone(TimeZone.getDefault()), absent(), -1), + new CharSequenceRowData<>(Tasks.TZ, "UTC"))))); } - /** - * Create task with start and due and update it with new values, check datetime values including generated duration. + * Create task with start and due and update it with new values, check datetime + * values including generated duration. */ @Test - public void testInsertTaskWithStartAndDueMovedForward() - { + public void testInsertTaskWithStartAndDueMovedForward() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -459,33 +350,24 @@ public class TaskProviderTest DateTime startNew = start.addDuration(duration); DateTime dueNew = due.addDuration(duration); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData()), - new Put<>(task, new TimeData<>(start, due)), - new Put<>(task, new TimeData<>(startNew, dueNew)) - ), resultsIn(mClient, - new Assert<>(task, new Composite<>( - new TimeData<>(startNew, dueNew), - new VersionData(1))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData( - startNew.shiftTimeZone(TimeZone.getDefault()), - dueNew.shiftTimeZone(TimeZone.getDefault()), - absent(), - 0), - new CharSequenceRowData<>(Tasks.TZ, "UTC")) - ))); + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData()), + new Put<>(task, new TimeData<>(start, due)), new Put<>(task, new TimeData<>(startNew, dueNew))), + resultsIn(mClient, + new Assert<>(task, new Composite<>(new TimeData<>(startNew, dueNew), new VersionData(1))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite( + new InstanceTestData(startNew.shiftTimeZone(TimeZone.getDefault()), + dueNew.shiftTimeZone(TimeZone.getDefault()), absent(), 0), + new CharSequenceRowData<>(Tasks.TZ, "UTC"))))); } - /** - * Create task with start and due and update it with new values, check datetime values including generated duration. + * Create task with start and due and update it with new values, check datetime + * values including generated duration. */ @Test - public void testInsertTaskWithStartAndDueMovedBackwards() - { + public void testInsertTaskWithStartAndDueMovedBackwards() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -496,66 +378,47 @@ public class TaskProviderTest DateTime startNew = start.addDuration(duration); DateTime dueNew = due.addDuration(duration); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData()), - new Put<>(task, new TimeData<>(start, due)), - new Put<>(task, new TimeData<>(startNew, dueNew)) - ), resultsIn(mClient, - new Assert<>(task, new Composite<>( - new TimeData<>(startNew, dueNew), - new VersionData(1))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData( - startNew.shiftTimeZone(TimeZone.getDefault()), - dueNew.shiftTimeZone(TimeZone.getDefault()), - absent(), - 0), - new CharSequenceRowData<>(Tasks.TZ, "UTC")) - ))); + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData()), + new Put<>(task, new TimeData<>(start, due)), new Put<>(task, new TimeData<>(startNew, dueNew))), + resultsIn(mClient, + new Assert<>(task, new Composite<>(new TimeData<>(startNew, dueNew), new VersionData(1))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite( + new InstanceTestData(startNew.shiftTimeZone(TimeZone.getDefault()), + dueNew.shiftTimeZone(TimeZone.getDefault()), absent(), 0), + new CharSequenceRowData<>(Tasks.TZ, "UTC"))))); } - /** - * Create task without dates and set start and due afterwards, check datetime values including generated duration. + * Create task without dates and set start and due afterwards, check datetime + * values including generated duration. */ @Test - public void testInsertTaskWithStartAndDueAddedAfterwards() - { + public void testInsertTaskWithStartAndDueAddedAfterwards() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); DateTime start = DateTime.now(); DateTime due = start.addDuration(new Duration(1, 1, 0)); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData()), - new Put<>(task, new TitleData("Test")), - new Put<>(task, new TimeData<>(start, due)) - ), resultsIn(mClient, - new Assert<>(task, new Composite<>( - new TimeData<>(start, due), - new VersionData(1))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData( - start.shiftTimeZone(TimeZone.getDefault()), - due.shiftTimeZone(TimeZone.getDefault()), - absent(), - 0), - new CharSequenceRowData<>(Tasks.TZ, "UTC")) - ))); + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData()), new Put<>(task, new TitleData("Test")), + new Put<>(task, new TimeData<>(start, due))), + resultsIn(mClient, new Assert<>(task, new Composite<>(new TimeData<>(start, due), new VersionData(1))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite( + new InstanceTestData(start.shiftTimeZone(TimeZone.getDefault()), + due.shiftTimeZone(TimeZone.getDefault()), absent(), 0), + new CharSequenceRowData<>(Tasks.TZ, "UTC"))))); } - /** - * Create task with start and duration, check datetime values including generated due. + * Create task with start and duration, check datetime values including + * generated due. */ @Test - public void testInsertWithStartAndDuration() - { + public void testInsertWithStartAndDuration() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -563,33 +426,26 @@ public class TaskProviderTest Duration duration = Duration.parse("PT1H"); long durationMillis = duration.toMillis(); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData()), - new Put<>(task, new TimeData<>(start, duration)) - - ), resultsIn(mClient, - new Assert<>(task, new Composite<>( - new TimeData<>(start, duration), - new VersionData(0))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData( - start.shiftTimeZone(TimeZone.getDefault()), - start.shiftTimeZone(TimeZone.getDefault()).addDuration(duration), - absent(), - 0), - new CharSequenceRowData<>(Tasks.TZ, "UTC")) - ))); + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData()), new Put<>(task, + new TimeData<>(start, duration))), + resultsIn(mClient, + new Assert<>(task, new Composite<>(new TimeData<>(start, duration), + new VersionData(0))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite( + new InstanceTestData(start.shiftTimeZone(TimeZone.getDefault()), + start.shiftTimeZone(TimeZone.getDefault()).addDuration(duration), + absent(), 0), + new CharSequenceRowData<>(Tasks.TZ, "UTC"))))); } - /** - * Create task with start and duration, check datetime values including generated due. + * Create task with start and duration, check datetime values including + * generated due. */ @Test - public void testInsertWithStartAndDurationChangeTimeZone() - { + public void testInsertWithStartAndDurationChangeTimeZone() { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); @@ -598,37 +454,28 @@ public class TaskProviderTest long durationMillis = duration.toMillis(); DateTime startNew = start.shiftTimeZone(TimeZone.getTimeZone("America/New_York")); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData()), - new Put<>(task, new TimeData<>(start, duration)), - // update the task with a the same start in a different time zone - new Put<>(task, new TimeData<>(startNew, duration)) - - ), resultsIn(mClient, - new Assert<>(task, new Composite<>( - new TimeData<>(startNew, duration), - new VersionData(1))), - // note that, apart from the time zone, all values stay the same - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData( - start.shiftTimeZone(TimeZone.getDefault()), - start.shiftTimeZone(TimeZone.getDefault()).addDuration(duration), - absent(), - 0), - new CharSequenceRowData<>(Tasks.TZ, "America/New_York")) - ))); + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData()), + new Put<>(task, new TimeData<>(start, duration)), + // update the task with a the same start in a different time zone + new Put<>(task, new TimeData<>(startNew, duration))), + resultsIn(mClient, + new Assert<>(task, new Composite<>(new TimeData<>(startNew, duration), new VersionData(1))), + // note that, apart from the time zone, all values stay the same + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite( + new InstanceTestData(start.shiftTimeZone(TimeZone.getDefault()), + start.shiftTimeZone(TimeZone.getDefault()).addDuration(duration), + absent(), 0), + new CharSequenceRowData<>(Tasks.TZ, "America/New_York"))))); } - /** - * Having a task with start and due. - * Update it with different due, check datetime values correct in Tasks and Instances. + * Having a task with start and due. Update it with different due, check + * datetime values correct in Tasks and Instances. */ @Test - public void testUpdateDue() throws Exception - { + public void testUpdateDue() throws Exception { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); OperationsQueue queue = new BasicOperationsQueue(mClient); @@ -636,128 +483,95 @@ public class TaskProviderTest DateTime start = DateTime.now(); DateTime due = start.addDuration(new Duration(1, 0, 1)); - queue.enqueue(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(task, new TimeData<>(start, due)) - )); + queue.enqueue( + new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(task, new TimeData<>(start, due)))); queue.flush(); DateTime due2 = due.addDuration(new Duration(1, 0, 2)); - assertThat(new SingletonIterable<>( - new Put<>(task, new TimeData<>(start, due2)) - - ), resultsIn(queue, - new Assert<>(task, new Composite<>( - new TimeData<>(start, due2), - new VersionData(1))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite( - new InstanceTestData( - start.shiftTimeZone(TimeZone.getDefault()), - due2.shiftTimeZone(TimeZone.getDefault()), - absent(), - 0), - new CharSequenceRowData<>(Tasks.TZ, "UTC")) - ))); + assertThat(new SingletonIterable<>(new Put<>(task, new TimeData<>(start, due2))), + resultsIn(queue, new Assert<>(task, new Composite<>(new TimeData<>(start, due2), new VersionData(1))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite( + new InstanceTestData(start.shiftTimeZone(TimeZone.getDefault()), + due2.shiftTimeZone(TimeZone.getDefault()), absent(), 0), + new CharSequenceRowData<>(Tasks.TZ, "UTC"))))); } - /** - * Having a single task. - * Delete task, check that it is removed from Tasks and Instances tables. + * Having a single task. Delete task, check that it is removed from Tasks and + * Instances tables. */ @Test - public void testInstanceDelete() throws Exception - { + public void testInstanceDelete() throws Exception { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table taskTable = new TaskListScoped(taskList, new TasksTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(taskTable); OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(task, new TitleData("task1")) - )); + queue.enqueue(new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(task, new TitleData("task1")))); queue.flush(); - assertThat(new SingletonIterable<>( - new Delete<>(task) - - ), resultsIn(queue, - new AssertEmptyTable<>(new TasksTable(mAuthority)), - new AssertEmptyTable<>(new InstanceTable(mAuthority)) - )); + assertThat(new SingletonIterable<>(new Delete<>(task)), + resultsIn(queue, new AssertEmptyTable<>(new TasksTable(mAuthority)), + new AssertEmptyTable<>(new InstanceTable(mAuthority)))); } - /** - * Having a single task. - * Delete the instance of that task, check that it is removed from Tasks and Instances tables. + * Having a single task. Delete the instance of that task, check that it is + * removed from Tasks and Instances tables. */ @Test - public void testDeleteInstance() throws Exception - { + public void testDeleteInstance() throws Exception { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table taskTable = new TaskListScoped(taskList, new TasksTable(mAuthority)); Table instancesTable = new InstanceTable(mAuthority); RowSnapshot task = new VirtualRowSnapshot<>(taskTable); OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq<>( - new Put<>(taskList, new NameData("list1")), - new Put<>(task, new TitleData("task1")) - )); + queue.enqueue(new Seq<>(new Put<>(taskList, new NameData("list1")), new Put<>(task, new TitleData("task1")))); queue.flush(); // check that removing the instance removes task and instance - assertThat(new SingletonIterable<>( - new BulkDelete<>(instancesTable, new ReferringTo<>(Instances.TASK_ID, task)) - - ), resultsIn(queue, - new AssertEmptyTable<>(new TasksTable(mAuthority)), - new AssertEmptyTable<>(new InstanceTable(mAuthority)) - )); + assertThat( + new SingletonIterable<>(new BulkDelete<>(instancesTable, new ReferringTo<>(Instances.TASK_ID, task))), + resultsIn(queue, new AssertEmptyTable<>(new TasksTable(mAuthority)), + new AssertEmptyTable<>(new InstanceTable(mAuthority)))); } - /** * Contract: LIST_ID is required on task creation. + * *

* Create task without LIST_ID, check for IllegalArgumentException. */ @Test(expected = IllegalArgumentException.class) - public void testInsertWithOutListId() throws Exception - { + public void testInsertWithOutListId() throws Exception { RowSnapshot task = new VirtualRowSnapshot<>(new TasksTable(mAuthority)); OperationsQueue queue = new BasicOperationsQueue(mClient); queue.enqueue(new SingletonIterable>(new Put<>(task, new TitleData("task1")))); queue.flush(); } - /** * Contract: LIST_ID has to refer to existing TaskList. + * *

* Create task with a non-exsiting LIST_ID, check for IllegalArgumentException. */ @Test(expected = IllegalArgumentException.class) - public void testInsertWithInvalidTaskListId() - { + public void testInsertWithInvalidTaskListId() { ContentValues values = new ContentValues(); values.put(Tasks.LIST_ID, 5); mResolver.insert(Tasks.getContentUri(mAuthority), values); } - /** - * Contract: Setting ORIGINAL_INSTANCE_SYNC_ID for an exception task, - * provider must fill ORIGINAL_INSTANCE_ID with corresponding original task's _ID. + * Contract: Setting ORIGINAL_INSTANCE_SYNC_ID for an exception task, provider + * must fill ORIGINAL_INSTANCE_ID with corresponding original task's _ID. */ @Test - public void testExceptionalInstance_settingSyncId_shouldUpdateRegularId() throws Exception - { + public void testExceptionalInstance_settingSyncId_shouldUpdateRegularId() throws Exception { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table taskTable = new TaskListScoped(taskList, new TasksTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(taskTable); @@ -765,34 +579,24 @@ public class TaskProviderTest OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new Put<>(taskList, new NameData("list1")), - new Put<>(task, new Composite<>( - new TitleData("task1"), - new SyncIdData("syncId1")) - ) - )); + queue.enqueue(new Seq>(new Put<>(taskList, new NameData("list1")), + new Put<>(task, new Composite<>(new TitleData("task1"), new SyncIdData("syncId1"))))); queue.flush(); - assertThat(new SingletonIterable<>( - new Put<>(exceptionTask, new Composite<>( - new TitleData("task1exception"), - new OriginalInstanceSyncIdData("syncId1", new DateTime(0))) - ) - - ), resultsIn(queue, - new AssertRelated<>(new TasksTable(mAuthority), Tasks.ORIGINAL_INSTANCE_ID, task, new TitleData("task1exception")) - )); + assertThat( + new SingletonIterable<>(new Put<>(exceptionTask, + new Composite<>(new TitleData("task1exception"), + new OriginalInstanceSyncIdData("syncId1", new DateTime(0))))), + resultsIn(queue, new AssertRelated<>(new TasksTable(mAuthority), Tasks.ORIGINAL_INSTANCE_ID, task, + new TitleData("task1exception")))); } - /** - * Contract: Setting ORIGINAL_INSTANCE_ID for an exception task, - * provider must fill ORIGINAL_INSTANCE_SYNC_ID with corresponding original task's _SYNC_ID. + * Contract: Setting ORIGINAL_INSTANCE_ID for an exception task, provider must + * fill ORIGINAL_INSTANCE_SYNC_ID with corresponding original task's _SYNC_ID. */ @Test - public void testExceptionalInstance_settingRegularId_shouldUpdateSyncId() throws Exception - { + public void testExceptionalInstance_settingRegularId_shouldUpdateSyncId() throws Exception { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); Table taskTable = new TaskListScoped(taskList, new TasksTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(taskTable); @@ -800,71 +604,53 @@ public class TaskProviderTest OperationsQueue queue = new BasicOperationsQueue(mClient); - queue.enqueue(new Seq>( - new Put<>(taskList, new NameData("list1")), - new Put<>(task, new Composite<>( - new TitleData("task1"), - new SyncIdData("syncId1"))) - )); + queue.enqueue(new Seq>(new Put<>(taskList, new NameData("list1")), + new Put<>(task, new Composite<>(new TitleData("task1"), new SyncIdData("syncId1"))))); queue.flush(); DateTime now = DateTime.now(); - assertThat(new SingletonIterable<>( - new Put<>(exceptionTask, - new Composite<>( - new TitleData("task1exception"), - new OriginalInstanceData(task, now))) - - ), resultsIn(queue, - new AssertRelated<>(new TasksTable(mAuthority), Tasks.ORIGINAL_INSTANCE_ID, task, - new Composite<>( - new TitleData("task1exception"), - new OriginalInstanceSyncIdData("syncId1", now) - )) - )); + assertThat( + new SingletonIterable<>(new Put<>(exceptionTask, + new Composite<>(new TitleData("task1exception"), new OriginalInstanceData(task, now)))), + resultsIn(queue, + new AssertRelated<>(new TasksTable(mAuthority), Tasks.ORIGINAL_INSTANCE_ID, task, + new Composite<>(new TitleData("task1exception"), + new OriginalInstanceSyncIdData("syncId1", now))))); } - - /** - * Move a non-recurring task to another list. - */ + /** Move a non-recurring task to another list. */ @Test - public void testMoveTaskInstance() throws Exception - { + public void testMoveTaskInstance() throws Exception { RowSnapshot taskListOld = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot taskListNew = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskListOld, new TasksTable(mAuthority))); OperationsQueue queue = new BasicOperationsQueue(mClient); // create two lists and a single task in the first list - queue.enqueue(new Seq<>( - new Put<>(taskListOld, new NameData("list1")), - new Put<>(taskListNew, new NameData("list2")), - new Put<>(task, new TitleData("title")) - )); + queue.enqueue(new Seq<>(new Put<>(taskListOld, new NameData("list1")), + new Put<>(taskListNew, new NameData("list2")), new Put<>(task, new TitleData("title")))); queue.flush(); assertThat(new SingletonIterable<>( // update the sole task instance to the new list - new BulkUpdate<>(new InstanceTable(mAuthority), new Referring<>(Tasks.LIST_ID, taskListNew), new ReferringTo<>(Tasks.LIST_ID, taskListOld)) - ), resultsIn(queue, - // assert the old list is empty - new Counted<>(0, new AssertRelated<>(new InstanceTable(mAuthority), Tasks.LIST_ID, taskListOld)), - new Counted<>(0, new AssertRelated<>(new TasksTable(mAuthority), Tasks.LIST_ID, taskListOld)), - // assert the new list contains a single entry - new Counted<>(1, new AssertRelated<>(new InstanceTable(mAuthority), Tasks.LIST_ID, taskListNew)), - new Counted<>(1, new AssertRelated<>(new TasksTable(mAuthority), Tasks.LIST_ID, taskListNew, new TitleData("title"))) - )); + new BulkUpdate<>(new InstanceTable(mAuthority), new Referring<>(Tasks.LIST_ID, taskListNew), + new ReferringTo<>(Tasks.LIST_ID, taskListOld))), + resultsIn(queue, + // assert the old list is empty + new Counted<>(0, + new AssertRelated<>(new InstanceTable(mAuthority), Tasks.LIST_ID, taskListOld)), + new Counted<>(0, new AssertRelated<>(new TasksTable(mAuthority), Tasks.LIST_ID, taskListOld)), + // assert the new list contains a single entry + new Counted<>(1, + new AssertRelated<>(new InstanceTable(mAuthority), Tasks.LIST_ID, taskListNew)), + new Counted<>(1, new AssertRelated<>(new TasksTable(mAuthority), Tasks.LIST_ID, taskListNew, + new TitleData("title"))))); } - - /** - * Move a non-recurring task to another list. - */ + /** Move a non-recurring task to another list. */ @Test - public void testMoveTaskInstanceAsSyncAdapter() throws Exception - { + public void testMoveTaskInstanceAsSyncAdapter() throws Exception { Table taskListsTable = new Synced<>(testAccount, new TaskListsTable(mAuthority)); Table instancesTable = new Synced<>(testAccount, new InstanceTable(mAuthority)); Table tasksTable = new Synced<>(testAccount, new TasksTable(mAuthority)); @@ -875,71 +661,59 @@ public class TaskProviderTest OperationsQueue queue = new BasicOperationsQueue(mClient); // create two lists and a single task in the first list - queue.enqueue(new Seq<>( - new Put<>(taskListOld, new NameData("list1")), - new Put<>(taskListNew, new NameData("list2")), - new Put<>(task, new Composite<>( - new SyncIdData("syncid"), // give it a sync id, so it counts as synced + queue.enqueue(new Seq<>(new Put<>(taskListOld, new NameData("list1")), + new Put<>(taskListNew, new NameData("list2")), new Put<>(task, new Composite<>(new SyncIdData("syncid"), // give + // it + // a + // sync + // id, + // so + // it + // counts + // as + // synced new TitleData("title"))))); queue.flush(); assertThat(new SingletonIterable<>( // update the sole task instance to the new list - new BulkUpdate<>(new InstanceTable(mAuthority), new Referring<>(Tasks.LIST_ID, taskListNew), new ReferringTo<>(Tasks.LIST_ID, taskListOld)) - ), resultsIn(queue, - // assert the old list contains a deleted entry for the task - new Counted<>(0, - new AssertRelated<>( - instancesTable, - Tasks.LIST_ID, - taskListOld)), - new Counted<>(1, - new AssertRelated<>( - tasksTable, - Tasks.LIST_ID, - taskListOld, - new Composite<>( - new TitleData("title"), - new CharSequenceRowData<>(Tasks._DELETED, "1")))), - // assert the new list contains a single entry - new Counted<>(1, new AssertRelated<>(instancesTable, Tasks.LIST_ID, taskListNew)), - new Counted<>(1, new AssertRelated<>(tasksTable, Tasks.LIST_ID, taskListNew, new TitleData("title"))) - )); + new BulkUpdate<>(new InstanceTable(mAuthority), new Referring<>(Tasks.LIST_ID, taskListNew), + new ReferringTo<>(Tasks.LIST_ID, taskListOld))), + resultsIn(queue, + // assert the old list contains a deleted entry for the task + new Counted<>(0, new AssertRelated<>(instancesTable, Tasks.LIST_ID, taskListOld)), + new Counted<>(1, + new AssertRelated<>(tasksTable, Tasks.LIST_ID, taskListOld, + new Composite<>(new TitleData("title"), + new CharSequenceRowData<>(Tasks._DELETED, "1")))), + // assert the new list contains a single entry + new Counted<>(1, new AssertRelated<>(instancesTable, Tasks.LIST_ID, taskListNew)), + new Counted<>(1, + new AssertRelated<>(tasksTable, Tasks.LIST_ID, taskListNew, new TitleData("title"))))); } - /** - * Create task with start and due, check datetime values including generated duration. + * Create task with start and due, check datetime values including generated + * duration. */ @Test - public void testInsertTaskWithoutStartAndDueButRRULE() throws InvalidRecurrenceRuleException - { + public void testInsertTaskWithoutStartAndDueButRRULE() throws InvalidRecurrenceRuleException { RowSnapshot taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority)); RowSnapshot task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority))); DateTime start = DateTime.now(); DateTime due = start.addDuration(new Duration(1, 1, 0)); - assertThat(new Seq<>( - new Put<>(taskList, new EmptyRowData<>()), - new Put<>(task, new Composite<>( - new TitleData("test"), - new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", RecurrenceRule.RfcMode.RFC2445_LAX))))), - resultsIn(mClient, - new Assert<>(task, new Composite<>( - new TitleData("test"), - new VersionData(0))), - new AssertRelated<>( - new InstanceTable(mAuthority), Instances.TASK_ID, task, - new Composite<>( - new CharSequenceRowData<>(Tasks.TITLE, "test"), - new InstanceTestData( - absent(), - absent(), - absent(), - 0), - new CharSequenceRowData<>(Tasks.TZ, null)) - ))); + assertThat( + new Seq<>(new Put<>(taskList, new EmptyRowData<>()), + new Put<>(task, + new Composite<>(new TitleData("test"), + new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;COUNT=5", + RecurrenceRule.RfcMode.RFC2445_LAX))))), + resultsIn(mClient, new Assert<>(task, new Composite<>(new TitleData("test"), new VersionData(0))), + new AssertRelated<>(new InstanceTable(mAuthority), Instances.TASK_ID, task, + new Composite<>(new CharSequenceRowData<>(Tasks.TITLE, "test"), + new InstanceTestData(absent(), absent(), absent(), 0), + new CharSequenceRowData<>(Tasks.TZ, null))))); } - } diff --git a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/matchers/NotifiesMatcher.java b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/matchers/NotifiesMatcher.java index 39014d6c94d9334ae1e114c0c9df9363c183550d..f06a04a3229a6a416a0b9303f878a909df5168ad 100644 --- a/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/matchers/NotifiesMatcher.java +++ b/opentasks-provider/src/androidTest/java/org/dmfs/provider/tasks/matchers/NotifiesMatcher.java @@ -21,57 +21,46 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; import android.os.HandlerThread; - +import androidx.annotation.NonNull; +import androidx.test.platform.app.InstrumentationRegistry; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.OperationsQueue; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeDiagnosingMatcher; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; - -import androidx.annotation.NonNull; -import androidx.test.platform.app.InstrumentationRegistry; - - /** * @author Marten Gajda */ -public final class NotifiesMatcher extends TypeSafeDiagnosingMatcher>> -{ +public final class NotifiesMatcher extends TypeSafeDiagnosingMatcher>> { private final Uri mUri; private final OperationsQueue mOperationsQueue; private final Matcher> mDelegate; - - public static Matcher>> notifies(@NonNull Uri uri, @NonNull OperationsQueue operationsQueue, @NonNull Matcher> delegate) - { + public static Matcher>> notifies(@NonNull Uri uri, + @NonNull OperationsQueue operationsQueue, @NonNull Matcher> delegate) { return new NotifiesMatcher(uri, operationsQueue, delegate); } - - public NotifiesMatcher(Uri uri, @NonNull OperationsQueue operationsQueue, @NonNull Matcher> delegate) - { + public NotifiesMatcher(Uri uri, @NonNull OperationsQueue operationsQueue, + @NonNull Matcher> delegate) { mUri = uri; mOperationsQueue = operationsQueue; mDelegate = delegate; } - @Override - protected boolean matchesSafely(Iterable> item, Description mismatchDescription) - { + protected boolean matchesSafely(Iterable> item, Description mismatchDescription) { Collection notifications = Collections.synchronizedCollection(new HashSet<>()); HandlerThread handlerThread = new HandlerThread("ObserverHandlerThread"); handlerThread.start(); - ContentObserver observer = new ContentObserver(new Handler(handlerThread.getLooper())) - { + ContentObserver observer = new ContentObserver(new Handler(handlerThread.getLooper())) { @Override - public void onChange(boolean selfChange, Uri uri) - { + public void onChange(boolean selfChange, Uri uri) { super.onChange(selfChange, uri); System.out.println("Notifcation: " + uri); notifications.add(uri); @@ -80,43 +69,32 @@ public final class NotifiesMatcher extends TypeSafeDiagnosingMatcher scheme(String scheme) - { +public final class UriMatcher { + public static Matcher scheme(String scheme) { return having(Uri::getScheme, is(scheme)); } - - public static Matcher authority(String authority) - { + public static Matcher authority(String authority) { return having(Uri::getEncodedAuthority, is(authority)); } - - public static Matcher path(Matcher patchMatcher) - { + public static Matcher path(Matcher patchMatcher) { return having(Uri::getEncodedPath, patchMatcher); } - } diff --git a/opentasks-provider/src/androidTest/res/values/opentasks_defaults.xml b/opentasks-provider/src/androidTest/res/values/opentasks_defaults.xml index d3b53833219a4e00c3200a1d1eeacb61dfcff4e4..27014a71ac030a2af2cc000c84e9975e86141dd6 100644 --- a/opentasks-provider/src/androidTest/res/values/opentasks_defaults.xml +++ b/opentasks-provider/src/androidTest/res/values/opentasks_defaults.xml @@ -2,8 +2,7 @@ - org.dmfs.tasks.test + org.dmfs.tasks.test - \ No newline at end of file + diff --git a/opentasks-provider/src/main/AndroidManifest.xml b/opentasks-provider/src/main/AndroidManifest.xml index 50a26647635a2dfd2e115ff4c7ef2d5a5108e7de..4043e13b94bec245857347442335e8b2759a1027 100644 --- a/opentasks-provider/src/main/AndroidManifest.xml +++ b/opentasks-provider/src/main/AndroidManifest.xml @@ -1,47 +1,50 @@ - + + android:name="foundation.e.tasks.permissiongroup.Tasks" + android:description="@string/opentasks_permission_group_description_tasks" + android:icon="@drawable/ic_24_opentasks" + android:label="@string/opentasks_provider_label" /> + android:name="foundation.e.permission.READ_TASKS" + android:description="@string/opentasks_permission_description_read_tasks" + android:label="@string/opentasks_permission_read_tasks" + android:permissionGroup="foundation.e.tasks.permissiongroup.Tasks" + android:protectionLevel="dangerous" /> + android:name="foundation.e.permission.WRITE_TASKS" + android:description="@string/opentasks_permission_description_write_tasks" + android:label="@string/opentasks_permission_write_tasks" + android:permissionGroup="foundation.e.tasks.permissiongroup.Tasks" + android:protectionLevel="dangerous" /> - + - - + + - + + android:name="org.dmfs.provider.tasks.TaskProviderBroadcastReceiver" + android:exported="true"> - + diff --git a/opentasks-provider/src/main/java/org/dmfs/ngrams/NGramGenerator.java b/opentasks-provider/src/main/java/org/dmfs/ngrams/NGramGenerator.java index 58e306480a644655e92b4ad842d3faae4ebb59f6..a92b90fe076754943a5972a0405bf6871a5ea452 100644 --- a/opentasks-provider/src/main/java/org/dmfs/ngrams/NGramGenerator.java +++ b/opentasks-provider/src/main/java/org/dmfs/ngrams/NGramGenerator.java @@ -22,23 +22,20 @@ import java.util.Locale; import java.util.Set; import java.util.regex.Pattern; - /** * Generator for N-grams from a given String. * * @author Marten Gajda */ -public final class NGramGenerator -{ +public final class NGramGenerator { /** - * A {@link Pattern} that matches anything that doesn't belong to a word or number. + * A {@link Pattern} that matches anything that doesn't belong to a word or + * number. */ - private final static Pattern SEPARATOR_PATTERN = Pattern.compile("[^\\p{L}\\p{M}\\d]+"); + private static final Pattern SEPARATOR_PATTERN = Pattern.compile("[^\\p{L}\\p{M}\\d]+"); - /** - * A {@link Pattern} that matches anything that doesn't belong to a word. - */ - private final static Pattern SEPARATOR_PATTERN_NO_NUMBERS = Pattern.compile("[^\\p{L}\\p{M}]+"); + /** A {@link Pattern} that matches anything that doesn't belong to a word. */ + private static final Pattern SEPARATOR_PATTERN_NO_NUMBERS = Pattern.compile("[^\\p{L}\\p{M}]+"); private final int mN; private final int mMinWordLen; @@ -47,83 +44,68 @@ public final class NGramGenerator private boolean mAddSpaceInFront = false; private Locale mLocale = Locale.getDefault(); - - public NGramGenerator(int n) - { + public NGramGenerator(int n) { this(n, 1); } - - public NGramGenerator(int n, int minWordLen) - { + public NGramGenerator(int n, int minWordLen) { mN = n; mMinWordLen = minWordLen; } - /** * Set whether to convert all words to lower-case first. * * @param lowercase - * true to convert the test to lower case first. - * + * true to convert the test to lower case first. * @return This instance. */ - public NGramGenerator setAllLowercase(boolean lowercase) - { + public NGramGenerator setAllLowercase(boolean lowercase) { mAllLowercase = lowercase; return this; } - /** - * Set whether to index the beginning of a word with a space in front. This slightly raises the weight of word beginnings when searching. + * Set whether to index the beginning of a word with a space in front. This + * slightly raises the weight of word beginnings when searching. * * @param addSpace - * true to add a space in front of each word, false otherwise. - * + * true to add a space in front of each word, + * false otherwise. * @return This instance. */ - public NGramGenerator setAddSpaceInFront(boolean addSpace) - { + public NGramGenerator setAddSpaceInFront(boolean addSpace) { mAddSpaceInFront = addSpace; return this; } - /** - * Sets the {@link Locale} to use when converting the input string to lower case. This has no effect when {@link #setAllLowercase(boolean)} is called with - * false. + * Sets the {@link Locale} to use when converting the input string to lower + * case. This has no effect when {@link #setAllLowercase(boolean)} is called + * with false. * * @param locale - * The {@link Locale} to user for the conversion to lower case. - * + * The {@link Locale} to user for the conversion to lower case. * @return This instance. */ - public NGramGenerator setLocale(Locale locale) - { + public NGramGenerator setLocale(Locale locale) { mLocale = locale; return this; } - /** * Get all N-grams contained in the given String. * * @param data - * The String to analyze. - * + * The String to analyze. * @return The {@link Set} containing the N-grams. */ - public Set getNgrams(String data) - { - if (data == null) - { + public Set getNgrams(String data) { + if (data == null) { return Collections.emptySet(); } - if (mAllLowercase) - { + if (mAllLowercase) { data = data.toLowerCase(mLocale); } @@ -131,34 +113,28 @@ public final class NGramGenerator Set set = new HashSet(128); - for (String word : words) - { + for (String word : words) { getNgrams(word, set); } return set; } - - private void getNgrams(String word, Set ngrams) - { + private void getNgrams(String word, Set ngrams) { final int len = word.length(); - if (len < mMinWordLen) - { + if (len < mMinWordLen) { return; } final int n = mN; final int last = Math.max(1, len - n + 1); - for (int i = 0; i < last; ++i) - { + for (int i = 0; i < last; ++i) { ngrams.add(word.substring(i, Math.min(i + n, len))); } - if (mAddSpaceInFront) - { + if (mAddSpaceInFront) { /* * Add another String with a space and the first n-1 characters of the word. */ diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/AuthorityUtil.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/AuthorityUtil.java index 81182b49178b09a9d0e55a506e23ddd33d881bfd..7a4bdaba65d4528e6226192d0728215fae72645c 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/AuthorityUtil.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/AuthorityUtil.java @@ -17,25 +17,21 @@ package org.dmfs.provider.tasks; import android.content.Context; - import org.dmfs.tasks.provider.R; - /** * Access for the authority name of the tasks content provider. * * @author Gabor Keszthelyi */ -// TODO Figure out better design or at least rename to TaskAuthority.get(context) (results in changes in many files) -public final class AuthorityUtil -{ +// TODO Figure out better design or at least rename to +// TaskAuthority.get(context) (results in +// changes in many files) +public final class AuthorityUtil { private static String sCachedValue; - - public static String taskAuthority(Context context) - { - if (sCachedValue == null) - { + public static String taskAuthority(Context context) { + if (sCachedValue == null) { sCachedValue = context.getString(R.string.opentasks_authority); } return sCachedValue; diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ContentOperation.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ContentOperation.java index 622533c4dc77b7a25cbb8f2d56743e6fd3a335f7..afabf5553b54c64a59be7a1812ac69623d33679d 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ContentOperation.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ContentOperation.java @@ -28,7 +28,7 @@ import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.os.Handler; import android.util.Log; - +import java.util.TimeZone; import org.dmfs.provider.tasks.model.CursorContentValuesInstanceAdapter; import org.dmfs.provider.tasks.model.CursorContentValuesTaskAdapter; import org.dmfs.provider.tasks.model.InstanceAdapter; @@ -39,32 +39,30 @@ import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Instances; import org.dmfs.tasks.contract.TaskContract.Tasks; -import java.util.TimeZone; - - -public enum ContentOperation -{ +public enum ContentOperation { /** - * When the local timezone has been changed we need to update the due and start sorting values. This handler will take care of running the appropriate + * When the local timezone has been changed we need to update the due and start + * sorting values. This handler will take care of running the appropriate * update. In addition it fires an operation to update all notifications. */ - UPDATE_TIMEZONE(new OperationHandler() - { + UPDATE_TIMEZONE(new OperationHandler() { @Override - public void handleOperation(Context context, Uri uri, SQLiteDatabase db, ContentValues values) - { + public void handleOperation(Context context, Uri uri, SQLiteDatabase db, ContentValues values) { long start = System.currentTimeMillis(); // request an update of all instance values ContentValues vals = new ContentValues(1); Instantiating.addUpdateRequest(vals); - // execute update that triggers a recalculation of all due and start sorting values - int count = context.getContentResolver().update( - TaskContract.Tasks.getContentUri(uri.getAuthority()).buildUpon().appendQueryParameter(TaskContract.CALLER_IS_SYNCADAPTER, "true").build(), - vals, null, null); + // execute update that triggers a recalculation of all due and start sorting + // values + int count = context.getContentResolver() + .update(TaskContract.Tasks.getContentUri(uri.getAuthority()).buildUpon() + .appendQueryParameter(TaskContract.CALLER_IS_SYNCADAPTER, "true").build(), vals, null, + null); - Log.i("TaskProvider", "time to update " + count + " tasks: " + (System.currentTimeMillis() - start) + " ms"); + Log.i("TaskProvider", + "time to update " + count + " tasks: " + (System.currentTimeMillis() - start) + " ms"); // now update alarms as well UPDATE_NOTIFICATION_ALARM.fire(context, null); @@ -74,12 +72,10 @@ public enum ContentOperation /** * Takes care of everything we need to send task start and task due broadcasts. */ - POST_NOTIFICATIONS(new OperationHandler() - { + POST_NOTIFICATIONS(new OperationHandler() { @Override - public void handleOperation(Context context, Uri uri, SQLiteDatabase db, ContentValues values) - { + public void handleOperation(Context context, Uri uri, SQLiteDatabase db, ContentValues values) { TimeZone localTimeZone = TimeZone.getDefault(); // the date-time of when the last notification was shown @@ -90,46 +86,46 @@ public enum ContentOperation String lastAlarmString = Long.toString(lastAlarm.getInstance()); String nowString = Long.toString(now.getInstance()); - // load all tasks that have started or became due since the last time we've shown a notification. - Cursor instancesCursor = db.query(TaskDatabaseHelper.Tables.INSTANCE_VIEW, null, "((" + TaskContract.Instances.INSTANCE_DUE_SORTING + ">? and " - + TaskContract.Instances.INSTANCE_DUE_SORTING + "<=?) or (" + TaskContract.Instances.INSTANCE_START_SORTING + ">? and " - + TaskContract.Instances.INSTANCE_START_SORTING + "<=?)) and " + Instances.IS_CLOSED + " = 0 and " + Tasks._DELETED + "=0", new String[] { - lastAlarmString, nowString, lastAlarmString, nowString }, null, null, null); - - try - { - while (instancesCursor.moveToNext()) - { - InstanceAdapter task = new CursorContentValuesInstanceAdapter(InstanceAdapter._ID.getFrom(instancesCursor), instancesCursor, null); + // load all tasks that have started or became due since the last time we've + // shown a + // notification. + Cursor instancesCursor = db.query(TaskDatabaseHelper.Tables.INSTANCE_VIEW, null, + "((" + TaskContract.Instances.INSTANCE_DUE_SORTING + ">? and " + + TaskContract.Instances.INSTANCE_DUE_SORTING + "<=?) or (" + + TaskContract.Instances.INSTANCE_START_SORTING + ">? and " + + TaskContract.Instances.INSTANCE_START_SORTING + "<=?)) and " + Instances.IS_CLOSED + + " = 0 and " + Tasks._DELETED + "=0", + new String[]{lastAlarmString, nowString, lastAlarmString, nowString}, null, null, null); + + try { + while (instancesCursor.moveToNext()) { + InstanceAdapter task = new CursorContentValuesInstanceAdapter( + InstanceAdapter._ID.getFrom(instancesCursor), instancesCursor, null); DateTime instanceDue = task.valueOf(InstanceAdapter.INSTANCE_DUE); - if (instanceDue != null && !instanceDue.isFloating()) - { + if (instanceDue != null && !instanceDue.isFloating()) { // make sure we compare instances in local time instanceDue = instanceDue.shiftTimeZone(localTimeZone); } DateTime instanceStart = task.valueOf(InstanceAdapter.INSTANCE_START); - if (instanceStart != null && !instanceStart.isFloating()) - { + if (instanceStart != null && !instanceStart.isFloating()) { // make sure we compare instances in local time instanceStart = instanceStart.shiftTimeZone(localTimeZone); } - if (instanceDue != null && lastAlarm.getInstance() < instanceDue.getInstance() && instanceDue.getInstance() <= now.getInstance()) - { + if (instanceDue != null && lastAlarm.getInstance() < instanceDue.getInstance() + && instanceDue.getInstance() <= now.getInstance()) { // this task became due since the last alarm, send a due broadcast sendBroadcast(context, TaskContract.ACTION_BROADCAST_TASK_DUE, task.uri(uri.getAuthority())); - } - else if (instanceStart != null && lastAlarm.getInstance() < instanceStart.getInstance() && instanceStart.getInstance() <= now.getInstance()) - { + } else if (instanceStart != null && lastAlarm.getInstance() < instanceStart.getInstance() + && instanceStart.getInstance() <= now.getInstance()) { // this task has started since the last alarm, send a start broadcast - sendBroadcast(context, TaskContract.ACTION_BROADCAST_TASK_STARTING, task.uri(uri.getAuthority())); + sendBroadcast(context, TaskContract.ACTION_BROADCAST_TASK_STARTING, + task.uri(uri.getAuthority())); } } - } - finally - { + } finally { instancesCursor.close(); } @@ -140,36 +136,32 @@ public enum ContentOperation UPDATE_NOTIFICATION_ALARM.fire(context, null); } - @SuppressLint("NewApi") - private void saveLastAlarmTime(Context context, DateTime time) - { + private void saveLastAlarmTime(Context context, DateTime time) { SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); Editor editor = prefs.edit(); editor.putLong(PREFS_KEY_LAST_ALARM_TIMESTAMP, time.getTimestamp()); editor.apply(); } - - private DateTime getLastAlarmTimestamp(Context context) - { + private DateTime getLastAlarmTimestamp(Context context) { SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - return new DateTime(TimeZone.getDefault(), prefs.getLong(PREFS_KEY_LAST_ALARM_TIMESTAMP, System.currentTimeMillis())); + return new DateTime(TimeZone.getDefault(), + prefs.getLong(PREFS_KEY_LAST_ALARM_TIMESTAMP, System.currentTimeMillis())); } - /** - * Sends a notification broadcast for a task instance that has started or became due. + * Sends a notification broadcast for a task instance that has started or became + * due. * * @param context - * A {@link Context}. + * A {@link Context}. * @param action - * The broadcast action. + * The broadcast action. * @param uri - * The task uri. + * The task uri. */ - private void sendBroadcast(Context context, String action, Uri uri) - { + private void sendBroadcast(Context context, String action, Uri uri) { Intent intent = new Intent(action); intent.setData(uri); // only notify our own package @@ -179,20 +171,18 @@ public enum ContentOperation }), /** - * Determines the date-time of when the next task becomes due or starts (whatever happens first) and sets an alarm to trigger a notification. + * Determines the date-time of when the next task becomes due or starts + * (whatever happens first) and sets an alarm to trigger a notification. */ - UPDATE_NOTIFICATION_ALARM(new OperationHandler() - { + UPDATE_NOTIFICATION_ALARM(new OperationHandler() { @Override - public void handleOperation(Context context, Uri uri, SQLiteDatabase db, ContentValues values) - { + public void handleOperation(Context context, Uri uri, SQLiteDatabase db, ContentValues values) { TimeZone localTimeZone = TimeZone.getDefault(); DateTime lastAlarm = getLastAlarmTimestamp(context); DateTime now = DateTime.nowAndHere(); - if (now.before(lastAlarm)) - { + if (now.before(lastAlarm)) { // time went backwards, set last alarm time to now lastAlarm = now; saveLastAlarmTime(context, now); @@ -203,217 +193,180 @@ public enum ContentOperation DateTime nextAlarm = null; // find the next task that starts - Cursor nextInstanceStartCursor = db.query(TaskDatabaseHelper.Tables.INSTANCE_VIEW, null, TaskContract.Instances.INSTANCE_START_SORTING + ">? and " - + Instances.IS_CLOSED + " = 0 and " + Tasks._DELETED + "=0", new String[] { lastAlarmString }, null, null, - TaskContract.Instances.INSTANCE_START_SORTING, "1"); - - try - { - if (nextInstanceStartCursor.moveToNext()) - { - TaskAdapter task = new CursorContentValuesTaskAdapter(TaskAdapter.INSTANCE_TASK_ID.getFrom(nextInstanceStartCursor), - nextInstanceStartCursor, null); + Cursor nextInstanceStartCursor = db.query(TaskDatabaseHelper.Tables.INSTANCE_VIEW, null, + TaskContract.Instances.INSTANCE_START_SORTING + ">? and " + Instances.IS_CLOSED + " = 0 and " + + Tasks._DELETED + "=0", + new String[]{lastAlarmString}, null, null, TaskContract.Instances.INSTANCE_START_SORTING, "1"); + + try { + if (nextInstanceStartCursor.moveToNext()) { + TaskAdapter task = new CursorContentValuesTaskAdapter( + TaskAdapter.INSTANCE_TASK_ID.getFrom(nextInstanceStartCursor), nextInstanceStartCursor, + null); nextAlarm = task.valueOf(TaskAdapter.INSTANCE_START); - if (!nextAlarm.isFloating()) - { + if (!nextAlarm.isFloating()) { nextAlarm = nextAlarm.shiftTimeZone(localTimeZone); } } - } - finally - { + } finally { nextInstanceStartCursor.close(); } // find the next task that's due - Cursor nextInstanceDueCursor = db.query(TaskDatabaseHelper.Tables.INSTANCE_VIEW, null, TaskContract.Instances.INSTANCE_DUE_SORTING + ">? and " - + Instances.IS_CLOSED + " = 0 and " + Tasks._DELETED + "=0", new String[] { lastAlarmString }, null, null, - TaskContract.Instances.INSTANCE_DUE_SORTING, "1"); - - try - { - if (nextInstanceDueCursor.moveToNext()) - { - TaskAdapter task = new CursorContentValuesTaskAdapter(TaskAdapter.INSTANCE_TASK_ID.getFrom(nextInstanceDueCursor), nextInstanceDueCursor, - null); + Cursor nextInstanceDueCursor = db.query(TaskDatabaseHelper.Tables.INSTANCE_VIEW, null, + TaskContract.Instances.INSTANCE_DUE_SORTING + ">? and " + Instances.IS_CLOSED + " = 0 and " + + Tasks._DELETED + "=0", + new String[]{lastAlarmString}, null, null, TaskContract.Instances.INSTANCE_DUE_SORTING, "1"); + + try { + if (nextInstanceDueCursor.moveToNext()) { + TaskAdapter task = new CursorContentValuesTaskAdapter( + TaskAdapter.INSTANCE_TASK_ID.getFrom(nextInstanceDueCursor), nextInstanceDueCursor, null); DateTime nextDue = task.valueOf(TaskAdapter.INSTANCE_DUE); - if (!nextDue.isFloating()) - { + if (!nextDue.isFloating()) { nextDue = nextDue.shiftTimeZone(localTimeZone); } - if (nextAlarm == null || nextAlarm.getInstance() > nextDue.getInstance()) - { + if (nextAlarm == null || nextAlarm.getInstance() > nextDue.getInstance()) { nextAlarm = nextDue; } } - } - finally - { + } finally { nextInstanceDueCursor.close(); } - if (nextAlarm != null) - { + if (nextAlarm != null) { TaskProviderBroadcastReceiver.planNotificationUpdate(context, nextAlarm); - } - else - { + } else { saveLastAlarmTime(context, now); } } - @SuppressLint("NewApi") - private void saveLastAlarmTime(Context context, DateTime time) - { + private void saveLastAlarmTime(Context context, DateTime time) { SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); Editor editor = prefs.edit(); editor.putLong(PREFS_KEY_LAST_ALARM_TIMESTAMP, time.getTimestamp()); editor.apply(); } - - private DateTime getLastAlarmTimestamp(Context context) - { + private DateTime getLastAlarmTimestamp(Context context) { SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - return new DateTime(TimeZone.getDefault(), prefs.getLong(PREFS_KEY_LAST_ALARM_TIMESTAMP, System.currentTimeMillis())); + return new DateTime(TimeZone.getDefault(), + prefs.getLong(PREFS_KEY_LAST_ALARM_TIMESTAMP, System.currentTimeMillis())); } - }); /** - * A lock object to serialize the execution of all incoming {@link ContentOperation}. + * A lock object to serialize the execution of all incoming + * {@link ContentOperation}. */ - private final static Object mLock = new Object(); + private static final Object mLock = new Object(); - /** - * The base path of the Uri to trigger content operations. - */ - private final static String BASE_PATH = "content_operation"; + /** The base path of the Uri to trigger content operations. */ + private static final String BASE_PATH = "content_operation"; - /** - * The {@link OperationHandler} that handles this {@link ContentOperation}. - */ + /** The {@link OperationHandler} that handles this {@link ContentOperation}. */ private final OperationHandler mHandler; private static final String PREFS_NAME = "org.dmfs.provider.tasks"; private static final String PREFS_KEY_LAST_ALARM_TIMESTAMP = "org.dmfs.provider.tasks.prefs.LAST_ALARM_TIMESTAMP"; - - ContentOperation(OperationHandler handler) - { + ContentOperation(OperationHandler handler) { mHandler = handler; } - /** * Execute this {@link ContentOperation} with the given values. * * @param context - * A {@link Context}. + * A {@link Context}. * @param values - * Optional {@link ContentValues}, may be null. + * Optional {@link ContentValues}, may be null. */ - public void fire(Context context, ContentValues values) - { - context.getContentResolver().update(uri(AuthorityUtil.taskAuthority(context)), values == null ? new ContentValues() : values, null, null); + public void fire(Context context, ContentValues values) { + context.getContentResolver().update(uri(AuthorityUtil.taskAuthority(context)), + values == null ? new ContentValues() : values, null, null); } - /** * Run the operation on the given handler. * * @param context - * A {@link Context}. + * A {@link Context}. * @param handler - * A {@link Handler} to run the operation on. + * A {@link Handler} to run the operation on. * @param uri - * The {@link Uri} that triggered this operation. + * The {@link Uri} that triggered this operation. * @param db - * The database. + * The database. * @param values - * The {@link ContentValues} that were supplied. + * The {@link ContentValues} that were supplied. */ - void run(final Context context, Handler handler, final Uri uri, final SQLiteDatabase db, final ContentValues values) - { - handler.post(new Runnable() - { + void run(final Context context, Handler handler, final Uri uri, final SQLiteDatabase db, + final ContentValues values) { + handler.post(new Runnable() { @Override - public void run() - { - synchronized (mLock) - { + public void run() { + synchronized (mLock) { mHandler.handleOperation(context, uri, db, values); } } }); } - /** * Returns the {@link Uri} that triggers this {@link ContentOperation}. * * @param authority - * The authority of this provide. - * + * The authority of this provide. * @return A {@link Uri}. */ - private Uri uri(String authority) - { - return new Uri.Builder().scheme("content").authority(authority).path(BASE_PATH).appendPath(this.toString()).build(); + private Uri uri(String authority) { + return new Uri.Builder().scheme("content").authority(authority).path(BASE_PATH).appendPath(this.toString()) + .build(); } - /** * Register the operations with the given {@link UriMatcher}. * * @param uriMatcher - * The {@link UriMatcher}. + * The {@link UriMatcher}. * @param authority - * The authority of this TaskProvider. + * The authority of this TaskProvider. * @param firstID - * Teh first Id to use for our Uris. + * Teh first Id to use for our Uris. */ - public static void register(UriMatcher uriMatcher, String authority, int firstID) - { - for (ContentOperation op : values()) - { + public static void register(UriMatcher uriMatcher, String authority, int firstID) { + for (ContentOperation op : values()) { Uri uri = op.uri(authority); uriMatcher.addURI(authority, uri.getPath().substring(1) /* remove leading slash */, firstID + op.ordinal()); } } - /** * Return a {@link ContentOperation} that belongs to the given id. * * @param id - * The id or the {@link ContentOperation}. + * The id or the {@link ContentOperation}. * @param firstId - * The first ID to use for Uris. - * - * @return The respective {@link ContentOperation} or null if none was found. + * The first ID to use for Uris. + * @return The respective {@link ContentOperation} or null if none + * was found. */ - public static ContentOperation get(int id, int firstId) - { - if (id < firstId) - { + public static ContentOperation get(int id, int firstId) { + if (id < firstId) { return null; } - if (id - firstId >= values().length) - { + if (id - firstId >= values().length) { return null; } return values()[id - firstId]; } - - public interface OperationHandler - { + public interface OperationHandler { void handleOperation(Context context, Uri uri, SQLiteDatabase db, ContentValues values); } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/FTSDatabaseHelper.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/FTSDatabaseHelper.java index 1093a4f549280340bfdf1f5747f3058e6acb4d5c..8d736a89e36a278d3db4cf46c413395310abb122 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/FTSDatabaseHelper.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/FTSDatabaseHelper.java @@ -20,7 +20,11 @@ import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.text.TextUtils; - +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import org.dmfs.jems.iterable.decorators.Chunked; import org.dmfs.ngrams.NGramGenerator; import org.dmfs.provider.tasks.TaskDatabaseHelper.Tables; @@ -30,194 +34,156 @@ import org.dmfs.tasks.contract.TaskContract.Properties; import org.dmfs.tasks.contract.TaskContract.TaskColumns; import org.dmfs.tasks.contract.TaskContract.Tasks; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - - /** * Supports the {@link TaskDatabaseHelper} in the matter of full-text-search. * * @author Tobias Reinsch * @author Marten Gajda */ -public class FTSDatabaseHelper -{ +public class FTSDatabaseHelper { /** - * We search the ngram table in chunks of 500. This should be good enough for an average task but still well below - * the SQLITE expression length limit and the variable count limit. + * We search the ngram table in chunks of 500. This should be good enough for an + * average task but still well below the SQLITE expression length limit and the + * variable count limit. */ - private final static int NGRAM_SEARCH_CHUNK_SIZE = 500; + private static final int NGRAM_SEARCH_CHUNK_SIZE = 500; - private final static float SEARCH_RESULTS_MIN_SCORE = 0.33f; + private static final float SEARCH_RESULTS_MIN_SCORE = 0.33f; - /** - * A Generator for 3-grams. - */ - private final static NGramGenerator TRIGRAM_GENERATOR = new NGramGenerator(3, 1).setAddSpaceInFront(true); + /** A Generator for 3-grams. */ + private static final NGramGenerator TRIGRAM_GENERATOR = new NGramGenerator(3, 1).setAddSpaceInFront(true); - /** - * A Generator for 4-grams. - */ - private final static NGramGenerator TETRAGRAM_GENERATOR = new NGramGenerator(4, 3 /* shorter words are fully covered by trigrams */).setAddSpaceInFront( - true); - private static final String PROPERTY_NGRAM_SELECTION = String.format("%s = ? AND %s = ? AND %s = ?", FTSContentColumns.TASK_ID, FTSContentColumns.TYPE, - FTSContentColumns.PROPERTY_ID); - private static final String NON_PROPERTY_NGRAM_SELECTION = String.format("%s = ? AND %s = ? AND %s is null", FTSContentColumns.TASK_ID, - FTSContentColumns.TYPE, - FTSContentColumns.PROPERTY_ID); - private static final String[] NGRAM_SYNC_COLUMNS = { "_rowid_", FTSContentColumns.NGRAM_ID }; + /** A Generator for 4-grams. */ + private static final NGramGenerator TETRAGRAM_GENERATOR = new NGramGenerator(4, + 3 /* shorter words are fully covered by trigrams */).setAddSpaceInFront(true); + private static final String PROPERTY_NGRAM_SELECTION = String.format("%s = ? AND %s = ? AND %s = ?", + FTSContentColumns.TASK_ID, FTSContentColumns.TYPE, FTSContentColumns.PROPERTY_ID); + private static final String NON_PROPERTY_NGRAM_SELECTION = String.format("%s = ? AND %s = ? AND %s is null", + FTSContentColumns.TASK_ID, FTSContentColumns.TYPE, FTSContentColumns.PROPERTY_ID); + private static final String[] NGRAM_SYNC_COLUMNS = {"_rowid_", FTSContentColumns.NGRAM_ID}; /** * Search content columns. Defines all the columns for the full text search * * @author Tobias Reinsch */ - public interface FTSContentColumns - { - /** - * The row id of the belonging task. - */ + public interface FTSContentColumns { + /** The row id of the belonging task. */ String TASK_ID = "fts_task_id"; /** - * The the property id of the searchable entry or null if the entry is not related to a property. + * The the property id of the searchable entry or null if the entry + * is not related to a property. */ String PROPERTY_ID = "fts_property_id"; - /** - * The the type of the searchable entry - */ + /** The the type of the searchable entry */ String TYPE = "fts_type"; - /** - * An n-gram for a task. - */ + /** An n-gram for a task. */ String NGRAM_ID = "fts_ngram_id"; - } - /** * The columns of the N-gram table for the FTS search * * @author Tobias Reinsch */ - public interface NGramColumns - { - /** - * The row id of the N-gram. - */ + public interface NGramColumns { + /** The row id of the N-gram. */ String NGRAM_ID = "ngram_id"; - /** - * The content of the N-gram - */ + /** The content of the N-gram */ String TEXT = "ngram_text"; - } - public static final String FTS_CONTENT_TABLE = "FTS_Content"; public static final String FTS_NGRAM_TABLE = "FTS_Ngram"; public static final String FTS_TASK_VIEW = "FTS_Task_View"; public static final String FTS_TASK_PROPERTY_VIEW = "FTS_Task_Property_View"; /** - * SQL command to create the table for full text search and contains relationships between ngrams and tasks + * SQL command to create the table for full text search and contains + * relationships between ngrams and tasks */ - private final static String SQL_CREATE_SEARCH_CONTENT_TABLE = "CREATE TABLE " + FTS_CONTENT_TABLE + "( " + FTSContentColumns.TASK_ID + " Integer, " - + FTSContentColumns.NGRAM_ID + " Integer, " + FTSContentColumns.PROPERTY_ID + " Integer, " + FTSContentColumns.TYPE + " Integer, " + "FOREIGN KEY(" - + FTSContentColumns.TASK_ID + ") REFERENCES " + Tables.TASKS + "(" + TaskColumns._ID + ")," + "FOREIGN KEY(" + FTSContentColumns.TASK_ID - + ") REFERENCES " + Tables.TASKS + "(" + TaskColumns._ID + ") UNIQUE (" + FTSContentColumns.TASK_ID + ", " + FTSContentColumns.TYPE + ", " - + FTSContentColumns.PROPERTY_ID + ") ON CONFLICT IGNORE )"; - - /** - * SQL command to create the table that stores the NGRAMS - */ - private final static String SQL_CREATE_NGRAM_TABLE = "CREATE TABLE " + FTS_NGRAM_TABLE + "( " + NGramColumns.NGRAM_ID - + " Integer PRIMARY KEY AUTOINCREMENT, " + NGramColumns.TEXT + " Text)"; - - // FIXME: at present the minimum score is hard coded can we leave that decision to the caller? - private final static String SQL_RAW_QUERY_SEARCH_TASK = "SELECT %s " + ", (1.0*count(DISTINCT " + NGramColumns.NGRAM_ID + ")/?) as " + TaskContract.Tasks.SCORE + " from " - + FTS_NGRAM_TABLE + " join " + FTS_CONTENT_TABLE + " on (" + FTS_NGRAM_TABLE + "." + NGramColumns.NGRAM_ID + "=" + FTS_CONTENT_TABLE + "." - + FTSContentColumns.NGRAM_ID + ") join " + Tables.INSTANCE_VIEW + " on (" + Tables.INSTANCE_VIEW + "." + TaskContract.Instances.TASK_ID + " = " + FTS_CONTENT_TABLE + "." - + FTSContentColumns.TASK_ID + ") where %s group by " + TaskContract.Instances.TASK_ID + " having " + TaskContract.Tasks.SCORE + " >= " + SEARCH_RESULTS_MIN_SCORE - + " and " + Tasks.VISIBLE + " = 1 order by %s;"; - - private final static String SQL_RAW_QUERY_SEARCH_TASK_DEFAULT_PROJECTION = Tables.INSTANCE_VIEW + ".* ," + FTS_NGRAM_TABLE + "." + NGramColumns.TEXT; - - private final static String SQL_CREATE_SEARCH_TASK_DELETE_TRIGGER = "CREATE TRIGGER search_task_delete_trigger AFTER DELETE ON " + Tables.TASKS + " BEGIN " - + " DELETE FROM " + FTS_CONTENT_TABLE + " WHERE " + FTSContentColumns.TASK_ID + " = old." + Tasks._ID + "; END"; - - private final static String SQL_CREATE_SEARCH_TASK_DELETE_PROPERTY_TRIGGER = "CREATE TRIGGER search_task_delete_property_trigger AFTER DELETE ON " - + Tables.PROPERTIES + " BEGIN " + " DELETE FROM " + FTS_CONTENT_TABLE + " WHERE " + FTSContentColumns.TASK_ID + " = old." + Properties.TASK_ID - + " AND " + FTSContentColumns.PROPERTY_ID + " = old." + Properties.PROPERTY_ID + "; END"; - + private static final String SQL_CREATE_SEARCH_CONTENT_TABLE = "CREATE TABLE " + FTS_CONTENT_TABLE + "( " + + FTSContentColumns.TASK_ID + " Integer, " + FTSContentColumns.NGRAM_ID + " Integer, " + + FTSContentColumns.PROPERTY_ID + " Integer, " + FTSContentColumns.TYPE + " Integer, " + "FOREIGN KEY(" + + FTSContentColumns.TASK_ID + ") REFERENCES " + Tables.TASKS + "(" + TaskColumns._ID + ")," + "FOREIGN KEY(" + + FTSContentColumns.TASK_ID + ") REFERENCES " + Tables.TASKS + "(" + TaskColumns._ID + ") UNIQUE (" + + FTSContentColumns.TASK_ID + ", " + FTSContentColumns.TYPE + ", " + FTSContentColumns.PROPERTY_ID + + ") ON CONFLICT IGNORE )"; + + /** SQL command to create the table that stores the NGRAMS */ + private static final String SQL_CREATE_NGRAM_TABLE = "CREATE TABLE " + FTS_NGRAM_TABLE + "( " + + NGramColumns.NGRAM_ID + " Integer PRIMARY KEY AUTOINCREMENT, " + NGramColumns.TEXT + " Text)"; + + // FIXME: at present the minimum score is hard coded can we leave that decision + // to the caller? + private static final String SQL_RAW_QUERY_SEARCH_TASK = "SELECT %s " + ", (1.0*count(DISTINCT " + + NGramColumns.NGRAM_ID + ")/?) as " + TaskContract.Tasks.SCORE + " from " + FTS_NGRAM_TABLE + " join " + + FTS_CONTENT_TABLE + " on (" + FTS_NGRAM_TABLE + "." + NGramColumns.NGRAM_ID + "=" + FTS_CONTENT_TABLE + + "." + FTSContentColumns.NGRAM_ID + ") join " + Tables.INSTANCE_VIEW + " on (" + Tables.INSTANCE_VIEW + "." + + TaskContract.Instances.TASK_ID + " = " + FTS_CONTENT_TABLE + "." + FTSContentColumns.TASK_ID + + ") where %s group by " + TaskContract.Instances.TASK_ID + " having " + TaskContract.Tasks.SCORE + " >= " + + SEARCH_RESULTS_MIN_SCORE + " and " + Tasks.VISIBLE + " = 1 order by %s;"; + + private static final String SQL_RAW_QUERY_SEARCH_TASK_DEFAULT_PROJECTION = Tables.INSTANCE_VIEW + ".* ," + + FTS_NGRAM_TABLE + "." + NGramColumns.TEXT; + + private static final String SQL_CREATE_SEARCH_TASK_DELETE_TRIGGER = "CREATE TRIGGER search_task_delete_trigger AFTER DELETE ON " + + Tables.TASKS + " BEGIN " + " DELETE FROM " + FTS_CONTENT_TABLE + " WHERE " + FTSContentColumns.TASK_ID + + " = old." + Tasks._ID + "; END"; + + private static final String SQL_CREATE_SEARCH_TASK_DELETE_PROPERTY_TRIGGER = "CREATE TRIGGER search_task_delete_property_trigger AFTER DELETE ON " + + Tables.PROPERTIES + " BEGIN " + " DELETE FROM " + FTS_CONTENT_TABLE + " WHERE " + + FTSContentColumns.TASK_ID + " = old." + Properties.TASK_ID + " AND " + FTSContentColumns.PROPERTY_ID + + " = old." + Properties.PROPERTY_ID + "; END"; /** - * The different types of searchable entries for tasks linked to the TYPE column. + * The different types of searchable entries for tasks linked to the + * TYPE column. * * @author Tobias Reinsch * @author Marten Gajda */ - public interface SearchableTypes - { - /** - * This is an entry for the title of a task. - */ + public interface SearchableTypes { + /** This is an entry for the title of a task. */ int TITLE = 1; - /** - * This is an entry for the description of a task. - */ + /** This is an entry for the description of a task. */ int DESCRIPTION = 2; - /** - * This is an entry for the location of a task. - */ + /** This is an entry for the location of a task. */ int LOCATION = 3; - /** - * This is an entry for a property of a task. - */ + /** This is an entry for a property of a task. */ int PROPERTY = 4; - } - - public static void onCreate(SQLiteDatabase db) - { + public static void onCreate(SQLiteDatabase db) { initializeFTS(db); } - - public static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) - { - if (oldVersion < 8) - { + public static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + if (oldVersion < 8) { initializeFTS(db); initializeFTSContent(db); } - if (oldVersion < 16) - { - db.execSQL(TaskDatabaseHelper.createIndexString(FTS_CONTENT_TABLE, true, FTSContentColumns.TYPE, FTSContentColumns.TASK_ID, - FTSContentColumns.PROPERTY_ID)); + if (oldVersion < 16) { + db.execSQL(TaskDatabaseHelper.createIndexString(FTS_CONTENT_TABLE, true, FTSContentColumns.TYPE, + FTSContentColumns.TASK_ID, FTSContentColumns.PROPERTY_ID)); } } - /** * Creates the tables and triggers used in FTS. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. */ - private static void initializeFTS(SQLiteDatabase db) - { + private static void initializeFTS(SQLiteDatabase db) { db.execSQL(SQL_CREATE_SEARCH_CONTENT_TABLE); db.execSQL(SQL_CREATE_NGRAM_TABLE); db.execSQL(SQL_CREATE_SEARCH_TASK_DELETE_TRIGGER); @@ -227,154 +193,132 @@ public class FTSDatabaseHelper db.execSQL(TaskDatabaseHelper.createIndexString(FTS_NGRAM_TABLE, true, NGramColumns.TEXT)); db.execSQL(TaskDatabaseHelper.createIndexString(FTS_CONTENT_TABLE, false, FTSContentColumns.NGRAM_ID)); db.execSQL(TaskDatabaseHelper.createIndexString(FTS_CONTENT_TABLE, false, FTSContentColumns.TASK_ID)); - db.execSQL(TaskDatabaseHelper.createIndexString(FTS_CONTENT_TABLE, true, FTSContentColumns.PROPERTY_ID, FTSContentColumns.TASK_ID, - FTSContentColumns.NGRAM_ID)); - - db.execSQL(TaskDatabaseHelper.createIndexString(FTS_CONTENT_TABLE, true, FTSContentColumns.TYPE, FTSContentColumns.TASK_ID, - FTSContentColumns.PROPERTY_ID)); + db.execSQL(TaskDatabaseHelper.createIndexString(FTS_CONTENT_TABLE, true, FTSContentColumns.PROPERTY_ID, + FTSContentColumns.TASK_ID, FTSContentColumns.NGRAM_ID)); + db.execSQL(TaskDatabaseHelper.createIndexString(FTS_CONTENT_TABLE, true, FTSContentColumns.TYPE, + FTSContentColumns.TASK_ID, FTSContentColumns.PROPERTY_ID)); } - /** * Creates the FTS entries for the existing tasks. * * @param db - * The writable {@link SQLiteDatabase}. + * The writable {@link SQLiteDatabase}. */ - private static void initializeFTSContent(SQLiteDatabase db) - { - String[] task_projection = new String[] { Tasks._ID, Tasks.TITLE, Tasks.DESCRIPTION, Tasks.LOCATION }; + private static void initializeFTSContent(SQLiteDatabase db) { + String[] task_projection = new String[]{Tasks._ID, Tasks.TITLE, Tasks.DESCRIPTION, Tasks.LOCATION}; Cursor c = db.query(Tables.TASKS_PROPERTY_VIEW, task_projection, null, null, null, null, null); - while (c.moveToNext()) - { + while (c.moveToNext()) { insertTaskFTSEntries(db, c.getLong(0), c.getString(1), c.getString(2), c.getString(3)); } c.close(); } - /** * Inserts the searchable texts of the task in the database. * * @param db - * The writable {@link SQLiteDatabase}. + * The writable {@link SQLiteDatabase}. * @param taskId - * The row id of the task. + * The row id of the task. * @param title - * The title of the task. + * The title of the task. * @param description - * The description of the task. + * The description of the task. */ - private static void insertTaskFTSEntries(SQLiteDatabase db, long taskId, String title, String description, String location) - { + private static void insertTaskFTSEntries(SQLiteDatabase db, long taskId, String title, String description, + String location) { // title - if (title != null && title.length() > 0) - { + if (title != null && title.length() > 0) { updateEntry(db, taskId, -1, SearchableTypes.TITLE, title); } // location - if (location != null && location.length() > 0) - { + if (location != null && location.length() > 0) { updateEntry(db, taskId, -1, SearchableTypes.LOCATION, location); } // description - if (description != null && description.length() > 0) - { + if (description != null && description.length() > 0) { updateEntry(db, taskId, -1, SearchableTypes.DESCRIPTION, description); } - } - /** * Updates the existing searchables entries for the task. * * @param db - * The writable {@link SQLiteDatabase}. + * The writable {@link SQLiteDatabase}. * @param task - * The {@link TaskAdapter} containing the new values. + * The {@link TaskAdapter} containing the new values. */ - public static void updateTaskFTSEntries(SQLiteDatabase db, TaskAdapter task) - { + public static void updateTaskFTSEntries(SQLiteDatabase db, TaskAdapter task) { // title - if (task.isUpdated(TaskAdapter.TITLE)) - { + if (task.isUpdated(TaskAdapter.TITLE)) { updateEntry(db, task.id(), -1, SearchableTypes.TITLE, task.valueOf(TaskAdapter.TITLE)); } // location - if (task.isUpdated(TaskAdapter.LOCATION)) - { + if (task.isUpdated(TaskAdapter.LOCATION)) { updateEntry(db, task.id(), -1, SearchableTypes.LOCATION, task.valueOf(TaskAdapter.LOCATION)); } // description - if (task.isUpdated(TaskAdapter.DESCRIPTION)) - { + if (task.isUpdated(TaskAdapter.DESCRIPTION)) { updateEntry(db, task.id(), -1, SearchableTypes.DESCRIPTION, task.valueOf(TaskAdapter.DESCRIPTION)); } - } - /** - * Updates or creates the searchable entries for a property. Passing null as searchable text will remove the entry. + * Updates or creates the searchable entries for a property. Passing + * null as searchable text will remove the entry. * * @param db - * The writable {@link SQLiteDatabase}. + * The writable {@link SQLiteDatabase}. * @param taskId - * the row id of the task this property belongs to. + * the row id of the task this property belongs to. * @param propertyId - * the id of the property + * the id of the property * @param searchableText - * the searchable text value of the property + * the searchable text value of the property */ - public static void updatePropertyFTSEntry(SQLiteDatabase db, long taskId, long propertyId, String searchableText) - { + public static void updatePropertyFTSEntry(SQLiteDatabase db, long taskId, long propertyId, String searchableText) { updateEntry(db, taskId, propertyId, SearchableTypes.PROPERTY, searchableText); } - /** - * Returns the IDs of each of the provided ngrams, creating them in th database if necessary. + * Returns the IDs of each of the provided ngrams, creating them in th database + * if necessary. * * @param db - * A writable {@link SQLiteDatabase}. + * A writable {@link SQLiteDatabase}. * @param ngrams - * The NGrams. - * + * The NGrams. * @return The ids of the ngrams in the given set. */ - private static Set ngramIds(SQLiteDatabase db, Set ngrams) - { - if (ngrams.size() == 0) - { + private static Set ngramIds(SQLiteDatabase db, Set ngrams) { + if (ngrams.size() == 0) { return Collections.emptySet(); } Set missingNgrams = new HashSet<>(ngrams); Set ngramIds = new HashSet<>(ngrams.size() * 2); - for (Iterable chunk : new Chunked<>(NGRAM_SEARCH_CHUNK_SIZE, ngrams)) - { + for (Iterable chunk : new Chunked<>(NGRAM_SEARCH_CHUNK_SIZE, ngrams)) { // build selection and arguments for each chunk - // we can't do this in a single query because the length of sql statement and number of arguments is limited. + // we can't do this in a single query because the length of sql statement and + // number of + // arguments is limited. StringBuilder selection = new StringBuilder(NGramColumns.TEXT); selection.append(" in ("); boolean first = true; List arguments = new ArrayList<>(NGRAM_SEARCH_CHUNK_SIZE); - for (String ngram : chunk) - { - if (first) - { + for (String ngram : chunk) { + if (first) { first = false; - } - else - { + } else { selection.append(","); } selection.append("?"); @@ -382,11 +326,9 @@ public class FTSDatabaseHelper } selection.append(" )"); - try (Cursor c = db.query(FTS_NGRAM_TABLE, new String[] { NGramColumns.NGRAM_ID, NGramColumns.TEXT }, selection.toString(), - arguments.toArray(new String[0]), null, null, null)) - { - while (c.moveToNext()) - { + try (Cursor c = db.query(FTS_NGRAM_TABLE, new String[]{NGramColumns.NGRAM_ID, NGramColumns.TEXT}, + selection.toString(), arguments.toArray(new String[0]), null, null, null)) { + while (c.moveToNext()) { // remove the ngrams we already have in the table missingNgrams.remove(c.getString(1)); // remember its id @@ -398,18 +340,14 @@ public class FTSDatabaseHelper ContentValues values = new ContentValues(1); // now insert the missing ngrams and store their ids - for (String ngram : missingNgrams) - { + for (String ngram : missingNgrams) { values.put(NGramColumns.TEXT, ngram); ngramIds.add(db.insert(FTS_NGRAM_TABLE, null, values)); } return ngramIds; - } - - private static void updateEntry(SQLiteDatabase db, long taskId, long propertyId, int type, String searchableText) - { + private static void updateEntry(SQLiteDatabase db, long taskId, long propertyId, int type, String searchableText) { // generate nGrams Set propertyNgrams = TRIGRAM_GENERATOR.getNgrams(searchableText); propertyNgrams.addAll(TETRAGRAM_GENERATOR.getNgrams(searchableText)); @@ -417,93 +355,82 @@ public class FTSDatabaseHelper // get an ID for each of the Ngrams. Set ngramIds = ngramIds(db, propertyNgrams); - // unlink unused ngrams from the task and get the missing ones we have to link to the tak + // unlink unused ngrams from the task and get the missing ones we have to link + // to the tak Set missing = syncNgrams(db, taskId, propertyId, type, ngramIds); // insert ngram relations for all new ngrams addNgrams(db, missing, taskId, propertyId, type); } - /** * Inserts NGrams relations for a task entry. * * @param db - * A writable {@link SQLiteDatabase}. + * A writable {@link SQLiteDatabase}. * @param ngramIds - * The set of NGram ids. + * The set of NGram ids. * @param taskId - * The row id of the task. + * The row id of the task. * @param propertyId - * The row id of the property. + * The row id of the property. */ - private static void addNgrams(SQLiteDatabase db, Set ngramIds, long taskId, Long propertyId, int contentType) - { + private static void addNgrams(SQLiteDatabase db, Set ngramIds, long taskId, Long propertyId, + int contentType) { ContentValues values = new ContentValues(4); - for (Long ngramId : ngramIds) - { + for (Long ngramId : ngramIds) { values.put(FTSContentColumns.TASK_ID, taskId); values.put(FTSContentColumns.NGRAM_ID, ngramId); values.put(FTSContentColumns.TYPE, contentType); - if (contentType == SearchableTypes.PROPERTY) - { + if (contentType == SearchableTypes.PROPERTY) { values.put(FTSContentColumns.PROPERTY_ID, propertyId); - } - else - { + } else { values.putNull(FTSContentColumns.PROPERTY_ID); } db.insert(FTS_CONTENT_TABLE, null, values); } - } - /** * Synchronizes the NGram relations of a task * * @param db - * The writable {@link SQLiteDatabase}. + * The writable {@link SQLiteDatabase}. * @param taskId - * The task row id. + * The task row id. * @param propertyId - * The property row id, ignored if contentType is not {@link SearchableTypes#PROPERTY}. + * The property row id, ignored if contentType is not + * {@link SearchableTypes#PROPERTY}. * @param contentType - * The {@link SearchableTypes} type. + * The {@link SearchableTypes} type. * @param ngramsIds - * The set of ngrams ids which should be linked to the task - * + * The set of ngrams ids which should be linked to the task * @return The number of deleted relations. */ - private static Set syncNgrams(SQLiteDatabase db, long taskId, long propertyId, int contentType, Set ngramsIds) - { + private static Set syncNgrams(SQLiteDatabase db, long taskId, long propertyId, int contentType, + Set ngramsIds) { String selection; String[] selectionArgs; - if (SearchableTypes.PROPERTY == contentType) - { + if (SearchableTypes.PROPERTY == contentType) { selection = PROPERTY_NGRAM_SELECTION; - selectionArgs = new String[] { String.valueOf(taskId), String.valueOf(contentType), String.valueOf(propertyId) }; - } - else - { + selectionArgs = new String[]{String.valueOf(taskId), String.valueOf(contentType), + String.valueOf(propertyId)}; + } else { selection = NON_PROPERTY_NGRAM_SELECTION; - selectionArgs = new String[] { String.valueOf(taskId), String.valueOf(contentType) }; + selectionArgs = new String[]{String.valueOf(taskId), String.valueOf(contentType)}; } - // In order to sync the ngrams, we go over each existing ngram and delete ngram relations not in the set of new ngrams + // In order to sync the ngrams, we go over each existing ngram and delete ngram + // relations not in + // the set of new ngrams // Then we return the set of ngrams we didn't find Set missing = new HashSet<>(ngramsIds); - try (Cursor c = db.query(FTS_CONTENT_TABLE, NGRAM_SYNC_COLUMNS, selection, selectionArgs, null, null, null)) - { - while (c.moveToNext()) - { + try (Cursor c = db.query(FTS_CONTENT_TABLE, NGRAM_SYNC_COLUMNS, selection, selectionArgs, null, null, null)) { + while (c.moveToNext()) { Long ngramId = c.getLong(1); - if (!ngramsIds.contains(ngramId)) - { - db.delete(FTS_CONTENT_TABLE, "_rowid_ = ?", new String[] { c.getString(0) }); - } - else - { + if (!ngramsIds.contains(ngramId)) { + db.delete(FTS_CONTENT_TABLE, "_rowid_ = ?", new String[]{c.getString(0)}); + } else { // this ngram wasn't missing missing.remove(ngramId); } @@ -512,39 +439,33 @@ public class FTSDatabaseHelper return missing; } - /** * Queries the task database to get a cursor with the search results. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param searchString - * The search query string. + * The search query string. * @param projection - * The database projection for the query. + * The database projection for the query. * @param selection - * The selection for the query. + * The selection for the query. * @param selectionArgs - * The arguments for the query. + * The arguments for the query. * @param sortOrder - * The sorting order of the query. - * + * The sorting order of the query. * @return A cursor of the task database with the search result. */ - public static Cursor getTaskSearchCursor(SQLiteDatabase db, String searchString, String[] projection, String selection, String[] selectionArgs, - String sortOrder) - { + public static Cursor getTaskSearchCursor(SQLiteDatabase db, String searchString, String[] projection, + String selection, String[] selectionArgs, String sortOrder) { StringBuilder selectionBuilder = new StringBuilder(1024); - if (!TextUtils.isEmpty(selection)) - { + if (!TextUtils.isEmpty(selection)) { selectionBuilder.append(" ("); selectionBuilder.append(selection); selectionBuilder.append(") AND ("); - } - else - { + } else { selectionBuilder.append(" ("); } @@ -553,33 +474,26 @@ public class FTSDatabaseHelper String[] queryArgs; - if (searchString != null && searchString.length() > 1) - { + if (searchString != null && searchString.length() > 1) { selectionBuilder.append(NGramColumns.TEXT); selectionBuilder.append(" in ("); - for (int i = 0, count = ngrams.size(); i < count; ++i) - { - if (i > 0) - { + for (int i = 0, count = ngrams.size(); i < count; ++i) { + if (i > 0) { selectionBuilder.append(","); } selectionBuilder.append("?"); - } // selection arguments - if (selectionArgs != null && selectionArgs.length > 0) - { + if (selectionArgs != null && selectionArgs.length > 0) { queryArgs = new String[selectionArgs.length + ngrams.size() + 1]; queryArgs[0] = String.valueOf(ngrams.size()); System.arraycopy(selectionArgs, 0, queryArgs, 1, selectionArgs.length); String[] ngramArray = ngrams.toArray(new String[ngrams.size()]); System.arraycopy(ngramArray, 0, queryArgs, selectionArgs.length + 1, ngramArray.length); - } - else - { + } else { String[] temp = ngrams.toArray(new String[ngrams.size()]); queryArgs = new String[temp.length + 1]; @@ -587,44 +501,34 @@ public class FTSDatabaseHelper System.arraycopy(temp, 0, queryArgs, 1, temp.length); } selectionBuilder.append(" ) "); - } - else - { + } else { selectionBuilder.append(NGramColumns.TEXT); selectionBuilder.append(" like ?"); // selection arguments - if (selectionArgs != null && selectionArgs.length > 0) - { + if (selectionArgs != null && selectionArgs.length > 0) { queryArgs = new String[selectionArgs.length + 2]; queryArgs[0] = String.valueOf(ngrams.size()); System.arraycopy(selectionArgs, 0, queryArgs, 1, selectionArgs.length); queryArgs[queryArgs.length - 1] = " " + searchString + "%"; - } - else - { + } else { queryArgs = new String[2]; queryArgs[0] = String.valueOf(ngrams.size()); queryArgs[1] = " " + searchString + "%"; } - } selectionBuilder.append(") AND "); selectionBuilder.append(Tasks._DELETED); selectionBuilder.append(" = 0"); - if (sortOrder == null) - { + if (sortOrder == null) { sortOrder = Tasks.SCORE + " desc"; - } - else - { + } else { sortOrder = Tasks.SCORE + " desc, " + sortOrder; } - Cursor c = db.rawQueryWithFactory(null, - String.format(SQL_RAW_QUERY_SEARCH_TASK, SQL_RAW_QUERY_SEARCH_TASK_DEFAULT_PROJECTION, selectionBuilder.toString(), sortOrder), queryArgs, - null); + Cursor c = db.rawQueryWithFactory(null, String.format(SQL_RAW_QUERY_SEARCH_TASK, + SQL_RAW_QUERY_SEARCH_TASK_DEFAULT_PROJECTION, selectionBuilder.toString(), sortOrder), queryArgs, null); return c; } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ProviderOperation.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ProviderOperation.java index 2d50bfdbff66b537821408ecff9a5d9459b5288a..f8b8a2b27cb4d09890c982f73a37bac7ff59c051 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ProviderOperation.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/ProviderOperation.java @@ -19,21 +19,14 @@ package org.dmfs.provider.tasks; /** * @author Marten Gajda */ -public enum ProviderOperation -{ +public enum ProviderOperation { - /** - * Insert operations. - */ + /** Insert operations. */ INSERT, - /** - * Update operations. - */ + /** Update operations. */ UPDATE, - /** - * Delete operations. - */ + /** Delete operations. */ DELETE } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/SQLiteContentProvider.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/SQLiteContentProvider.java index 21c54ae0c75c1e9413581eb9bf594ef2ecb5ff74..fbc8a921ac58422c8439e4a03fbb5c28feced5ca 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/SQLiteContentProvider.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/SQLiteContentProvider.java @@ -26,39 +26,35 @@ import android.content.OperationApplicationException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; - +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; import org.dmfs.iterables.SingletonIterable; import org.dmfs.jems.fragile.Fragile; import org.dmfs.jems.iterable.composite.Joined; import org.dmfs.jems.single.Single; import org.dmfs.provider.tasks.utils.Profiled; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Locale; -import java.util.Set; - - /** - * General purpose {@link ContentProvider} base class that uses SQLiteDatabase for storage. + * General purpose {@link ContentProvider} base class that uses SQLiteDatabase + * for storage. */ /* * Changed by marten@dmfs.org: - * - * removed protected mDb field and replaced it by local fields. There is no reason to store the database if we get a new one for every transaction. Instead we - * also pass the database to the *InTransaction methods. - * + * + * removed protected mDb field and replaced it by local fields. There is no + * reason to store the database if we get a new one for every transaction. + * Instead we also pass the database to the *InTransaction methods. + * * update visibility of class and methods */ -abstract class SQLiteContentProvider extends ContentProvider -{ +abstract class SQLiteContentProvider extends ContentProvider { - interface TransactionEndTask - { + interface TransactionEndTask { void execute(SQLiteDatabase database); } - @SuppressWarnings("unused") private static final String TAG = "SQLiteContentProvider"; @@ -68,133 +64,106 @@ abstract class SQLiteContentProvider extends ContentProvider private final ThreadLocal mApplyingBatch = new ThreadLocal(); private static final int SLEEP_AFTER_YIELD_DELAY = 4000; - /** - * Maximum number of operations allowed in a batch between yield points. - */ + /** Maximum number of operations allowed in a batch between yield points. */ private static final int MAX_OPERATIONS_PER_YIELD_POINT = 500; private final Iterable mTransactionEndTasks; - - protected SQLiteContentProvider(Iterable transactionEndTasks) - { + protected SQLiteContentProvider(Iterable transactionEndTasks) { // append a task to set the transaction to successful - mTransactionEndTasks = new Joined<>(transactionEndTasks, new SingletonIterable<>(new SuccessfulTransactionEndTask())); + mTransactionEndTasks = new Joined<>(transactionEndTasks, + new SingletonIterable<>(new SuccessfulTransactionEndTask())); } - @Override - public boolean onCreate() - { + public boolean onCreate() { mOpenHelper = getDatabaseHelper(getContext()); return true; } - - /** - * Returns a {@link SQLiteOpenHelper} that can open the database. - */ + /** Returns a {@link SQLiteOpenHelper} that can open the database. */ protected abstract SQLiteOpenHelper getDatabaseHelper(Context context); /** - * The equivalent of the {@link #insert} method, but invoked within a transaction. + * The equivalent of the {@link #insert} method, but invoked within a + * transaction. */ - public abstract Uri insertInTransaction(SQLiteDatabase db, Uri uri, ContentValues values, boolean callerIsSyncAdapter); + public abstract Uri insertInTransaction(SQLiteDatabase db, Uri uri, ContentValues values, + boolean callerIsSyncAdapter); /** - * The equivalent of the {@link #update} method, but invoked within a transaction. + * The equivalent of the {@link #update} method, but invoked within a + * transaction. */ - public abstract int updateInTransaction(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String[] selectionArgs, - boolean callerIsSyncAdapter); + public abstract int updateInTransaction(SQLiteDatabase db, Uri uri, ContentValues values, String selection, + String[] selectionArgs, boolean callerIsSyncAdapter); /** - * The equivalent of the {@link #delete} method, but invoked within a transaction. + * The equivalent of the {@link #delete} method, but invoked within a + * transaction. */ - public abstract int deleteInTransaction(SQLiteDatabase db, Uri uri, String selection, String[] selectionArgs, boolean callerIsSyncAdapter); - + public abstract int deleteInTransaction(SQLiteDatabase db, Uri uri, String selection, String[] selectionArgs, + boolean callerIsSyncAdapter); /** - * Call this to add a URI to the list of URIs to be notified when the transaction is committed. + * Call this to add a URI to the list of URIs to be notified when the + * transaction is committed. */ - protected void postNotifyUri(Uri uri) - { - synchronized (mChangedUris) - { + protected void postNotifyUri(Uri uri) { + synchronized (mChangedUris) { mChangedUris.add(uri); } } - - public boolean isCallerSyncAdapter(Uri uri) - { + public boolean isCallerSyncAdapter(Uri uri) { return false; } - - public SQLiteOpenHelper getDatabaseHelper() - { + public SQLiteOpenHelper getDatabaseHelper() { return mOpenHelper; } - - private boolean applyingBatch() - { + private boolean applyingBatch() { return mApplyingBatch.get() != null && mApplyingBatch.get(); } - @Override - public Uri insert(Uri uri, ContentValues values) - { - return new Profiled("Insert").run((Single) () -> - { + public Uri insert(Uri uri, ContentValues values) { + return new Profiled("Insert").run((Single) () -> { Uri result; boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); boolean applyingBatch = applyingBatch(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - if (!applyingBatch) - { + if (!applyingBatch) { db.beginTransaction(); - try - { + try { result = insertInTransaction(db, uri, values, callerIsSyncAdapter); endTransaction(db); - } - finally - { + } finally { db.endTransaction(); } onEndTransaction(callerIsSyncAdapter); - } - else - { + } else { result = insertInTransaction(db, uri, values, callerIsSyncAdapter); } return result; }); } - @Override - public int bulkInsert(Uri uri, ContentValues[] values) - { - return new Profiled("BulkInsert").run((Single) () -> - { + public int bulkInsert(Uri uri, ContentValues[] values) { + return new Profiled("BulkInsert").run((Single) () -> { int numValues = values.length; boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); db.beginTransaction(); - try - { - for (int i = 0; i < numValues; i++) - { + try { + for (int i = 0; i < numValues; i++) { insertInTransaction(db, uri, values[i], callerIsSyncAdapter); db.yieldIfContendedSafely(); } endTransaction(db); - } - finally - { + } finally { db.endTransaction(); } onEndTransaction(callerIsSyncAdapter); @@ -202,104 +171,81 @@ abstract class SQLiteContentProvider extends ContentProvider }); } - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) - { - return new Profiled("Update").run((Single) () -> - { + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return new Profiled("Update").run((Single) () -> { int count; boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); boolean applyingBatch = applyingBatch(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - if (!applyingBatch) - { + if (!applyingBatch) { db.beginTransaction(); - try - { + try { count = updateInTransaction(db, uri, values, selection, selectionArgs, callerIsSyncAdapter); endTransaction(db); - } - finally - { + } finally { db.endTransaction(); } onEndTransaction(callerIsSyncAdapter); - } - else - { + } else { count = updateInTransaction(db, uri, values, selection, selectionArgs, callerIsSyncAdapter); } return count; }); } - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) - { - return new Profiled("Delete").run((Single) () -> - { + public int delete(Uri uri, String selection, String[] selectionArgs) { + return new Profiled("Delete").run((Single) () -> { int count; boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); boolean applyingBatch = applyingBatch(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - if (!applyingBatch) - { + if (!applyingBatch) { db.beginTransaction(); - try - { + try { count = deleteInTransaction(db, uri, selection, selectionArgs, callerIsSyncAdapter); endTransaction(db); - } - finally - { + } finally { db.endTransaction(); } onEndTransaction(callerIsSyncAdapter); - } - else - { + } else { count = deleteInTransaction(db, uri, selection, selectionArgs, callerIsSyncAdapter); } return count; }); } - @Override - public ContentProviderResult[] applyBatch(ArrayList operations) throws OperationApplicationException - { - return new Profiled(String.format(Locale.ENGLISH, "Batch of %d operations", operations.size())).run( - (Fragile) () -> - { + public ContentProviderResult[] applyBatch(ArrayList operations) + throws OperationApplicationException { + return new Profiled(String.format(Locale.ENGLISH, "Batch of %d operations", operations.size())) + .run((Fragile) () -> { int ypCount = 0; int opCount = 0; boolean callerIsSyncAdapter = false; SQLiteDatabase db = mOpenHelper.getWritableDatabase(); db.beginTransaction(); - try - { + try { mApplyingBatch.set(true); final int numOperations = operations.size(); final ContentProviderResult[] results = new ContentProviderResult[numOperations]; - for (int i = 0; i < numOperations; i++) - { - if (++opCount >= MAX_OPERATIONS_PER_YIELD_POINT) - { - throw new OperationApplicationException("Too many content provider operations between yield points. " - + "The maximum number of operations per yield point is " + MAX_OPERATIONS_PER_YIELD_POINT, ypCount); + for (int i = 0; i < numOperations; i++) { + if (++opCount >= MAX_OPERATIONS_PER_YIELD_POINT) { + throw new OperationApplicationException( + "Too many content provider operations between yield points. " + + "The maximum number of operations per yield point is " + + MAX_OPERATIONS_PER_YIELD_POINT, + ypCount); } final ContentProviderOperation operation = operations.get(i); - if (!callerIsSyncAdapter && isCallerSyncAdapter(operation.getUri())) - { + if (!callerIsSyncAdapter && isCallerSyncAdapter(operation.getUri())) { callerIsSyncAdapter = true; } - if (i > 0 && operation.isYieldAllowed()) - { + if (i > 0 && operation.isYieldAllowed()) { opCount = 0; - if (db.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY)) - { + if (db.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY)) { ypCount++; } } @@ -307,9 +253,7 @@ abstract class SQLiteContentProvider extends ContentProvider } endTransaction(db); return results; - } - finally - { + } finally { mApplyingBatch.set(false); db.endTransaction(); onEndTransaction(callerIsSyncAdapter); @@ -317,47 +261,33 @@ abstract class SQLiteContentProvider extends ContentProvider }); } - - protected void onEndTransaction(boolean callerIsSyncAdapter) - { + protected void onEndTransaction(boolean callerIsSyncAdapter) { Set changed; - synchronized (mChangedUris) - { + synchronized (mChangedUris) { changed = new HashSet(mChangedUris); mChangedUris.clear(); } ContentResolver resolver = getContext().getContentResolver(); - for (Uri uri : changed) - { + for (Uri uri : changed) { boolean syncToNetwork = !callerIsSyncAdapter && syncToNetwork(uri); resolver.notifyChange(uri, null, syncToNetwork); } } - - protected boolean syncToNetwork(Uri uri) - { + protected boolean syncToNetwork(Uri uri) { return false; } - - private void endTransaction(SQLiteDatabase database) - { - for (TransactionEndTask task : mTransactionEndTasks) - { + private void endTransaction(SQLiteDatabase database) { + for (TransactionEndTask task : mTransactionEndTasks) { task.execute(database); } } - - /** - * A {@link TransactionEndTask} which sets the transaction to be successful. - */ - private static class SuccessfulTransactionEndTask implements TransactionEndTask - { + /** A {@link TransactionEndTask} which sets the transaction to be successful. */ + private static class SuccessfulTransactionEndTask implements TransactionEndTask { @Override - public void execute(SQLiteDatabase database) - { + public void execute(SQLiteDatabase database) { database.setTransactionSuccessful(); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskDatabaseHelper.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskDatabaseHelper.java index a78d8c76d7a556d29c5de49114587eeaa053aac2..cac006ec8ab88174a69f5c934fd26a288fe5f756 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskDatabaseHelper.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskDatabaseHelper.java @@ -22,7 +22,7 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; - +import java.util.Locale; import org.dmfs.jems.optional.adapters.First; import org.dmfs.jems.predicate.elementary.Equals; import org.dmfs.provider.tasks.model.CursorContentValuesTaskAdapter; @@ -38,47 +38,35 @@ import org.dmfs.tasks.contract.TaskContract.Property.Category; import org.dmfs.tasks.contract.TaskContract.TaskLists; import org.dmfs.tasks.contract.TaskContract.Tasks; -import java.util.Locale; - - /** - * Task database helper takes care of creating and updating the task database, including tables, indices and triggers. + * Task database helper takes care of creating and updating the task database, + * including tables, indices and triggers. * * @author Marten Gajda * @author Tobias Reinsch */ -public class TaskDatabaseHelper extends SQLiteOpenHelper -{ +public class TaskDatabaseHelper extends SQLiteOpenHelper { /** - * Interface of a listener that's called when the database has been created or migrated. + * Interface of a listener that's called when the database has been created or + * migrated. */ - public interface OnDatabaseOperationListener - { + public interface OnDatabaseOperationListener { void onDatabaseCreated(SQLiteDatabase db); void onDatabaseUpdate(SQLiteDatabase db, int oldVersion, int newVersion); } - private static final String TAG = "TaskDatabaseHelper"; - /** - * The name of our database file. - */ + /** The name of our database file. */ private static final String DATABASE_NAME = "tasks.db"; - /** - * The database version. - */ + /** The database version. */ private static final int DATABASE_VERSION = 23; - - /** - * List of all tables we provide. - */ - public interface Tables - { + /** List of all tables we provide. */ + public interface Tables { String LISTS = "Lists"; String WRITEABLE_LISTS = "Writeable_Lists"; @@ -110,449 +98,316 @@ public class TaskDatabaseHelper extends SQLiteOpenHelper String SYNCSTATE = "SyncState"; } - - /** - * Columns of internal table for the category mapping. - */ - public interface CategoriesMapping - { + /** Columns of internal table for the category mapping. */ + public interface CategoriesMapping { String TASK_ID = "task_id"; String CATEGORY_ID = "category_id"; String PROPERTY_ID = "property_id"; - } - /** - * SQL command to create a view that combines tasks with some data from the list they belong to. + * SQL command to create a view that combines tasks with some data from the list + * they belong to. */ - private final static String SQL_CREATE_TASK_VIEW = "create view " + Tables.TASKS_VIEW + " as select " + - Tables.TASKS + ".*, " + - Tables.LISTS + "." + Tasks.ACCOUNT_NAME + ", " + - Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " + - Tables.LISTS + "." + Tasks.LIST_OWNER + ", " + - Tables.LISTS + "." + Tasks.LIST_NAME + ", " + - Tables.LISTS + "." + Tasks.LIST_ACCESS_LEVEL + ", " + - Tables.LISTS + "." + Tasks.LIST_COLOR + ", " + - Tables.LISTS + "." + Tasks.VISIBLE + - " from " + Tables.TASKS + " join " + Tables.LISTS + - " on (" + Tables.TASKS + "." + Tasks.LIST_ID + "=" + Tables.LISTS + "." + TaskLists._ID + ");"; + private static final String SQL_CREATE_TASK_VIEW = "create view " + Tables.TASKS_VIEW + " as select " + Tables.TASKS + + ".*, " + Tables.LISTS + "." + Tasks.ACCOUNT_NAME + ", " + Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " + + Tables.LISTS + "." + Tasks.LIST_OWNER + ", " + Tables.LISTS + "." + Tasks.LIST_NAME + ", " + Tables.LISTS + + "." + Tasks.LIST_ACCESS_LEVEL + ", " + Tables.LISTS + "." + Tasks.LIST_COLOR + ", " + Tables.LISTS + "." + + Tasks.VISIBLE + " from " + Tables.TASKS + " join " + Tables.LISTS + " on (" + Tables.TASKS + "." + + Tasks.LIST_ID + "=" + Tables.LISTS + "." + TaskLists._ID + ");"; /** - * SQL command to create a view that combines tasks with some data from the list they belong to. + * SQL command to create a view that combines tasks with some data from the list + * they belong to. */ - private final static String SQL_CREATE_TASK_PROPERTY_VIEW = "create view " + Tables.TASKS_PROPERTY_VIEW + " as select " + - Tables.TASKS + ".*, " + - Tables.PROPERTIES + ".*, " + - Tables.LISTS + "." + Tasks.ACCOUNT_NAME + ", " + - Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " + - Tables.LISTS + "." + Tasks.LIST_OWNER + ", " + - Tables.LISTS + "." + Tasks.LIST_NAME + ", " + - Tables.LISTS + "." + Tasks.LIST_ACCESS_LEVEL + ", " + - Tables.LISTS + "." + Tasks.LIST_COLOR + ", " + - Tables.LISTS + "." + Tasks.VISIBLE + - " from " + Tables.TASKS + " join " + Tables.LISTS + - " on (" + Tables.TASKS + "." + Tasks.LIST_ID + "=" + Tables.LISTS + "." + TaskLists._ID + ") " + - "left join " + Tables.PROPERTIES + " on (" + Tables.TASKS + "." + Tasks._ID + "=" + Tables.PROPERTIES + "." + Properties.TASK_ID + ");"; + private static final String SQL_CREATE_TASK_PROPERTY_VIEW = "create view " + Tables.TASKS_PROPERTY_VIEW + + " as select " + Tables.TASKS + ".*, " + Tables.PROPERTIES + ".*, " + Tables.LISTS + "." + + Tasks.ACCOUNT_NAME + ", " + Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " + Tables.LISTS + "." + + Tasks.LIST_OWNER + ", " + Tables.LISTS + "." + Tasks.LIST_NAME + ", " + Tables.LISTS + "." + + Tasks.LIST_ACCESS_LEVEL + ", " + Tables.LISTS + "." + Tasks.LIST_COLOR + ", " + Tables.LISTS + "." + + Tasks.VISIBLE + " from " + Tables.TASKS + " join " + Tables.LISTS + " on (" + Tables.TASKS + "." + + Tasks.LIST_ID + "=" + Tables.LISTS + "." + TaskLists._ID + ") " + "left join " + Tables.PROPERTIES + + " on (" + Tables.TASKS + "." + Tasks._ID + "=" + Tables.PROPERTIES + "." + Properties.TASK_ID + ");"; - /** - * SQL command to drop the task view. - */ - private final static String SQL_DROP_TASK_VIEW = "DROP VIEW " + Tables.TASKS_VIEW + ";"; + /** SQL command to drop the task view. */ + private static final String SQL_DROP_TASK_VIEW = "DROP VIEW " + Tables.TASKS_VIEW + ";"; /** - * SQL command to create a view that combines task instances with some data from the list they belong to. + * SQL command to create a view that combines task instances with some data from + * the list they belong to. */ - private final static String SQL_CREATE_INSTANCE_VIEW = "CREATE VIEW " + Tables.INSTANCE_VIEW + " AS SELECT " - + Tables.INSTANCES + ".*, " - + Tables.TASKS + ".*, " - + Tables.LISTS + "." + Tasks.ACCOUNT_NAME + ", " - + Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " - + Tables.LISTS + "." + Tasks.LIST_OWNER + ", " - + Tables.LISTS + "." + Tasks.LIST_NAME + ", " - + Tables.LISTS + "." + Tasks.LIST_ACCESS_LEVEL + ", " - + Tables.LISTS + "." + Tasks.LIST_COLOR + ", " - + Tables.LISTS + "." + Tasks.VISIBLE - + " FROM " + Tables.TASKS - + " JOIN " + Tables.LISTS + " ON (" + Tables.TASKS + "." + TaskContract.Tasks.LIST_ID + "=" + Tables.LISTS + "." + TaskContract.Tasks._ID + ")" - + " JOIN " + Tables.INSTANCES + " ON (" + Tables.TASKS + "." + TaskContract.Tasks._ID + "=" + Tables.INSTANCES + "." + TaskContract.Instances.TASK_ID + ");"; + private static final String SQL_CREATE_INSTANCE_VIEW = "CREATE VIEW " + Tables.INSTANCE_VIEW + " AS SELECT " + + Tables.INSTANCES + ".*, " + Tables.TASKS + ".*, " + Tables.LISTS + "." + Tasks.ACCOUNT_NAME + ", " + + Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " + Tables.LISTS + "." + Tasks.LIST_OWNER + ", " + + Tables.LISTS + "." + Tasks.LIST_NAME + ", " + Tables.LISTS + "." + Tasks.LIST_ACCESS_LEVEL + ", " + + Tables.LISTS + "." + Tasks.LIST_COLOR + ", " + Tables.LISTS + "." + Tasks.VISIBLE + " FROM " + + Tables.TASKS + " JOIN " + Tables.LISTS + " ON (" + Tables.TASKS + "." + TaskContract.Tasks.LIST_ID + "=" + + Tables.LISTS + "." + TaskContract.Tasks._ID + ")" + " JOIN " + Tables.INSTANCES + " ON (" + Tables.TASKS + + "." + TaskContract.Tasks._ID + "=" + Tables.INSTANCES + "." + TaskContract.Instances.TASK_ID + ");"; /** - * SQL command to create a view that combines task instances with some data from the list they belong to. This replaces the task DTSTART, DUE and + * SQL command to create a view that combines task instances with some data from + * the list they belong to. This replaces the task DTSTART, DUE and * ORIGINAL_INSTANCE_TIME values with respective values of the instance. + * *

* This is the instances view as seen by the content provider clients. */ - private final static String SQL_CREATE_INSTANCE_CLIENT_VIEW = "CREATE VIEW " + Tables.INSTANCE_CLIENT_VIEW + " AS SELECT " - + Tables.INSTANCES + ".*, " + private static final String SQL_CREATE_INSTANCE_CLIENT_VIEW = "CREATE VIEW " + Tables.INSTANCE_CLIENT_VIEW + + " AS SELECT " + Tables.INSTANCES + ".*, " // override task due, start and original times with the instance values + Tables.INSTANCES + "." + TaskContract.Instances.INSTANCE_START + " as " + Tasks.DTSTART + ", " + Tables.INSTANCES + "." + TaskContract.Instances.INSTANCE_DUE + " as " + Tasks.DUE + ", " - + Tables.INSTANCES + "." + TaskContract.Instances.INSTANCE_ORIGINAL_TIME + " as " + Tasks.ORIGINAL_INSTANCE_TIME + ", " + + Tables.INSTANCES + "." + TaskContract.Instances.INSTANCE_ORIGINAL_TIME + " as " + + Tasks.ORIGINAL_INSTANCE_TIME + ", " // override task duration with null, we already have a due + "null as " + Tasks.DURATION + ", " // override recurrence values with null, instances themselves are not recurring - + "null as " + Tasks.RRULE + ", " - + "null as " + Tasks.RDATE + ", " - + "null as " + Tasks.EXDATE + ", " - // this instance is part of a recurring task if either it has recurrence values or overrides an instance - + "not (" + Tasks.RRULE + " is null and " + Tasks.RDATE + " is null and " + Tasks.ORIGINAL_INSTANCE_ID + " is null and " + Tasks.ORIGINAL_INSTANCE_SYNC_ID + " is null) as " + TaskContract.Instances.IS_RECURRING + ", " - + Tables.TASKS + ".*, " - + Tables.LISTS + "." + Tasks.ACCOUNT_NAME + ", " - + Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " - + Tables.LISTS + "." + Tasks.LIST_OWNER + ", " - + Tables.LISTS + "." + Tasks.LIST_NAME + ", " - + Tables.LISTS + "." + Tasks.LIST_ACCESS_LEVEL + ", " - + Tables.LISTS + "." + Tasks.LIST_COLOR + ", " - + Tables.LISTS + "." + Tasks.VISIBLE - + " FROM " + Tables.TASKS - + " JOIN " + Tables.LISTS + " ON (" + Tables.TASKS + "." + TaskContract.Tasks.LIST_ID + "=" + Tables.LISTS + "." + TaskContract.TaskLists._ID + ")" - + " JOIN " + Tables.INSTANCES + " ON (" + Tables.TASKS + "." + TaskContract.Tasks._ID + "=" + Tables.INSTANCES + "." + TaskContract.Instances.TASK_ID + ");"; - - /** - * SQL command to create a view that combines task instances view with the belonging properties. - */ - private final static String SQL_CREATE_INSTANCE_PROPERTY_VIEW = "CREATE VIEW " + Tables.INSTANCE_PROPERTY_VIEW + " AS SELECT " - + Tables.INSTANCES + ".*, " - + Tables.PROPERTIES + ".*, " - + Tables.TASKS + ".*, " - + Tables.LISTS + "." + Tasks.ACCOUNT_NAME + ", " - + Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " - + Tables.LISTS + "." + Tasks.LIST_OWNER + ", " - + Tables.LISTS + "." + Tasks.LIST_NAME + ", " - + Tables.LISTS + "." + Tasks.LIST_ACCESS_LEVEL + ", " - + Tables.LISTS + "." + Tasks.LIST_COLOR + ", " - + Tables.LISTS + "." + Tasks.VISIBLE - + " FROM " + Tables.TASKS - + " JOIN " + Tables.LISTS + " ON (" + Tables.TASKS + "." + TaskContract.Tasks.LIST_ID + "=" + Tables.LISTS + "." + TaskContract.Tasks._ID + ")" - + " JOIN " + Tables.INSTANCES + " ON (" + Tables.TASKS + "." + TaskContract.Tasks._ID + "=" + Tables.INSTANCES + "." + TaskContract.Instances.TASK_ID + ")" - + " LEFT JOIN " + Tables.PROPERTIES + " ON (" + Tables.TASKS + "." + Tasks._ID + "=" + Tables.PROPERTIES + "." + Properties.TASK_ID + ");"; - - /** - * SQL command to create a view that combines task instances with some data from the list they belong to. - */ - private final static String SQL_CREATE_INSTANCE_CATEGORY_VIEW = "CREATE VIEW " + Tables.INSTANCE_CATEGORY_VIEW + " AS SELECT " - + Tables.INSTANCES + ".*, " - + Tables.CATEGORIES_MAPPING + "." + CategoriesMapping.CATEGORY_ID + ", " - + Tables.TASKS + ".*, " - + Tables.LISTS + "." + Tasks.ACCOUNT_NAME + ", " - + Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " - + Tables.LISTS + "." + Tasks.LIST_OWNER + ", " - + Tables.LISTS + "." + Tasks.LIST_NAME + ", " - + Tables.LISTS + "." + Tasks.LIST_ACCESS_LEVEL + ", " - + Tables.LISTS + "." + Tasks.LIST_COLOR + ", " - + Tables.LISTS + "." + Tasks.VISIBLE - + " FROM " + Tables.TASKS - + " JOIN " + Tables.LISTS + " ON (" + Tables.TASKS + "." + TaskContract.Tasks.LIST_ID + "=" + Tables.LISTS + "." + TaskContract.Tasks._ID + ")" - + " JOIN " + Tables.INSTANCES + " ON (" + Tables.TASKS + "." + TaskContract.Tasks._ID + "=" + Tables.INSTANCES + "." + TaskContract.Instances.TASK_ID + ")" - + " LEFT JOIN " + Tables.CATEGORIES_MAPPING + " ON (" + Tables.CATEGORIES_MAPPING + "." + CategoriesMapping.TASK_ID + "=" + Tables.INSTANCES + "." + TaskContract.Instances.TASK_ID + ");"; - - /** - * SQL command to drop the instance view. - */ - private final static String SQL_DROP_INSTANCE_VIEW = "DROP VIEW " + Tables.INSTANCE_VIEW + ";"; - - /** - * SQL command to drop the instance property view. - */ - //private final static String SQL_DROP_INSTANCE_PROPERTY_VIEW = "DROP VIEW " + Tables.INSTANCE_PROPERTY_VIEW + ";"; - - /** - * SQL command to create the instances table. - */ - private final static String SQL_CREATE_SYNCSTATE_TABLE = - "CREATE TABLE " + Tables.SYNCSTATE + " ( " + - TaskContract.SyncState._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + TaskContract.SyncState.ACCOUNT_NAME + " TEXT, " - + TaskContract.SyncState.ACCOUNT_TYPE + " TEXT, " - + TaskContract.SyncState.DATA + " TEXT " - + ");"; - - /** - * SQL command to create the instances table. - */ - private final static String SQL_CREATE_INSTANCES_TABLE = - "CREATE TABLE " + Tables.INSTANCES + " ( " + - TaskContract.Instances._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + TaskContract.Instances.TASK_ID + " INTEGER NOT NULL, " // NOT NULL - + TaskContract.Instances.INSTANCE_START + " INTEGER, " - + TaskContract.Instances.INSTANCE_DUE + " INTEGER, " - + TaskContract.Instances.INSTANCE_START_SORTING + " INTEGER, " - + TaskContract.Instances.INSTANCE_DUE_SORTING + " INTEGER, " - + TaskContract.Instances.INSTANCE_DURATION + " INTEGER, " - + TaskContract.Instances.INSTANCE_ORIGINAL_TIME + " INTEGER DEFAULT 0, " - + TaskContract.Instances.DISTANCE_FROM_CURRENT + " INTEGER DEFAULT 0);"; - - /** - * SQL command to create a trigger to clean up data of removed tasks. - */ - private final static String SQL_CREATE_TASKS_CLEANUP_TRIGGER = - "CREATE TRIGGER task_cleanup_trigger AFTER DELETE ON " + Tables.TASKS - + " BEGIN " - + " DELETE FROM " + Tables.PROPERTIES + " WHERE " + TaskContract.Properties.TASK_ID + "= old." + TaskContract.Tasks._ID + ";" - + " DELETE FROM " + Tables.INSTANCES + " WHERE " + TaskContract.Instances.TASK_ID + "=old." + TaskContract.Tasks._ID + ";" - + " END;"; - - /** - * SQL command to create a trigger to clean up data of removed lists. - */ - private final static String SQL_CREATE_LISTS_CLEANUP_TRIGGER = - "CREATE TRIGGER list_cleanup_trigger AFTER DELETE ON " + Tables.LISTS - + " BEGIN " - + " DELETE FROM " + Tables.TASKS + " WHERE " + Tasks.LIST_ID + "= old." + TaskLists._ID + ";" - + " END;"; - - /** - * SQL command to drop the clean up trigger. - */ - private final static String SQL_DROP_TASKS_CLEANUP_TRIGGER = - "DROP TRIGGER task_cleanup_trigger;"; - - /** - * SQL command that counts and sets the alarm on deletion - */ - private final static String SQL_COUNT_ALARMS_ON_DELETE = - " BEGIN UPDATE " + Tables.TASKS + " SET " + Tasks.HAS_ALARMS - + " = (SELECT COUNT (*) FROM " + Tables.PROPERTIES - + " WHERE " + Properties.MIMETYPE + " = '" + Alarm.CONTENT_ITEM_TYPE + "' AND " + Alarm.ALARM_TYPE + " <> " + Alarm.ALARM_TYPE_NOTHING + " AND " + Properties.TASK_ID + " = OLD." + Properties.TASK_ID - + ") WHERE " + Tasks._ID + " = OLD." + Properties.TASK_ID - + "; END;"; - - /** - * SQL command that counts and sets the alarm on insert and update - */ - private final static String SQL_COUNT_ALARMS = - " BEGIN UPDATE " + Tables.TASKS + " SET " + Tasks.HAS_ALARMS - + " = (SELECT COUNT (*) FROM " + Tables.PROPERTIES - + " WHERE " + Properties.MIMETYPE + " = '" + Alarm.CONTENT_ITEM_TYPE + "' AND " + Alarm.ALARM_TYPE + " <> " + Alarm.ALARM_TYPE_NOTHING + " AND " + Properties.TASK_ID + " = NEW." + Properties.TASK_ID - + ") WHERE " + Tasks._ID + " = NEW." + Properties.TASK_ID - + "; END;"; + + "null as " + Tasks.RRULE + ", " + "null as " + Tasks.RDATE + ", " + "null as " + Tasks.EXDATE + ", " + // this instance is part of a recurring task if either it has recurrence values + // or + // overrides an instance + + "not (" + Tasks.RRULE + " is null and " + Tasks.RDATE + " is null and " + Tasks.ORIGINAL_INSTANCE_ID + + " is null and " + Tasks.ORIGINAL_INSTANCE_SYNC_ID + " is null) as " + TaskContract.Instances.IS_RECURRING + + ", " + Tables.TASKS + ".*, " + Tables.LISTS + "." + Tasks.ACCOUNT_NAME + ", " + Tables.LISTS + "." + + Tasks.ACCOUNT_TYPE + ", " + Tables.LISTS + "." + Tasks.LIST_OWNER + ", " + Tables.LISTS + "." + + Tasks.LIST_NAME + ", " + Tables.LISTS + "." + Tasks.LIST_ACCESS_LEVEL + ", " + Tables.LISTS + "." + + Tasks.LIST_COLOR + ", " + Tables.LISTS + "." + Tasks.VISIBLE + " FROM " + Tables.TASKS + " JOIN " + + Tables.LISTS + " ON (" + Tables.TASKS + "." + TaskContract.Tasks.LIST_ID + "=" + Tables.LISTS + "." + + TaskContract.TaskLists._ID + ")" + " JOIN " + Tables.INSTANCES + " ON (" + Tables.TASKS + "." + + TaskContract.Tasks._ID + "=" + Tables.INSTANCES + "." + TaskContract.Instances.TASK_ID + ");"; + + /** + * SQL command to create a view that combines task instances view with the + * belonging properties. + */ + private static final String SQL_CREATE_INSTANCE_PROPERTY_VIEW = "CREATE VIEW " + Tables.INSTANCE_PROPERTY_VIEW + + " AS SELECT " + Tables.INSTANCES + ".*, " + Tables.PROPERTIES + ".*, " + Tables.TASKS + ".*, " + + Tables.LISTS + "." + Tasks.ACCOUNT_NAME + ", " + Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " + + Tables.LISTS + "." + Tasks.LIST_OWNER + ", " + Tables.LISTS + "." + Tasks.LIST_NAME + ", " + Tables.LISTS + + "." + Tasks.LIST_ACCESS_LEVEL + ", " + Tables.LISTS + "." + Tasks.LIST_COLOR + ", " + Tables.LISTS + "." + + Tasks.VISIBLE + " FROM " + Tables.TASKS + " JOIN " + Tables.LISTS + " ON (" + Tables.TASKS + "." + + TaskContract.Tasks.LIST_ID + "=" + Tables.LISTS + "." + TaskContract.Tasks._ID + ")" + " JOIN " + + Tables.INSTANCES + " ON (" + Tables.TASKS + "." + TaskContract.Tasks._ID + "=" + Tables.INSTANCES + "." + + TaskContract.Instances.TASK_ID + ")" + " LEFT JOIN " + Tables.PROPERTIES + " ON (" + Tables.TASKS + "." + + Tasks._ID + "=" + Tables.PROPERTIES + "." + Properties.TASK_ID + ");"; + + /** + * SQL command to create a view that combines task instances with some data from + * the list they belong to. + */ + private static final String SQL_CREATE_INSTANCE_CATEGORY_VIEW = "CREATE VIEW " + Tables.INSTANCE_CATEGORY_VIEW + + " AS SELECT " + Tables.INSTANCES + ".*, " + Tables.CATEGORIES_MAPPING + "." + + CategoriesMapping.CATEGORY_ID + ", " + Tables.TASKS + ".*, " + Tables.LISTS + "." + Tasks.ACCOUNT_NAME + + ", " + Tables.LISTS + "." + Tasks.ACCOUNT_TYPE + ", " + Tables.LISTS + "." + Tasks.LIST_OWNER + ", " + + Tables.LISTS + "." + Tasks.LIST_NAME + ", " + Tables.LISTS + "." + Tasks.LIST_ACCESS_LEVEL + ", " + + Tables.LISTS + "." + Tasks.LIST_COLOR + ", " + Tables.LISTS + "." + Tasks.VISIBLE + " FROM " + + Tables.TASKS + " JOIN " + Tables.LISTS + " ON (" + Tables.TASKS + "." + TaskContract.Tasks.LIST_ID + "=" + + Tables.LISTS + "." + TaskContract.Tasks._ID + ")" + " JOIN " + Tables.INSTANCES + " ON (" + Tables.TASKS + + "." + TaskContract.Tasks._ID + "=" + Tables.INSTANCES + "." + TaskContract.Instances.TASK_ID + ")" + + " LEFT JOIN " + Tables.CATEGORIES_MAPPING + " ON (" + Tables.CATEGORIES_MAPPING + "." + + CategoriesMapping.TASK_ID + "=" + Tables.INSTANCES + "." + TaskContract.Instances.TASK_ID + ");"; + + /** SQL command to drop the instance view. */ + private static final String SQL_DROP_INSTANCE_VIEW = "DROP VIEW " + Tables.INSTANCE_VIEW + ";"; + + /** SQL command to drop the instance property view. */ + // private final static String SQL_DROP_INSTANCE_PROPERTY_VIEW = "DROP VIEW " + + // Tables.INSTANCE_PROPERTY_VIEW + ";"; + + /** SQL command to create the instances table. */ + private static final String SQL_CREATE_SYNCSTATE_TABLE = "CREATE TABLE " + Tables.SYNCSTATE + " ( " + + TaskContract.SyncState._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + TaskContract.SyncState.ACCOUNT_NAME + + " TEXT, " + TaskContract.SyncState.ACCOUNT_TYPE + " TEXT, " + TaskContract.SyncState.DATA + " TEXT " + + ");"; + + /** SQL command to create the instances table. */ + private static final String SQL_CREATE_INSTANCES_TABLE = "CREATE TABLE " + Tables.INSTANCES + " ( " + + TaskContract.Instances._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + TaskContract.Instances.TASK_ID + + " INTEGER NOT NULL, " // NOT NULL + + TaskContract.Instances.INSTANCE_START + " INTEGER, " + TaskContract.Instances.INSTANCE_DUE + " INTEGER, " + + TaskContract.Instances.INSTANCE_START_SORTING + " INTEGER, " + TaskContract.Instances.INSTANCE_DUE_SORTING + + " INTEGER, " + TaskContract.Instances.INSTANCE_DURATION + " INTEGER, " + + TaskContract.Instances.INSTANCE_ORIGINAL_TIME + " INTEGER DEFAULT 0, " + + TaskContract.Instances.DISTANCE_FROM_CURRENT + " INTEGER DEFAULT 0);"; + + /** SQL command to create a trigger to clean up data of removed tasks. */ + private static final String SQL_CREATE_TASKS_CLEANUP_TRIGGER = "CREATE TRIGGER task_cleanup_trigger AFTER DELETE ON " + + Tables.TASKS + " BEGIN " + " DELETE FROM " + Tables.PROPERTIES + " WHERE " + + TaskContract.Properties.TASK_ID + "= old." + TaskContract.Tasks._ID + ";" + " DELETE FROM " + + Tables.INSTANCES + " WHERE " + TaskContract.Instances.TASK_ID + "=old." + TaskContract.Tasks._ID + ";" + + " END;"; + + /** SQL command to create a trigger to clean up data of removed lists. */ + private static final String SQL_CREATE_LISTS_CLEANUP_TRIGGER = "CREATE TRIGGER list_cleanup_trigger AFTER DELETE ON " + + Tables.LISTS + " BEGIN " + " DELETE FROM " + Tables.TASKS + " WHERE " + Tasks.LIST_ID + "= old." + + TaskLists._ID + ";" + " END;"; + + /** SQL command to drop the clean up trigger. */ + private static final String SQL_DROP_TASKS_CLEANUP_TRIGGER = "DROP TRIGGER task_cleanup_trigger;"; + + /** SQL command that counts and sets the alarm on deletion */ + private static final String SQL_COUNT_ALARMS_ON_DELETE = " BEGIN UPDATE " + Tables.TASKS + " SET " + + Tasks.HAS_ALARMS + " = (SELECT COUNT (*) FROM " + Tables.PROPERTIES + " WHERE " + Properties.MIMETYPE + + " = '" + Alarm.CONTENT_ITEM_TYPE + "' AND " + Alarm.ALARM_TYPE + " <> " + Alarm.ALARM_TYPE_NOTHING + + " AND " + Properties.TASK_ID + " = OLD." + Properties.TASK_ID + ") WHERE " + Tasks._ID + " = OLD." + + Properties.TASK_ID + "; END;"; + + /** SQL command that counts and sets the alarm on insert and update */ + private static final String SQL_COUNT_ALARMS = " BEGIN UPDATE " + Tables.TASKS + " SET " + Tasks.HAS_ALARMS + + " = (SELECT COUNT (*) FROM " + Tables.PROPERTIES + " WHERE " + Properties.MIMETYPE + " = '" + + Alarm.CONTENT_ITEM_TYPE + "' AND " + Alarm.ALARM_TYPE + " <> " + Alarm.ALARM_TYPE_NOTHING + " AND " + + Properties.TASK_ID + " = NEW." + Properties.TASK_ID + ") WHERE " + Tasks._ID + " = NEW." + + Properties.TASK_ID + "; END;"; /** * SQL command to create a trigger that counts the alarms for a task on create */ - private final static String SQL_CREATE_ALARM_COUNT_CREATE_TRIGGER = - "CREATE TRIGGER alarm_count_create_trigger AFTER INSERT ON " + Tables.PROPERTIES + " WHEN NEW." + Properties.MIMETYPE + " = '" + Alarm.CONTENT_ITEM_TYPE + "'" - + SQL_COUNT_ALARMS; + private static final String SQL_CREATE_ALARM_COUNT_CREATE_TRIGGER = "CREATE TRIGGER alarm_count_create_trigger AFTER INSERT ON " + + Tables.PROPERTIES + " WHEN NEW." + Properties.MIMETYPE + " = '" + Alarm.CONTENT_ITEM_TYPE + "'" + + SQL_COUNT_ALARMS; /** * SQL command to create a trigger that counts the alarms for a task on update */ - private final static String SQL_CREATE_ALARM_COUNT_UPDATE_TRIGGER = - "CREATE TRIGGER alarm_count_update_trigger AFTER UPDATE ON " + Tables.PROPERTIES + " WHEN NEW." + Properties.MIMETYPE + " = '" + Alarm.CONTENT_ITEM_TYPE + "'" - + SQL_COUNT_ALARMS; + private static final String SQL_CREATE_ALARM_COUNT_UPDATE_TRIGGER = "CREATE TRIGGER alarm_count_update_trigger AFTER UPDATE ON " + + Tables.PROPERTIES + " WHEN NEW." + Properties.MIMETYPE + " = '" + Alarm.CONTENT_ITEM_TYPE + "'" + + SQL_COUNT_ALARMS; /** * SQL command to create a trigger that counts the alarms for a task on delete */ - private final static String SQL_CREATE_ALARM_COUNT_DELETE_TRIGGER = - "CREATE TRIGGER alarm_count_delete_trigger AFTER DELETE ON " + Tables.PROPERTIES + " WHEN OLD." + Properties.MIMETYPE + " = '" + Alarm.CONTENT_ITEM_TYPE + "'" - + SQL_COUNT_ALARMS_ON_DELETE; + private static final String SQL_CREATE_ALARM_COUNT_DELETE_TRIGGER = "CREATE TRIGGER alarm_count_delete_trigger AFTER DELETE ON " + + Tables.PROPERTIES + " WHEN OLD." + Properties.MIMETYPE + " = '" + Alarm.CONTENT_ITEM_TYPE + "'" + + SQL_COUNT_ALARMS_ON_DELETE; - /** - * SQL command to create a trigger to clean up data of removed property. - */ - private final static String SQL_CREATE_ALARM_PROPERTY_CLEANUP_TRIGGER = - "CREATE TRIGGER alarm_property_cleanup_trigger AFTER DELETE ON " + Tables.PROPERTIES + " WHEN OLD." + Properties.MIMETYPE + " = '" + Alarm.CONTENT_ITEM_TYPE + "'" - + " BEGIN " - + " DELETE FROM " + Tables.ALARMS + " WHERE " + TaskContract.Alarms.ALARM_ID + "= OLD." + TaskContract.Properties.PROPERTY_ID + ";" - + " END;"; + /** SQL command to create a trigger to clean up data of removed property. */ + private static final String SQL_CREATE_ALARM_PROPERTY_CLEANUP_TRIGGER = "CREATE TRIGGER alarm_property_cleanup_trigger AFTER DELETE ON " + + Tables.PROPERTIES + " WHEN OLD." + Properties.MIMETYPE + " = '" + Alarm.CONTENT_ITEM_TYPE + "'" + + " BEGIN " + " DELETE FROM " + Tables.ALARMS + " WHERE " + TaskContract.Alarms.ALARM_ID + "= OLD." + + TaskContract.Properties.PROPERTY_ID + ";" + " END;"; - /** - * SQL command to create a trigger to clean up data of removed property. - */ - private final static String SQL_CREATE_CATEGORY_PROPERTY_CLEANUP_TRIGGER = - "CREATE TRIGGER category_property_cleanup_trigger AFTER DELETE ON " + Tables.PROPERTIES + " WHEN OLD." + Properties.MIMETYPE + " = '" + Category.CONTENT_ITEM_TYPE + "'" - + " BEGIN " - + " DELETE FROM " + Tables.CATEGORIES_MAPPING + " WHERE " + CategoriesMapping.PROPERTY_ID + "= OLD." + TaskContract.Properties.PROPERTY_ID + ";" - + " END;"; + /** SQL command to create a trigger to clean up data of removed property. */ + private static final String SQL_CREATE_CATEGORY_PROPERTY_CLEANUP_TRIGGER = "CREATE TRIGGER category_property_cleanup_trigger AFTER DELETE ON " + + Tables.PROPERTIES + " WHEN OLD." + Properties.MIMETYPE + " = '" + Category.CONTENT_ITEM_TYPE + "'" + + " BEGIN " + " DELETE FROM " + Tables.CATEGORIES_MAPPING + " WHERE " + CategoriesMapping.PROPERTY_ID + + "= OLD." + TaskContract.Properties.PROPERTY_ID + ";" + " END;"; /** * SQL command to create a trigger to clean up property data of removed task. */ - private final static String SQL_CREATE_TASK_PROPERTY_CLEANUP_TRIGGER = - "CREATE TRIGGER task_property_cleanup_trigger AFTER DELETE ON " + Tables.TASKS + " BEGIN " - + " DELETE FROM " + Tables.PROPERTIES + " WHERE " + Properties.TASK_ID + "= OLD." + Tasks._ID + ";" - + " END;"; - - /** - * SQL command to create a trigger to increment task version number on every update. - */ - private final static String SQL_CREATE_TASK_VERSION_TRIGGER = - "CREATE TRIGGER task_version_trigger BEFORE UPDATE ON " + Tables.TASKS + " BEGIN " - + " UPDATE " + Tables.TASKS + " SET " + Tasks.VERSION + " = OLD." + Tasks.VERSION + " + 1 where " + Tasks._ID + " = NEW." + Tasks._ID + ";" - + " END;"; - - /** - * SQL command to create the task list table. - */ - private final static String SQL_CREATE_LISTS_TABLE = - "CREATE TABLE " + Tables.LISTS + " ( " - + TaskContract.TaskLists._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," - + TaskContract.TaskLists.ACCOUNT_NAME + " TEXT," - + TaskContract.TaskLists.ACCOUNT_TYPE + " TEXT," - + TaskContract.TaskLists.LIST_NAME + " TEXT," - + TaskContract.TaskLists.LIST_COLOR + " INTEGER," - + TaskContract.TaskLists.ACCESS_LEVEL + " INTEGER," - + TaskContract.TaskLists.VISIBLE + " INTEGER," - + TaskContract.TaskLists.SYNC_ENABLED + " INTEGER," - + TaskContract.TaskLists.OWNER + " TEXT," - + TaskContract.TaskLists._DIRTY + " INTEGER DEFAULT 0," - + TaskContract.TaskLists._SYNC_ID + " TEXT," - + TaskContract.TaskLists.SYNC_VERSION + " TEXT," - + TaskContract.TaskLists.SYNC1 + " TEXT," - + TaskContract.TaskLists.SYNC2 + " TEXT," - + TaskContract.TaskLists.SYNC3 + " TEXT," - + TaskContract.TaskLists.SYNC4 + " TEXT," - + TaskContract.TaskLists.SYNC5 + " TEXT," - + TaskContract.TaskLists.SYNC6 + " TEXT," - + TaskContract.TaskLists.SYNC7 + " TEXT," - + TaskContract.TaskLists.SYNC8 + " TEXT);"; - - /** - * SQL command to create the task table. - */ - private final static String SQL_CREATE_TASKS_TABLE = - "CREATE TABLE " + Tables.TASKS + " ( " - + TaskContract.Tasks._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," - + TaskContract.Tasks.VERSION + " INTEGER DEFAULT 0," - + TaskContract.Tasks.LIST_ID + " INTEGER NOT NULL, " - + TaskContract.Tasks.TITLE + " TEXT," - + TaskContract.Tasks.LOCATION + " TEXT," - + TaskContract.Tasks.GEO + " TEXT," - + TaskContract.Tasks.DESCRIPTION + " TEXT," - + TaskContract.Tasks.URL + " TEXT," - + TaskContract.Tasks.ORGANIZER + " TEXT," - + TaskContract.Tasks.PRIORITY + " INTEGER, " - + TaskContract.Tasks.TASK_COLOR + " INTEGER," - + TaskContract.Tasks.CLASSIFICATION + " INTEGER," - + TaskContract.Tasks.COMPLETED + " INTEGER," - + TaskContract.Tasks.COMPLETED_IS_ALLDAY + " INTEGER," - + TaskContract.Tasks.PERCENT_COMPLETE + " INTEGER," - + TaskContract.Tasks.STATUS + " INTEGER DEFAULT " + TaskContract.Tasks.STATUS_DEFAULT + "," - + TaskContract.Tasks.IS_NEW + " INTEGER," - + TaskContract.Tasks.IS_CLOSED + " INTEGER," - + TaskContract.Tasks.DTSTART + " INTEGER," - + TaskContract.Tasks.CREATED + " INTEGER," - + TaskContract.Tasks.LAST_MODIFIED + " INTEGER," - + TaskContract.Tasks.IS_ALLDAY + " INTEGER," - + TaskContract.Tasks.TZ + " TEXT," - + TaskContract.Tasks.DUE + " INTEGER," - + TaskContract.Tasks.DURATION + " TEXT," - + TaskContract.Tasks.RDATE + " TEXT," - + TaskContract.Tasks.EXDATE + " TEXT," - + TaskContract.Tasks.RRULE + " TEXT," - + TaskContract.Tasks.PARENT_ID + " INTEGER," - + TaskContract.Tasks.SORTING + " TEXT," - + TaskContract.Tasks.HAS_ALARMS + " INTEGER," - + TaskContract.Tasks.HAS_PROPERTIES + " INTEGER," - + TaskContract.Tasks.PINNED + " INTEGER," - + TaskContract.Tasks.ORIGINAL_INSTANCE_SYNC_ID + " TEXT," - + TaskContract.Tasks.ORIGINAL_INSTANCE_ID + " INTEGER," - + TaskContract.Tasks.ORIGINAL_INSTANCE_TIME + " INTEGER," - + TaskContract.Tasks.ORIGINAL_INSTANCE_ALLDAY + " INTEGER," - + TaskContract.Tasks._DIRTY + " INTEGER DEFAULT 1," // a new task is always dirty - + TaskContract.Tasks._DELETED + " INTEGER DEFAULT 0," // new tasks are not deleted by default - + TaskContract.Tasks._SYNC_ID + " TEXT," - + TaskContract.Tasks._UID + " TEXT," - + TaskContract.Tasks.SYNC_VERSION + " TEXT," - + TaskContract.Tasks.SYNC1 + " TEXT," - + TaskContract.Tasks.SYNC2 + " TEXT," - + TaskContract.Tasks.SYNC3 + " TEXT," - + TaskContract.Tasks.SYNC4 + " TEXT," - + TaskContract.Tasks.SYNC5 + " TEXT," - + TaskContract.Tasks.SYNC6 + " TEXT," - + TaskContract.Tasks.SYNC7 + " TEXT," - + TaskContract.Tasks.SYNC8 + " TEXT);"; - - /** - * SQL command to create the categories table. - */ - private final static String SQL_CREATE_CATEGORIES_TABLE = - "CREATE TABLE " + Tables.CATEGORIES - + " ( " + TaskContract.Categories._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," - + TaskContract.Categories.ACCOUNT_NAME + " TEXT," - + TaskContract.Categories.ACCOUNT_TYPE + " TEXT," - + TaskContract.Categories.NAME + " TEXT," - + TaskContract.Categories.COLOR + " INTEGER);"; - - /** - * SQL command to create the categories table. - */ - private final static String SQL_CREATE_CATEGORIES_MAPPING_TABLE = - "CREATE TABLE " + Tables.CATEGORIES_MAPPING - + " ( " + CategoriesMapping.TASK_ID + " INTEGER," - + CategoriesMapping.CATEGORY_ID + " INTEGER," - + CategoriesMapping.PROPERTY_ID + " INTEGER," - + "FOREIGN KEY (" + CategoriesMapping.TASK_ID + ") REFERENCES " + Tables.TASKS + "(" + TaskContract.Tasks._ID + ")," - + "FOREIGN KEY (" + CategoriesMapping.PROPERTY_ID + ") REFERENCES " + Tables.PROPERTIES + "(" + TaskContract.Properties.PROPERTY_ID + ")," - + "FOREIGN KEY (" + CategoriesMapping.CATEGORY_ID + ") REFERENCES " + Tables.CATEGORIES + "(" + TaskContract.Categories._ID + "));"; - - /** - * SQL command to create the alarms table the stores the already triggered alarms. - */ - private final static String SQL_CREATE_ALARMS_TABLE = - "CREATE TABLE " + Tables.ALARMS - + " ( " + TaskContract.Alarms.ALARM_ID + " INTEGER," - + TaskContract.Alarms.LAST_TRIGGER + " TEXT," - + TaskContract.Alarms.NEXT_TRIGGER + " TEXT);"; - - /** - * SQL command to create the table for extended properties. - */ - private final static String SQL_CREATE_PROPERTIES_TABLE = - "CREATE TABLE " + Tables.PROPERTIES + " ( " - + TaskContract.Properties.PROPERTY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," - + TaskContract.Properties.TASK_ID + " INTEGER," - + TaskContract.Properties.MIMETYPE + " INTEGER," - + TaskContract.Properties.VERSION + " INTEGER," - + TaskContract.Properties.DATA0 + " TEXT," - + TaskContract.Properties.DATA1 + " TEXT," - + TaskContract.Properties.DATA2 + " TEXT," - + TaskContract.Properties.DATA3 + " TEXT," - + TaskContract.Properties.DATA4 + " TEXT," - + TaskContract.Properties.DATA5 + " TEXT," - + TaskContract.Properties.DATA6 + " TEXT," - + TaskContract.Properties.DATA7 + " TEXT," - + TaskContract.Properties.DATA8 + " TEXT," - + TaskContract.Properties.DATA9 + " TEXT," - + TaskContract.Properties.DATA10 + " TEXT," - + TaskContract.Properties.DATA11 + " TEXT," - + TaskContract.Properties.DATA12 + " TEXT," - + TaskContract.Properties.DATA13 + " TEXT," - + TaskContract.Properties.DATA14 + " TEXT," - + TaskContract.Properties.DATA15 + " TEXT," - + TaskContract.Properties.SYNC1 + " TEXT," - + TaskContract.Properties.SYNC2 + " TEXT," - + TaskContract.Properties.SYNC3 + " TEXT," - + TaskContract.Properties.SYNC4 + " TEXT," - + TaskContract.Properties.SYNC5 + " TEXT," - + TaskContract.Properties.SYNC6 + " TEXT," - + TaskContract.Properties.SYNC7 + " TEXT," - + TaskContract.Properties.SYNC8 + " TEXT);"; - - /** - * SQL command to drop the task view. - */ - private final static String SQL_DROP_PROPERTIES_TABLE = "DROP TABLE " + Tables.PROPERTIES + ";"; - - - /** - * Builds a string that creates an index on the given table for the given columns. + private static final String SQL_CREATE_TASK_PROPERTY_CLEANUP_TRIGGER = "CREATE TRIGGER task_property_cleanup_trigger AFTER DELETE ON " + + Tables.TASKS + " BEGIN " + " DELETE FROM " + Tables.PROPERTIES + " WHERE " + Properties.TASK_ID + "= OLD." + + Tasks._ID + ";" + " END;"; + + /** + * SQL command to create a trigger to increment task version number on every + * update. + */ + private static final String SQL_CREATE_TASK_VERSION_TRIGGER = "CREATE TRIGGER task_version_trigger BEFORE UPDATE ON " + + Tables.TASKS + " BEGIN " + " UPDATE " + Tables.TASKS + " SET " + Tasks.VERSION + " = OLD." + Tasks.VERSION + + " + 1 where " + Tasks._ID + " = NEW." + Tasks._ID + ";" + " END;"; + + /** SQL command to create the task list table. */ + private static final String SQL_CREATE_LISTS_TABLE = "CREATE TABLE " + Tables.LISTS + " ( " + + TaskContract.TaskLists._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + TaskContract.TaskLists.ACCOUNT_NAME + + " TEXT," + TaskContract.TaskLists.ACCOUNT_TYPE + " TEXT," + TaskContract.TaskLists.LIST_NAME + " TEXT," + + TaskContract.TaskLists.LIST_COLOR + " INTEGER," + TaskContract.TaskLists.ACCESS_LEVEL + " INTEGER," + + TaskContract.TaskLists.VISIBLE + " INTEGER," + TaskContract.TaskLists.SYNC_ENABLED + " INTEGER," + + TaskContract.TaskLists.OWNER + " TEXT," + TaskContract.TaskLists._DIRTY + " INTEGER DEFAULT 0," + + TaskContract.TaskLists._SYNC_ID + " TEXT," + TaskContract.TaskLists.SYNC_VERSION + " TEXT," + + TaskContract.TaskLists.SYNC1 + " TEXT," + TaskContract.TaskLists.SYNC2 + " TEXT," + + TaskContract.TaskLists.SYNC3 + " TEXT," + TaskContract.TaskLists.SYNC4 + " TEXT," + + TaskContract.TaskLists.SYNC5 + " TEXT," + TaskContract.TaskLists.SYNC6 + " TEXT," + + TaskContract.TaskLists.SYNC7 + " TEXT," + TaskContract.TaskLists.SYNC8 + " TEXT);"; + + /** SQL command to create the task table. */ + private static final String SQL_CREATE_TASKS_TABLE = "CREATE TABLE " + Tables.TASKS + " ( " + TaskContract.Tasks._ID + + " INTEGER PRIMARY KEY AUTOINCREMENT," + TaskContract.Tasks.VERSION + " INTEGER DEFAULT 0," + + TaskContract.Tasks.LIST_ID + " INTEGER NOT NULL, " + TaskContract.Tasks.TITLE + " TEXT," + + TaskContract.Tasks.LOCATION + " TEXT," + TaskContract.Tasks.GEO + " TEXT," + + TaskContract.Tasks.DESCRIPTION + " TEXT," + TaskContract.Tasks.URL + " TEXT," + + TaskContract.Tasks.ORGANIZER + " TEXT," + TaskContract.Tasks.PRIORITY + " INTEGER, " + + TaskContract.Tasks.TASK_COLOR + " INTEGER," + TaskContract.Tasks.CLASSIFICATION + " INTEGER," + + TaskContract.Tasks.COMPLETED + " INTEGER," + TaskContract.Tasks.COMPLETED_IS_ALLDAY + " INTEGER," + + TaskContract.Tasks.PERCENT_COMPLETE + " INTEGER," + TaskContract.Tasks.STATUS + " INTEGER DEFAULT " + + TaskContract.Tasks.STATUS_DEFAULT + "," + TaskContract.Tasks.IS_NEW + " INTEGER," + + TaskContract.Tasks.IS_CLOSED + " INTEGER," + TaskContract.Tasks.DTSTART + " INTEGER," + + TaskContract.Tasks.CREATED + " INTEGER," + TaskContract.Tasks.LAST_MODIFIED + " INTEGER," + + TaskContract.Tasks.IS_ALLDAY + " INTEGER," + TaskContract.Tasks.TZ + " TEXT," + TaskContract.Tasks.DUE + + " INTEGER," + TaskContract.Tasks.DURATION + " TEXT," + TaskContract.Tasks.RDATE + " TEXT," + + TaskContract.Tasks.EXDATE + " TEXT," + TaskContract.Tasks.RRULE + " TEXT," + TaskContract.Tasks.PARENT_ID + + " INTEGER," + TaskContract.Tasks.SORTING + " TEXT," + TaskContract.Tasks.HAS_ALARMS + " INTEGER," + + TaskContract.Tasks.HAS_PROPERTIES + " INTEGER," + TaskContract.Tasks.PINNED + " INTEGER," + + TaskContract.Tasks.ORIGINAL_INSTANCE_SYNC_ID + " TEXT," + TaskContract.Tasks.ORIGINAL_INSTANCE_ID + + " INTEGER," + TaskContract.Tasks.ORIGINAL_INSTANCE_TIME + " INTEGER," + + TaskContract.Tasks.ORIGINAL_INSTANCE_ALLDAY + " INTEGER," + TaskContract.Tasks._DIRTY + + " INTEGER DEFAULT 1," // a new task is always dirty + + TaskContract.Tasks._DELETED + " INTEGER DEFAULT 0," // new tasks are not deleted by default + + TaskContract.Tasks._SYNC_ID + " TEXT," + TaskContract.Tasks._UID + " TEXT," + + TaskContract.Tasks.SYNC_VERSION + " TEXT," + TaskContract.Tasks.SYNC1 + " TEXT," + + TaskContract.Tasks.SYNC2 + " TEXT," + TaskContract.Tasks.SYNC3 + " TEXT," + TaskContract.Tasks.SYNC4 + + " TEXT," + TaskContract.Tasks.SYNC5 + " TEXT," + TaskContract.Tasks.SYNC6 + " TEXT," + + TaskContract.Tasks.SYNC7 + " TEXT," + TaskContract.Tasks.SYNC8 + " TEXT);"; + + /** SQL command to create the categories table. */ + private static final String SQL_CREATE_CATEGORIES_TABLE = "CREATE TABLE " + Tables.CATEGORIES + " ( " + + TaskContract.Categories._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + TaskContract.Categories.ACCOUNT_NAME + + " TEXT," + TaskContract.Categories.ACCOUNT_TYPE + " TEXT," + TaskContract.Categories.NAME + " TEXT," + + TaskContract.Categories.COLOR + " INTEGER);"; + + /** SQL command to create the categories table. */ + private static final String SQL_CREATE_CATEGORIES_MAPPING_TABLE = "CREATE TABLE " + Tables.CATEGORIES_MAPPING + + " ( " + CategoriesMapping.TASK_ID + " INTEGER," + CategoriesMapping.CATEGORY_ID + " INTEGER," + + CategoriesMapping.PROPERTY_ID + " INTEGER," + "FOREIGN KEY (" + CategoriesMapping.TASK_ID + + ") REFERENCES " + Tables.TASKS + "(" + TaskContract.Tasks._ID + ")," + "FOREIGN KEY (" + + CategoriesMapping.PROPERTY_ID + ") REFERENCES " + Tables.PROPERTIES + "(" + + TaskContract.Properties.PROPERTY_ID + ")," + "FOREIGN KEY (" + CategoriesMapping.CATEGORY_ID + + ") REFERENCES " + Tables.CATEGORIES + "(" + TaskContract.Categories._ID + "));"; + + /** + * SQL command to create the alarms table the stores the already triggered + * alarms. + */ + private static final String SQL_CREATE_ALARMS_TABLE = "CREATE TABLE " + Tables.ALARMS + " ( " + + TaskContract.Alarms.ALARM_ID + " INTEGER," + TaskContract.Alarms.LAST_TRIGGER + " TEXT," + + TaskContract.Alarms.NEXT_TRIGGER + " TEXT);"; + + /** SQL command to create the table for extended properties. */ + private static final String SQL_CREATE_PROPERTIES_TABLE = "CREATE TABLE " + Tables.PROPERTIES + " ( " + + TaskContract.Properties.PROPERTY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + + TaskContract.Properties.TASK_ID + " INTEGER," + TaskContract.Properties.MIMETYPE + " INTEGER," + + TaskContract.Properties.VERSION + " INTEGER," + TaskContract.Properties.DATA0 + " TEXT," + + TaskContract.Properties.DATA1 + " TEXT," + TaskContract.Properties.DATA2 + " TEXT," + + TaskContract.Properties.DATA3 + " TEXT," + TaskContract.Properties.DATA4 + " TEXT," + + TaskContract.Properties.DATA5 + " TEXT," + TaskContract.Properties.DATA6 + " TEXT," + + TaskContract.Properties.DATA7 + " TEXT," + TaskContract.Properties.DATA8 + " TEXT," + + TaskContract.Properties.DATA9 + " TEXT," + TaskContract.Properties.DATA10 + " TEXT," + + TaskContract.Properties.DATA11 + " TEXT," + TaskContract.Properties.DATA12 + " TEXT," + + TaskContract.Properties.DATA13 + " TEXT," + TaskContract.Properties.DATA14 + " TEXT," + + TaskContract.Properties.DATA15 + " TEXT," + TaskContract.Properties.SYNC1 + " TEXT," + + TaskContract.Properties.SYNC2 + " TEXT," + TaskContract.Properties.SYNC3 + " TEXT," + + TaskContract.Properties.SYNC4 + " TEXT," + TaskContract.Properties.SYNC5 + " TEXT," + + TaskContract.Properties.SYNC6 + " TEXT," + TaskContract.Properties.SYNC7 + " TEXT," + + TaskContract.Properties.SYNC8 + " TEXT);"; + + /** SQL command to drop the task view. */ + private static final String SQL_DROP_PROPERTIES_TABLE = "DROP TABLE " + Tables.PROPERTIES + ";"; + + /** + * Builds a string that creates an index on the given table for the given + * columns. * * @param table - * The table to create the index on. + * The table to create the index on. * @param fields - * The fields to index. - * + * The fields to index. * @return An SQL command string. */ - public static String createIndexString(String table, boolean unique, String... fields) - { - if (fields == null || fields.length < 1) - { + public static String createIndexString(String table, boolean unique, String... fields) { + if (fields == null || fields.length < 1) { throw new IllegalArgumentException("need at least one field to build an index!"); } @@ -560,63 +415,61 @@ public class TaskDatabaseHelper extends SQLiteOpenHelper // Index name is constructed like this: tablename_fields[0]_idx buffer.append("CREATE "); - if (unique) - { + if (unique) { buffer.append(" UNIQUE "); } buffer.append("INDEX IF NOT EXISTS "); buffer.append(table).append("_").append(fields[0]).append("_idx ON "); buffer.append(table).append(" ("); buffer.append(fields[0]); - for (int i = 1; i < fields.length; i++) - { + for (int i = 1; i < fields.length; i++) { buffer.append(", ").append(fields[i]); } buffer.append(");"); return buffer.toString(); - } - private final OnDatabaseOperationListener mListener; - - TaskDatabaseHelper(Context context, OnDatabaseOperationListener listener) - { + TaskDatabaseHelper(Context context, OnDatabaseOperationListener listener) { super(context, DATABASE_NAME, null, DATABASE_VERSION); mListener = listener; } - /** * Creates the tables, views, triggers and indices. + * *

* TODO: move all strings to separate final static variables. */ @Override - public void onCreate(SQLiteDatabase db) - { + public void onCreate(SQLiteDatabase db) { // create task list table db.execSQL(SQL_CREATE_LISTS_TABLE); // trigger that removes tasks of a list that has been removed - db.execSQL("CREATE TRIGGER task_list_cleanup_trigger AFTER DELETE ON " + Tables.LISTS + " BEGIN DELETE FROM " + Tables.TASKS + " WHERE " - + TaskContract.Tasks.LIST_ID + "= old." + TaskContract.TaskLists._ID + "; END"); + db.execSQL("CREATE TRIGGER task_list_cleanup_trigger AFTER DELETE ON " + Tables.LISTS + " BEGIN DELETE FROM " + + Tables.TASKS + " WHERE " + TaskContract.Tasks.LIST_ID + "= old." + TaskContract.TaskLists._ID + + "; END"); // create task table db.execSQL(SQL_CREATE_TASKS_TABLE); - // trigger that marks a list as dirty if a task in that list gets marked as dirty or deleted - db.execSQL("CREATE TRIGGER task_list_make_dirty_on_update AFTER UPDATE ON " + Tables.TASKS + " BEGIN UPDATE " + Tables.LISTS + " SET " - + TaskContract.TaskLists._DIRTY + "=" + TaskContract.TaskLists._DIRTY + " + " + "new." + TaskContract.Tasks._DIRTY + " + " + "new." - + TaskContract.Tasks._DELETED + " WHERE " + TaskContract.TaskLists._ID + "= new." + TaskContract.Tasks.LIST_ID + "; END"); + // trigger that marks a list as dirty if a task in that list gets marked as + // dirty or deleted + db.execSQL("CREATE TRIGGER task_list_make_dirty_on_update AFTER UPDATE ON " + Tables.TASKS + " BEGIN UPDATE " + + Tables.LISTS + " SET " + TaskContract.TaskLists._DIRTY + "=" + TaskContract.TaskLists._DIRTY + " + " + + "new." + TaskContract.Tasks._DIRTY + " + " + "new." + TaskContract.Tasks._DELETED + " WHERE " + + TaskContract.TaskLists._ID + "= new." + TaskContract.Tasks.LIST_ID + "; END"); - // trigger that marks a list as dirty if a task in that list gets marked as dirty or deleted - db.execSQL("CREATE TRIGGER task_list_make_dirty_on_insert AFTER INSERT ON " + Tables.TASKS + " BEGIN UPDATE " + Tables.LISTS + " SET " - + TaskContract.TaskLists._DIRTY + "=" + TaskContract.TaskLists._DIRTY + " + " + "new." + TaskContract.Tasks._DIRTY + " + " + "new." - + TaskContract.Tasks._DELETED + " WHERE " + TaskContract.TaskLists._ID + "= new." + TaskContract.Tasks.LIST_ID + "; END"); + // trigger that marks a list as dirty if a task in that list gets marked as + // dirty or deleted + db.execSQL("CREATE TRIGGER task_list_make_dirty_on_insert AFTER INSERT ON " + Tables.TASKS + " BEGIN UPDATE " + + Tables.LISTS + " SET " + TaskContract.TaskLists._DIRTY + "=" + TaskContract.TaskLists._DIRTY + " + " + + "new." + TaskContract.Tasks._DIRTY + " + " + "new." + TaskContract.Tasks._DELETED + " WHERE " + + TaskContract.TaskLists._ID + "= new." + TaskContract.Tasks.LIST_ID + "; END"); // create task version update trigger db.execSQL(SQL_CREATE_TASK_VERSION_TRIGGER); @@ -648,20 +501,23 @@ public class TaskDatabaseHelper extends SQLiteOpenHelper db.execSQL(SQL_CREATE_INSTANCE_CATEGORY_VIEW); // create indices - db.execSQL(createIndexString(Tables.INSTANCES, false, TaskContract.Instances.TASK_ID, TaskContract.Instances.INSTANCE_START, - TaskContract.Instances.INSTANCE_DUE)); + db.execSQL(createIndexString(Tables.INSTANCES, false, TaskContract.Instances.TASK_ID, + TaskContract.Instances.INSTANCE_START, TaskContract.Instances.INSTANCE_DUE)); db.execSQL(createIndexString(Tables.INSTANCES, false, TaskContract.Instances.INSTANCE_START_SORTING)); db.execSQL(createIndexString(Tables.INSTANCES, false, TaskContract.Instances.INSTANCE_DUE_SORTING)); db.execSQL(createIndexString(Tables.INSTANCES, false, TaskContract.Instances.INSTANCE_ORIGINAL_TIME)); db.execSQL(createIndexString(Tables.LISTS, false, TaskContract.TaskLists.ACCOUNT_NAME, // not sure if necessary TaskContract.TaskLists.ACCOUNT_TYPE)); - db.execSQL(createIndexString(Tables.TASKS, false, TaskContract.Tasks.STATUS, TaskContract.Tasks.LIST_ID, TaskContract.Tasks._SYNC_ID)); - db.execSQL(createIndexString(Tables.PROPERTIES, false, TaskContract.Properties.MIMETYPE, TaskContract.Properties.TASK_ID)); + db.execSQL(createIndexString(Tables.TASKS, false, TaskContract.Tasks.STATUS, TaskContract.Tasks.LIST_ID, + TaskContract.Tasks._SYNC_ID)); + db.execSQL(createIndexString(Tables.PROPERTIES, false, TaskContract.Properties.MIMETYPE, + TaskContract.Properties.TASK_ID)); db.execSQL(createIndexString(Tables.PROPERTIES, false, TaskContract.Properties.TASK_ID)); - db.execSQL(createIndexString(Tables.CATEGORIES, false, TaskContract.Categories.ACCOUNT_NAME, TaskContract.Categories.ACCOUNT_TYPE, - TaskContract.Categories.NAME)); + db.execSQL(createIndexString(Tables.CATEGORIES, false, TaskContract.Categories.ACCOUNT_NAME, + TaskContract.Categories.ACCOUNT_TYPE, TaskContract.Categories.NAME)); db.execSQL(createIndexString(Tables.CATEGORIES, false, TaskContract.Categories.NAME)); - db.execSQL(createIndexString(Tables.SYNCSTATE, true, TaskContract.SyncState.ACCOUNT_NAME, TaskContract.SyncState.ACCOUNT_TYPE)); + db.execSQL(createIndexString(Tables.SYNCSTATE, true, TaskContract.SyncState.ACCOUNT_NAME, + TaskContract.SyncState.ACCOUNT_TYPE)); // trigger that removes properties of a task that has been removed db.execSQL(SQL_CREATE_TASKS_CLEANUP_TRIGGER); @@ -683,45 +539,40 @@ public class TaskDatabaseHelper extends SQLiteOpenHelper // initialize FTS FTSDatabaseHelper.onCreate(db); - if (mListener != null) - { + if (mListener != null) { mListener.onDatabaseCreated(db); } } - - /** - * Manages the database schema migration. - */ + /** Manages the database schema migration. */ @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) - { + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.i(TAG, "updgrading db from " + oldVersion + " to " + newVersion); - if (oldVersion < 2) - { + if (oldVersion < 2) { // add IS_NEW and IS_CLOSED columns and update their values db.execSQL("ALTER TABLE " + Tables.TASKS + " ADD COLUMN " + TaskContract.Tasks.IS_NEW + " INTEGER"); db.execSQL("ALTER TABLE " + Tables.TASKS + " ADD COLUMN " + TaskContract.Tasks.IS_CLOSED + " INTEGER"); - db.execSQL("UPDATE " + Tables.TASKS + " SET " + TaskContract.Tasks.IS_NEW + " = 1 WHERE " + TaskContract.Tasks.STATUS + " = " - + TaskContract.Tasks.STATUS_NEEDS_ACTION); - db.execSQL("UPDATE " + Tables.TASKS + " SET " + TaskContract.Tasks.IS_NEW + " = 0 WHERE " + TaskContract.Tasks.STATUS + " != " - + TaskContract.Tasks.STATUS_NEEDS_ACTION); - db.execSQL("UPDATE " + Tables.TASKS + " SET " + TaskContract.Tasks.IS_CLOSED + " = 1 WHERE " + TaskContract.Tasks.STATUS + " > " - + TaskContract.Tasks.STATUS_IN_PROCESS); - db.execSQL("UPDATE " + Tables.TASKS + " SET " + TaskContract.Tasks.IS_CLOSED + " = 0 WHERE " + TaskContract.Tasks.STATUS + " <= " - + TaskContract.Tasks.STATUS_IN_PROCESS); + db.execSQL("UPDATE " + Tables.TASKS + " SET " + TaskContract.Tasks.IS_NEW + " = 1 WHERE " + + TaskContract.Tasks.STATUS + " = " + TaskContract.Tasks.STATUS_NEEDS_ACTION); + db.execSQL("UPDATE " + Tables.TASKS + " SET " + TaskContract.Tasks.IS_NEW + " = 0 WHERE " + + TaskContract.Tasks.STATUS + " != " + TaskContract.Tasks.STATUS_NEEDS_ACTION); + db.execSQL("UPDATE " + Tables.TASKS + " SET " + TaskContract.Tasks.IS_CLOSED + " = 1 WHERE " + + TaskContract.Tasks.STATUS + " > " + TaskContract.Tasks.STATUS_IN_PROCESS); + db.execSQL("UPDATE " + Tables.TASKS + " SET " + TaskContract.Tasks.IS_CLOSED + " = 0 WHERE " + + TaskContract.Tasks.STATUS + " <= " + TaskContract.Tasks.STATUS_IN_PROCESS); } - if (oldVersion < 3) - { + if (oldVersion < 3) { // add instance sortings - db.execSQL("ALTER TABLE " + Tables.INSTANCES + " ADD COLUMN " + TaskContract.Instances.INSTANCE_START_SORTING + " INTEGER"); - db.execSQL("ALTER TABLE " + Tables.INSTANCES + " ADD COLUMN " + TaskContract.Instances.INSTANCE_DUE_SORTING + " INTEGER"); - db.execSQL("UPDATE " + Tables.INSTANCES + " SET " + TaskContract.Instances.INSTANCE_START_SORTING + " = " + TaskContract.Instances.INSTANCE_START - + ", " + TaskContract.Instances.INSTANCE_DUE_SORTING + " = " + TaskContract.Instances.INSTANCE_DUE); + db.execSQL("ALTER TABLE " + Tables.INSTANCES + " ADD COLUMN " + + TaskContract.Instances.INSTANCE_START_SORTING + " INTEGER"); + db.execSQL("ALTER TABLE " + Tables.INSTANCES + " ADD COLUMN " + TaskContract.Instances.INSTANCE_DUE_SORTING + + " INTEGER"); + db.execSQL("UPDATE " + Tables.INSTANCES + " SET " + TaskContract.Instances.INSTANCE_START_SORTING + " = " + + TaskContract.Instances.INSTANCE_START + ", " + TaskContract.Instances.INSTANCE_DUE_SORTING + " = " + + TaskContract.Instances.INSTANCE_DUE); } - if (oldVersion < 4) - { + if (oldVersion < 4) { // drop old view before altering the schema db.execSQL(SQL_DROP_TASK_VIEW); db.execSQL(SQL_DROP_INSTANCE_VIEW); @@ -746,10 +597,11 @@ public class TaskDatabaseHelper extends SQLiteOpenHelper db.execSQL(SQL_CREATE_INSTANCE_CATEGORY_VIEW); // create Indices - db.execSQL(createIndexString(Tables.PROPERTIES, false, TaskContract.Properties.MIMETYPE, TaskContract.Properties.TASK_ID)); + db.execSQL(createIndexString(Tables.PROPERTIES, false, TaskContract.Properties.MIMETYPE, + TaskContract.Properties.TASK_ID)); db.execSQL(createIndexString(Tables.PROPERTIES, false, TaskContract.Properties.TASK_ID)); - db.execSQL(createIndexString(Tables.CATEGORIES, false, TaskContract.Categories.ACCOUNT_NAME, TaskContract.Categories.ACCOUNT_TYPE, - TaskContract.Categories.NAME)); + db.execSQL(createIndexString(Tables.CATEGORIES, false, TaskContract.Categories.ACCOUNT_NAME, + TaskContract.Categories.ACCOUNT_TYPE, TaskContract.Categories.NAME)); db.execSQL(createIndexString(Tables.CATEGORIES, false, TaskContract.Categories.NAME)); // add new triggers @@ -757,112 +609,100 @@ public class TaskDatabaseHelper extends SQLiteOpenHelper db.execSQL(SQL_CREATE_ALARM_COUNT_CREATE_TRIGGER); db.execSQL(SQL_CREATE_ALARM_COUNT_UPDATE_TRIGGER); db.execSQL(SQL_CREATE_ALARM_COUNT_DELETE_TRIGGER); - } - if (oldVersion < 6) - { + if (oldVersion < 6) { db.execSQL("alter table " + Tables.TASKS + " add column " + Tasks.PARENT_ID + " integer;"); db.execSQL("alter table " + Tables.TASKS + " add column " + Tasks.HAS_ALARMS + " integer;"); db.execSQL("alter table " + Tables.TASKS + " add column " + Tasks.SORTING + " text;"); } - if (oldVersion < 7) - { + if (oldVersion < 7) { db.execSQL(SQL_CREATE_LISTS_CLEANUP_TRIGGER); } - if (oldVersion < 8) - { - // replace priority 0 by null. We need this to sort the widget properly. Since 0 is the default this is no problem when syncing. + if (oldVersion < 8) { + // replace priority 0 by null. We need this to sort the widget properly. Since 0 + // is the + // default this is no problem when syncing. db.execSQL("update " + Tables.TASKS + " set " + Tasks.PRIORITY + "=null where " + Tasks.PRIORITY + "=0;"); } - if (oldVersion < 9) - { + if (oldVersion < 9) { // add missing column _UID db.execSQL("alter table " + Tables.TASKS + " add column " + Tasks._UID + " integer;"); // add cleanup trigger for orphaned properties db.execSQL(SQL_CREATE_TASK_PROPERTY_CLEANUP_TRIGGER); } - if (oldVersion < 10) - { - // add property column to categories_mapping table. Since adding a constraint is not supported by SQLite we have to remove and recreate the entire + if (oldVersion < 10) { + // add property column to categories_mapping table. Since adding a constraint is + // not supported + // by SQLite we have to remove and recreate the entire // table db.execSQL("drop table " + Tables.CATEGORIES_MAPPING); db.execSQL(SQL_CREATE_CATEGORIES_MAPPING_TABLE); db.execSQL(SQL_CREATE_CATEGORY_PROPERTY_CLEANUP_TRIGGER); } - if (oldVersion < 11) - { + if (oldVersion < 11) { db.execSQL("alter table " + Tables.TASKS + " add column " + Tasks.PINNED + " integer;"); db.execSQL("alter table " + Tables.TASKS + " add column " + Tasks.HAS_PROPERTIES + " integer;"); } - if (oldVersion < 12) - { + if (oldVersion < 12) { // rename the local account type ContentValues values = new ContentValues(1); values.put(TaskLists.ACCOUNT_TYPE, TaskContract.LOCAL_ACCOUNT_TYPE); - db.update(Tables.LISTS, values, TaskLists.ACCOUNT_TYPE + "=?", new String[] { "LOCAL" }); + db.update(Tables.LISTS, values, TaskLists.ACCOUNT_TYPE + "=?", new String[]{"LOCAL"}); } - if (oldVersion < 13) - { + if (oldVersion < 13) { db.execSQL(SQL_CREATE_SYNCSTATE_TABLE); } - if (oldVersion < 14) - { - // create a unique index for account name and account type on the sync state table - db.execSQL(createIndexString(Tables.SYNCSTATE, true, TaskContract.SyncState.ACCOUNT_NAME, TaskContract.SyncState.ACCOUNT_TYPE)); + if (oldVersion < 14) { + // create a unique index for account name and account type on the sync state + // table + db.execSQL(createIndexString(Tables.SYNCSTATE, true, TaskContract.SyncState.ACCOUNT_NAME, + TaskContract.SyncState.ACCOUNT_TYPE)); } - if (oldVersion < 16) - { + if (oldVersion < 16) { db.execSQL(createIndexString(Tables.INSTANCES, false, TaskContract.Instances.INSTANCE_START_SORTING)); db.execSQL(createIndexString(Tables.INSTANCES, false, TaskContract.Instances.INSTANCE_DUE_SORTING)); } - if (oldVersion < 17) - { - db.execSQL("alter table " + Tables.INSTANCES + " add column " + TaskContract.Instances.INSTANCE_ORIGINAL_TIME + " integer default 0;"); + if (oldVersion < 17) { + db.execSQL("alter table " + Tables.INSTANCES + " add column " + + TaskContract.Instances.INSTANCE_ORIGINAL_TIME + " integer default 0;"); db.execSQL(createIndexString(Tables.INSTANCES, false, TaskContract.Instances.INSTANCE_ORIGINAL_TIME)); } - if (oldVersion < 18) - { - db.execSQL("alter table " + Tables.INSTANCES + " add column " + TaskContract.Instances.DISTANCE_FROM_CURRENT + " integer default 0;"); + if (oldVersion < 18) { + db.execSQL("alter table " + Tables.INSTANCES + " add column " + TaskContract.Instances.DISTANCE_FROM_CURRENT + + " integer default 0;"); } - if (oldVersion < 19) - { + if (oldVersion < 19) { db.execSQL(SQL_CREATE_INSTANCE_CLIENT_VIEW); } - if (oldVersion < 22) - { + if (oldVersion < 22) { // create version column, unless it already exists - if (!new First<>(new TableColumns(Tables.TASKS).value(db), new Equals<>(Tasks.VERSION)).isPresent()) - { + if (!new First<>(new TableColumns(Tables.TASKS).value(db), new Equals<>(Tasks.VERSION)).isPresent()) { // create task version column and update trigger db.execSQL("alter table " + Tables.TASKS + " add column " + Tasks.VERSION + " Integer default 0;"); db.execSQL(SQL_CREATE_TASK_VERSION_TRIGGER); } } - if (oldVersion < 22) - { + if (oldVersion < 22) { db.beginTransaction(); - try - { + try { // make sure we upgrade the instances of every recurring task EntityProcessor processor = new Instantiating(new NoOpProcessor<>()); try (Cursor c = db.query(Tables.TASKS, - new String[] { - TaskContract.Tasks._ID, Tasks.ORIGINAL_INSTANCE_ID, Tasks.DTSTART, Tasks.DUE, Tasks.DURATION, Tasks.IS_CLOSED, Tasks.TZ, - Tasks.IS_ALLDAY, Tasks.RRULE, Tasks.RDATE, Tasks.EXDATE, Tasks.ORIGINAL_INSTANCE_TIME, Tasks.ORIGINAL_INSTANCE_ALLDAY }, - String.format(Locale.ENGLISH, "%s is null", TaskContract.Tasks.ORIGINAL_INSTANCE_ID), - null, null, null, null)) - { - while (c.moveToNext()) - { + new String[]{TaskContract.Tasks._ID, Tasks.ORIGINAL_INSTANCE_ID, Tasks.DTSTART, Tasks.DUE, + Tasks.DURATION, Tasks.IS_CLOSED, Tasks.TZ, Tasks.IS_ALLDAY, Tasks.RRULE, Tasks.RDATE, + Tasks.EXDATE, Tasks.ORIGINAL_INSTANCE_TIME, Tasks.ORIGINAL_INSTANCE_ALLDAY}, + String.format(Locale.ENGLISH, "%s is null", TaskContract.Tasks.ORIGINAL_INSTANCE_ID), null, + null, null, null)) { + while (c.moveToNext()) { ContentValues values = new ContentValues(); Instantiating.addUpdateRequest(values); TaskAdapter adapter = new CursorContentValuesTaskAdapter(c, values); @@ -870,15 +710,12 @@ public class TaskDatabaseHelper extends SQLiteOpenHelper } } db.setTransactionSuccessful(); - } - finally - { + } finally { db.endTransaction(); } } - if (oldVersion < 23) - { + if (oldVersion < 23) { db.execSQL("drop view " + Tables.INSTANCE_CLIENT_VIEW + ";"); db.execSQL(SQL_CREATE_INSTANCE_CLIENT_VIEW); } @@ -886,10 +723,8 @@ public class TaskDatabaseHelper extends SQLiteOpenHelper // upgrade FTS FTSDatabaseHelper.onUpgrade(db, oldVersion, newVersion); - if (mListener != null) - { + if (mListener != null) { mListener.onDatabaseUpdate(db, oldVersion, newVersion); } } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProvider.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProvider.java index d78d9a3ad7cfefac1da77574ec637720e82c49ed..c729f06f86443b704a7f9e97bcf183e5f73c7002 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProvider.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProvider.java @@ -37,7 +37,12 @@ import android.os.Handler; import android.os.HandlerThread; import android.text.TextUtils; import android.util.Log; - +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import org.dmfs.iterables.EmptyIterable; import org.dmfs.provider.tasks.TaskDatabaseHelper.OnDatabaseOperationListener; import org.dmfs.provider.tasks.TaskDatabaseHelper.Tables; @@ -78,30 +83,28 @@ import org.dmfs.tasks.contract.TaskContract.TaskListSyncColumns; import org.dmfs.tasks.contract.TaskContract.TaskLists; import org.dmfs.tasks.contract.TaskContract.Tasks; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - - /** * The provider for tasks. + * *

* TODO: add support for recurring tasks + * *

* TODO: add support for reminders + * *

* TODO: add support for attendees + * *

* TODO: refactor the selection stuff * * @author Marten Gajda * @author Tobias Reinsch */ -public final class TaskProvider extends SQLiteContentProvider implements OnAccountsUpdateListener, OnDatabaseOperationListener -{ +public final class TaskProvider extends SQLiteContentProvider + implements + OnAccountsUpdateListener, + OnDatabaseOperationListener { private static final int LISTS = 1; private static final int LIST_ID = 2; @@ -121,73 +124,72 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou private static final int OPERATIONS = 100000; - private final static Set TASK_LIST_SYNC_COLUMNS = new HashSet(Arrays.asList(TaskLists.SYNC_ADAPTER_COLUMNS)); + private static final Set TASK_LIST_SYNC_COLUMNS = new HashSet( + Arrays.asList(TaskLists.SYNC_ADAPTER_COLUMNS)); private static final String TAG = "TaskProvider"; /** - * A list of {@link EntityProcessor}s to execute when doing operations on the instances table. + * A list of {@link EntityProcessor}s to execute when doing operations on the + * instances table. */ private EntityProcessor mInstanceProcessorChain; /** - * A list of {@link EntityProcessor}s to execute when doing operations on the tasks table. + * A list of {@link EntityProcessor}s to execute when doing operations on the + * tasks table. */ private EntityProcessor mTaskProcessorChain; /** - * A list of {@link EntityProcessor}s to execute when doing operations on the task lists table. + * A list of {@link EntityProcessor}s to execute when doing operations on the + * task lists table. */ private EntityProcessor mListProcessorChain; - /** - * Our authority. - */ + /** Our authority. */ String mAuthority; - /** - * The {@link UriMatcher} we use. - */ + /** The {@link UriMatcher} we use. */ private UriMatcher mUriMatcher; - /** - * A handler to execute asynchronous jobs. - */ + /** A handler to execute asynchronous jobs. */ Handler mAsyncHandler; /** * Boolean to track if there are changes within a transaction. + * *

* This can be shared by multiple threads, hence the {@link AtomicBoolean}. */ private AtomicBoolean mChanged = new AtomicBoolean(false); /** - * This is a per transaction/thread flag which indicates whether new lists with an unknown account have been added. - * If this holds true at the end of a transaction a window should be shown to ask the user for access to that account. + * This is a per transaction/thread flag which indicates whether new lists with + * an unknown account have been added. If this holds true at the end of a + * transaction a window should be shown to ask the user for access to that + * account. */ private ThreadLocal mStaleListCreated = new ThreadLocal<>(); /** - * The currently known accounts. This may be accessed from various threads, hence the AtomicReference. - * By statring with an empty set, we can always guarantee a non-null reference. + * The currently known accounts. This may be accessed from various threads, + * hence the AtomicReference. By statring with an empty set, we can always + * guarantee a non-null reference. */ private AtomicReference> mAccountCache = new AtomicReference<>(Collections.emptySet()); - - public TaskProvider() - { - // for now we don't have anything specific to execute before the transaction ends. + public TaskProvider() { + // for now we don't have anything specific to execute before the transaction + // ends. super(EmptyIterable.instance()); } - @Override - public boolean onCreate() - { + public boolean onCreate() { mAuthority = AuthorityUtil.taskAuthority(getContext()); - mTaskProcessorChain = new Validating( - new AutoCompleting(new Relating(new Reparenting(new Instantiating(new Searchable(new Moving(new Originating(new TaskCommitProcessor())))))))); + mTaskProcessorChain = new Validating(new AutoCompleting(new Relating(new Reparenting( + new Instantiating(new Searchable(new Moving(new Originating(new TaskCommitProcessor())))))))); mListProcessorChain = new org.dmfs.provider.tasks.processors.lists.Validating(new ListCommitProcessor()); @@ -236,118 +238,100 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou return result; } - /** - * Return true if the caller is a sync adapter (i.e. if the Uri contains the query parameter {@link TaskContract#CALLER_IS_SYNCADAPTER} and its value is + * Return true if the caller is a sync adapter (i.e. if the Uri contains the + * query parameter {@link TaskContract#CALLER_IS_SYNCADAPTER} and its value is * true). * * @param uri - * The {@link Uri} to check. - * - * @return true if the caller pretends to be a sync adapter, false otherwise. + * The {@link Uri} to check. + * @return true if the caller pretends to be a sync adapter, + * false otherwise. */ @Override - public boolean isCallerSyncAdapter(Uri uri) - { + public boolean isCallerSyncAdapter(Uri uri) { String param = uri.getQueryParameter(TaskContract.CALLER_IS_SYNCADAPTER); return param != null && !"false".equals(param); } - /** - * Return true if the URI indicates to a load extended properties with {@link TaskContract#LOAD_PROPERTIES}. + * Return true if the URI indicates to a load extended properties with + * {@link TaskContract#LOAD_PROPERTIES}. * * @param uri - * The {@link Uri} to check. - * - * @return true if the URI requests to load extended properties, false otherwise. + * The {@link Uri} to check. + * @return true if the URI requests to load extended properties, + * false otherwise. */ - public boolean shouldLoadProperties(Uri uri) - { + public boolean shouldLoadProperties(Uri uri) { String param = uri.getQueryParameter(TaskContract.LOAD_PROPERTIES); return param != null && !"false".equals(param); } - /** * Get the account name from the given {@link Uri}. * * @param uri - * The Uri to check. - * + * The Uri to check. * @return The account name or null if no account name has been specified. */ - protected String getAccountName(Uri uri) - { + protected String getAccountName(Uri uri) { return uri.getQueryParameter(TaskContract.ACCOUNT_NAME); } - /** * Get the account type from the given {@link Uri}. * * @param uri - * The Uri to check. - * + * The Uri to check. * @return The account type or null if no account type has been specified. */ - protected String getAccountType(Uri uri) - { + protected String getAccountType(Uri uri) { return uri.getQueryParameter(TaskContract.ACCOUNT_TYPE); } - /** * Get any id from the given {@link Uri}. * * @param uri - * The Uri. - * + * The Uri. * @return The last path segment (which should contain the id). */ - private long getId(Uri uri) - { + private long getId(Uri uri) { return Long.parseLong(uri.getPathSegments().get(1)); } - /** - * Build a selection string that selects the account specified in uri. + * Build a selection string that selects the account specified in + * uri. * * @param uri - * A {@link Uri} that specifies an account. - * + * A {@link Uri} that specifies an account. * @return A {@link StringBuilder} with a selection string for the account. */ - protected StringBuilder selectAccount(Uri uri) - { + protected StringBuilder selectAccount(Uri uri) { StringBuilder sb = new StringBuilder(256); return selectAccount(sb, uri); } - /** - * Append the selection of the account specified in uri to the {@link StringBuilder} sb. + * Append the selection of the account specified in uri to the + * {@link StringBuilder} sb. * * @param sb - * A {@link StringBuilder} that the selection is appended to. + * A {@link StringBuilder} that the selection is appended to. * @param uri - * A {@link Uri} that specifies an account. - * + * A {@link Uri} that specifies an account. * @return sb. */ - protected StringBuilder selectAccount(StringBuilder sb, Uri uri) - { + protected StringBuilder selectAccount(StringBuilder sb, Uri uri) { String accountName = getAccountName(uri); String accountType = getAccountType(uri); - if (accountName != null || accountType != null) - { + if (accountName != null || accountType != null) { - if (accountName != null) - { - if (sb.length() > 0) - { + if (accountName != null) { + if (sb.length() > 0) { sb.append(" AND "); } @@ -355,11 +339,9 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou sb.append("="); DatabaseUtils.appendEscapedSQLString(sb, accountName); } - if (accountType != null) - { + if (accountType != null) { - if (sb.length() > 0) - { + if (sb.length() > 0) { sb.append(" AND "); } @@ -371,29 +353,26 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou return sb; } - /** - * Append the selection of the account specified in uri to the an {@link SQLiteQueryBuilder}. + * Append the selection of the account specified in uri to the an + * {@link SQLiteQueryBuilder}. * * @param sqlBuilder - * A {@link SQLiteQueryBuilder} that the selection is appended to. + * A {@link SQLiteQueryBuilder} that the selection is appended to. * @param uri - * A {@link Uri} that specifies an account. + * A {@link Uri} that specifies an account. */ - protected void selectAccount(SQLiteQueryBuilder sqlBuilder, Uri uri) - { + protected void selectAccount(SQLiteQueryBuilder sqlBuilder, Uri uri) { String accountName = getAccountName(uri); String accountType = getAccountType(uri); - if (accountName != null) - { + if (accountName != null) { sqlBuilder.appendWhere(" AND "); sqlBuilder.appendWhere(TaskListSyncColumns.ACCOUNT_NAME); sqlBuilder.appendWhere("="); sqlBuilder.appendWhereEscapeString(accountName); } - if (accountType != null) - { + if (accountType != null) { sqlBuilder.appendWhere(" AND "); sqlBuilder.appendWhere(TaskListSyncColumns.ACCOUNT_TYPE); sqlBuilder.appendWhere("="); @@ -401,11 +380,8 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou } } - - private StringBuilder _selectId(StringBuilder sb, long id, String key) - { - if (sb.length() > 0) - { + private StringBuilder _selectId(StringBuilder sb, long id, String key) { + if (sb.length() > 0) { sb.append(" AND "); } sb.append(key); @@ -414,329 +390,276 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou return sb; } - - protected StringBuilder selectId(Uri uri) - { + protected StringBuilder selectId(Uri uri) { StringBuilder sb = new StringBuilder(128); return selectId(sb, uri); } - - protected StringBuilder selectId(StringBuilder sb, Uri uri) - { + protected StringBuilder selectId(StringBuilder sb, Uri uri) { return _selectId(sb, getId(uri), TaskListColumns._ID); } - - protected StringBuilder selectTaskId(Uri uri) - { + protected StringBuilder selectTaskId(Uri uri) { StringBuilder sb = new StringBuilder(128); return selectTaskId(sb, uri); } - - protected StringBuilder selectTaskId(long id) - { + protected StringBuilder selectTaskId(long id) { StringBuilder sb = new StringBuilder(128); return selectTaskId(sb, id); } - - protected StringBuilder selectTaskId(StringBuilder sb, Uri uri) - { + protected StringBuilder selectTaskId(StringBuilder sb, Uri uri) { return selectTaskId(sb, getId(uri)); } - - protected StringBuilder selectTaskId(StringBuilder sb, long id) - { + protected StringBuilder selectTaskId(StringBuilder sb, long id) { return _selectId(sb, id, Instances.TASK_ID); - } - - protected StringBuilder selectPropertyId(Uri uri) - { + protected StringBuilder selectPropertyId(Uri uri) { StringBuilder sb = new StringBuilder(128); return selectPropertyId(sb, uri); } - - protected StringBuilder selectPropertyId(StringBuilder sb, Uri uri) - { + protected StringBuilder selectPropertyId(StringBuilder sb, Uri uri) { return selectPropertyId(sb, getId(uri)); } - - protected StringBuilder selectPropertyId(long id) - { + protected StringBuilder selectPropertyId(long id) { StringBuilder sb = new StringBuilder(128); return selectPropertyId(sb, id); } - - protected StringBuilder selectPropertyId(StringBuilder sb, long id) - { + protected StringBuilder selectPropertyId(StringBuilder sb, long id) { return _selectId(sb, id, PropertyColumns.PROPERTY_ID); } - /** - * Add a selection by ID to the given {@link SQLiteQueryBuilder}. The id is taken from the given Uri. + * Add a selection by ID to the given {@link SQLiteQueryBuilder}. The id is + * taken from the given Uri. * * @param sqlBuilder - * The {@link SQLiteQueryBuilder} to append the selection to. + * The {@link SQLiteQueryBuilder} to append the selection to. * @param idColumn - * The column that must match the id. + * The column that must match the id. * @param uri - * An {@link Uri} that contains the id. + * An {@link Uri} that contains the id. */ - protected void selectId(SQLiteQueryBuilder sqlBuilder, String idColumn, Uri uri) - { + protected void selectId(SQLiteQueryBuilder sqlBuilder, String idColumn, Uri uri) { sqlBuilder.appendWhere(" AND "); sqlBuilder.appendWhere(idColumn); sqlBuilder.appendWhere("="); sqlBuilder.appendWhere(String.valueOf(getId(uri))); } - /** * Append any arbitrary selection string to the selection in sb * * @param sb - * A {@link StringBuilder} that already contains a selection string. + * A {@link StringBuilder} that already contains a selection string. * @param selection - * A valid SQL selection string. - * + * A valid SQL selection string. * @return A string with the final selection. */ - protected String updateSelection(StringBuilder sb, String selection) - { - if (selection != null) - { - if (sb.length() > 0) - { + protected String updateSelection(StringBuilder sb, String selection) { + if (selection != null) { + if (sb.length() > 0) { sb.append(" AND ( ").append(selection).append(" ) "); - } - else - { + } else { sb.append(" ( ").append(selection).append(" ) "); } } return sb.toString(); } - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) - { + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { final SQLiteDatabase db = getDatabaseHelper().getWritableDatabase(); SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder(); - // initialize appendWhere, this allows us to append all other selections with a preceding "AND" + // initialize appendWhere, this allows us to append all other selections with a + // preceding "AND" sqlBuilder.appendWhere(" 1=1 "); boolean isSyncAdapter = isCallerSyncAdapter(uri); - switch (mUriMatcher.match(uri)) - { - case SYNCSTATE_ID: + switch (mUriMatcher.match(uri)) { + case SYNCSTATE_ID : // the id is ignored, we only match by account type and name given in the Uri - case SYNCSTATE: - { - if (TextUtils.isEmpty(getAccountName(uri)) || TextUtils.isEmpty(getAccountType(uri))) - { + case SYNCSTATE : { + if (TextUtils.isEmpty(getAccountName(uri)) || TextUtils.isEmpty(getAccountType(uri))) { throw new IllegalArgumentException("uri must contain an account when accessing syncstate"); } selectAccount(sqlBuilder, uri); sqlBuilder.setTables(Tables.SYNCSTATE); break; } - case LISTS: + case LISTS : // add account to selection if any selectAccount(sqlBuilder, uri); sqlBuilder.setTables(Tables.LISTS); - if (sortOrder == null || sortOrder.length() == 0) - { + if (sortOrder == null || sortOrder.length() == 0) { sortOrder = TaskContract.TaskLists.DEFAULT_SORT_ORDER; } break; - case LIST_ID: + case LIST_ID : // add account to selection if any selectAccount(sqlBuilder, uri); sqlBuilder.setTables(Tables.LISTS); selectId(sqlBuilder, TaskListColumns._ID, uri); - if (sortOrder == null || sortOrder.length() == 0) - { + if (sortOrder == null || sortOrder.length() == 0) { sortOrder = TaskContract.TaskLists.DEFAULT_SORT_ORDER; } break; - case TASKS: - if (shouldLoadProperties(uri)) - { - // extended properties were requested, therefore change to task view that includes these properties + case TASKS : + if (shouldLoadProperties(uri)) { + // extended properties were requested, therefore change to task view that + // includes these + // properties sqlBuilder.setTables(Tables.TASKS_PROPERTY_VIEW); - } - else - { + } else { sqlBuilder.setTables(Tables.TASKS_VIEW); } - if (!isSyncAdapter) - { + if (!isSyncAdapter) { // do not return deleted rows if caller is not a sync adapter sqlBuilder.appendWhere(" AND "); sqlBuilder.appendWhere(Tasks._DELETED); sqlBuilder.appendWhere("=0"); } - if (sortOrder == null || sortOrder.length() == 0) - { + if (sortOrder == null || sortOrder.length() == 0) { sortOrder = TaskContract.Tasks.DEFAULT_SORT_ORDER; } break; - case TASK_ID: - if (shouldLoadProperties(uri)) - { - // extended properties were requested, therefore change to task view that includes these properties + case TASK_ID : + if (shouldLoadProperties(uri)) { + // extended properties were requested, therefore change to task view that + // includes these + // properties sqlBuilder.setTables(Tables.TASKS_PROPERTY_VIEW); - } - else - { + } else { sqlBuilder.setTables(Tables.TASKS_VIEW); } selectId(sqlBuilder, TaskColumns._ID, uri); - if (!isSyncAdapter) - { + if (!isSyncAdapter) { // do not return deleted rows if caller is not a sync adapter sqlBuilder.appendWhere(" AND "); sqlBuilder.appendWhere(Tasks._DELETED); sqlBuilder.appendWhere("=0"); } - if (sortOrder == null || sortOrder.length() == 0) - { + if (sortOrder == null || sortOrder.length() == 0) { sortOrder = TaskContract.Tasks.DEFAULT_SORT_ORDER; } break; - case INSTANCES: - if (shouldLoadProperties(uri)) - { - // extended properties were requested, therefore change to instance view that includes these properties + case INSTANCES : + if (shouldLoadProperties(uri)) { + // extended properties were requested, therefore change to instance view that + // includes + // these properties sqlBuilder.setTables(Tables.INSTANCE_PROPERTY_VIEW); - } - else - { + } else { sqlBuilder.setTables(Tables.INSTANCE_CLIENT_VIEW); } - if (!isSyncAdapter) - { + if (!isSyncAdapter) { // do not return deleted rows if caller is not a sync adapter sqlBuilder.appendWhere(" AND "); sqlBuilder.appendWhere(Tasks._DELETED); sqlBuilder.appendWhere("=0"); } - if (sortOrder == null || sortOrder.length() == 0) - { + if (sortOrder == null || sortOrder.length() == 0) { sortOrder = TaskContract.Instances.DEFAULT_SORT_ORDER; } break; - case INSTANCE_ID: - if (shouldLoadProperties(uri)) - { - // extended properties were requested, therefore change to instance view that includes these properties + case INSTANCE_ID : + if (shouldLoadProperties(uri)) { + // extended properties were requested, therefore change to instance view that + // includes + // these properties sqlBuilder.setTables(Tables.INSTANCE_PROPERTY_VIEW); - } - else - { + } else { sqlBuilder.setTables(Tables.INSTANCE_CLIENT_VIEW); } selectId(sqlBuilder, Instances._ID, uri); - if (!isSyncAdapter) - { + if (!isSyncAdapter) { // do not return deleted rows if caller is not a sync adapter sqlBuilder.appendWhere(" AND "); sqlBuilder.appendWhere(Tasks._DELETED); sqlBuilder.appendWhere("=0"); } - if (sortOrder == null || sortOrder.length() == 0) - { + if (sortOrder == null || sortOrder.length() == 0) { sortOrder = TaskContract.Instances.DEFAULT_SORT_ORDER; } break; - case CATEGORIES: + case CATEGORIES : selectAccount(sqlBuilder, uri); sqlBuilder.setTables(Tables.CATEGORIES); - if (sortOrder == null || sortOrder.length() == 0) - { + if (sortOrder == null || sortOrder.length() == 0) { sortOrder = TaskContract.Categories.DEFAULT_SORT_ORDER; } break; - case CATEGORY_ID: + case CATEGORY_ID : selectAccount(sqlBuilder, uri); sqlBuilder.setTables(Tables.CATEGORIES); selectId(sqlBuilder, CategoriesColumns._ID, uri); - if (sortOrder == null || sortOrder.length() == 0) - { + if (sortOrder == null || sortOrder.length() == 0) { sortOrder = TaskContract.Categories.DEFAULT_SORT_ORDER; } break; - case PROPERTIES: + case PROPERTIES : sqlBuilder.setTables(Tables.PROPERTIES); break; - case PROPERTY_ID: + case PROPERTY_ID : sqlBuilder.setTables(Tables.PROPERTIES); selectId(sqlBuilder, PropertyColumns.PROPERTY_ID, uri); break; - case SEARCH: + case SEARCH : String searchString = uri.getQueryParameter(Tasks.SEARCH_QUERY_PARAMETER); searchString = Uri.decode(searchString); - Cursor searchCursor = FTSDatabaseHelper.getTaskSearchCursor(db, searchString, projection, selection, selectionArgs, sortOrder); - if (searchCursor != null) - { - // attach tasks uri for notifications, that way the search results are updated when a task changes + Cursor searchCursor = FTSDatabaseHelper.getTaskSearchCursor(db, searchString, projection, selection, + selectionArgs, sortOrder); + if (searchCursor != null) { + // attach tasks uri for notifications, that way the search results are updated + // when a task + // changes searchCursor.setNotificationUri(getContext().getContentResolver(), Tasks.getContentUri(mAuthority)); } return searchCursor; - default: + default : throw new IllegalArgumentException("Unknown URI " + uri); } Cursor c = sqlBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); - if (c != null) - { + if (c != null) { c.setNotificationUri(getContext().getContentResolver(), uri); } return c; } - @Override - public int deleteInTransaction(final SQLiteDatabase db, Uri uri, String selection, String[] selectionArgs, final boolean isSyncAdapter) - { + public int deleteInTransaction(final SQLiteDatabase db, Uri uri, String selection, String[] selectionArgs, + final boolean isSyncAdapter) { int count = 0; String accountName = getAccountName(uri); String accountType = getAccountType(uri); - switch (mUriMatcher.match(uri)) - { - case SYNCSTATE_ID: + switch (mUriMatcher.match(uri)) { + case SYNCSTATE_ID : // the id is ignored, we only match by account type and name given in the Uri - case SYNCSTATE: - { - if (!isSyncAdapter) - { + case SYNCSTATE : { + if (!isSyncAdapter) { throw new IllegalAccessError("only sync adapters may access syncstate"); } - if (TextUtils.isEmpty(getAccountName(uri)) || TextUtils.isEmpty(getAccountType(uri))) - { + if (TextUtils.isEmpty(getAccountName(uri)) || TextUtils.isEmpty(getAccountType(uri))) { throw new IllegalArgumentException("uri must contain an account when accessing syncstate"); } selection = updateSelection(selectAccount(uri), selection); @@ -744,69 +667,62 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou break; } /* - * Deleting task lists is only allowed to sync adapters. They must provide ACCOUNT_NAME and ACCOUNT_TYPE. + * Deleting task lists is only allowed to sync adapters. They must provide + * ACCOUNT_NAME and ACCOUNT_TYPE. */ - case LIST_ID: + case LIST_ID : // add _id to selection and fall through selection = updateSelection(selectId(uri), selection); - case LISTS: - { - if (isSyncAdapter) - { - if (TextUtils.isEmpty(accountType) || TextUtils.isEmpty(accountName)) - { - throw new IllegalArgumentException("Sync adapters must specify an account and account type: " + uri); + case LISTS : { + if (isSyncAdapter) { + if (TextUtils.isEmpty(accountType) || TextUtils.isEmpty(accountName)) { + throw new IllegalArgumentException( + "Sync adapters must specify an account and account type: " + uri); } } // iterate over all lists that match the selection final Cursor cursor = db.query(Tables.LISTS, null, selection, selectionArgs, null, null, null, null); - try - { - while (cursor.moveToNext()) - { - final ListAdapter list = new CursorContentValuesListAdapter(ListAdapter._ID.getFrom(cursor), cursor, new ContentValues()); + try { + while (cursor.moveToNext()) { + final ListAdapter list = new CursorContentValuesListAdapter(ListAdapter._ID.getFrom(cursor), + cursor, new ContentValues()); mListProcessorChain.delete(db, list, isSyncAdapter); mChanged.set(true); count++; } - } - finally - { + } finally { cursor.close(); } break; - } /* - * Task won't be removed, just marked as deleted if the caller isn't a sync adapter. Sync adapters can remove tasks immediately. + * Task won't be removed, just marked as deleted if the caller isn't a sync + * adapter. Sync adapters can remove tasks immediately. */ - case TASK_ID: + case TASK_ID : // add id to selection and fall through selection = updateSelection(selectId(uri), selection); - case TASKS: - { + case TASKS : { // TODO: filter by account name and type if present in uri. - if (isSyncAdapter) - { - if (TextUtils.isEmpty(accountType) || TextUtils.isEmpty(accountName)) - { - throw new IllegalArgumentException("Sync adapters must specify an account and account type: " + uri); + if (isSyncAdapter) { + if (TextUtils.isEmpty(accountType) || TextUtils.isEmpty(accountName)) { + throw new IllegalArgumentException( + "Sync adapters must specify an account and account type: " + uri); } } // iterate over all tasks that match the selection - final Cursor cursor = db.query(Tables.TASKS_VIEW, null, selection, selectionArgs, null, null, null, null); + final Cursor cursor = db.query(Tables.TASKS_VIEW, null, selection, selectionArgs, null, null, null, + null); - try - { - while (cursor.moveToNext()) - { + try { + while (cursor.moveToNext()) { final TaskAdapter task = new CursorContentValuesTaskAdapter(cursor, new ContentValues()); mTaskProcessorChain.delete(db, task, isSyncAdapter); @@ -814,27 +730,24 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou mChanged.set(true); count++; } - } - finally - { + } finally { cursor.close(); } break; } - case INSTANCE_ID: + case INSTANCE_ID : // add id to selection and fall through selection = updateSelection(selectId(uri), selection); - case INSTANCES: - { + case INSTANCES : { // iterate over all instances that match the selection - try (Cursor cursor = db.query(Tables.INSTANCE_VIEW, null, selection, selectionArgs, null, null, null, null)) - { - while (cursor.moveToNext()) - { - mInstanceProcessorChain.delete(db, new CursorContentValuesInstanceAdapter(cursor, new ContentValues()), isSyncAdapter); + try (Cursor cursor = db.query(Tables.INSTANCE_VIEW, null, selection, selectionArgs, null, null, null, + null)) { + while (cursor.moveToNext()) { + mInstanceProcessorChain.delete(db, + new CursorContentValuesInstanceAdapter(cursor, new ContentValues()), isSyncAdapter); mChanged.set(true); count++; } @@ -843,52 +756,45 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou break; } - case ALARM_ID: + case ALARM_ID : // add id to selection and fall through selection = updateSelection(selectId(uri), selection); - case ALARMS: - + case ALARMS : count = db.delete(Tables.ALARMS, selection, selectionArgs); break; - case PROPERTY_ID: + case PROPERTY_ID : selection = updateSelection(selectPropertyId(uri), selection); - case PROPERTIES: + case PROPERTIES : // fetch all properties that match the selection Cursor cursor = db.query(Tables.PROPERTIES, null, selection, selectionArgs, null, null, null); - try - { + try { int propIdCol = cursor.getColumnIndex(Properties.PROPERTY_ID); int taskIdCol = cursor.getColumnIndex(Properties.TASK_ID); int mimeTypeCol = cursor.getColumnIndex(Properties.MIMETYPE); - while (cursor.moveToNext()) - { + while (cursor.moveToNext()) { long propertyId = cursor.getLong(propIdCol); long taskId = cursor.getLong(taskIdCol); String mimeType = cursor.getString(mimeTypeCol); - if (mimeType != null) - { + if (mimeType != null) { PropertyHandler handler = PropertyHandlerFactory.get(mimeType); count += handler.delete(db, taskId, propertyId, cursor, isSyncAdapter); } } - } - finally - { + } finally { cursor.close(); } postNotifyUri(Properties.getContentUri(mAuthority)); break; - default: + default : throw new IllegalArgumentException("Unknown URI " + uri); } - if (count > 0) - { + if (count > 0) { postNotifyUri(uri); postNotifyUri(Instances.getContentUri(mAuthority)); postNotifyUri(Tasks.getContentUri(mAuthority)); @@ -896,26 +802,21 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou return count; } - @Override - public Uri insertInTransaction(final SQLiteDatabase db, Uri uri, final ContentValues values, final boolean isSyncAdapter) - { + public Uri insertInTransaction(final SQLiteDatabase db, Uri uri, final ContentValues values, + final boolean isSyncAdapter) { long rowId; Uri result_uri; String accountName = getAccountName(uri); String accountType = getAccountType(uri); - switch (mUriMatcher.match(uri)) - { - case SYNCSTATE: - { - if (!isSyncAdapter) - { + switch (mUriMatcher.match(uri)) { + case SYNCSTATE : { + if (!isSyncAdapter) { throw new IllegalAccessError("only sync adapters may access syncstate"); } - if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) - { + if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) { throw new IllegalArgumentException("uri must contain an account when accessing syncstate"); } values.put(SyncState.ACCOUNT_NAME, accountName); @@ -924,8 +825,7 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou result_uri = TaskContract.SyncState.getContentUri(mAuthority); break; } - case LISTS: - { + case LISTS : { final ListAdapter list = new ContentValuesListAdapter(values); list.set(ListAdapter.ACCOUNT_NAME, accountName); list.set(ListAdapter.ACCOUNT_TYPE, accountType); @@ -936,17 +836,16 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou rowId = list.id(); result_uri = TaskContract.TaskLists.getContentUri(mAuthority); // if the account is unknown we need to ask the user - if (Build.VERSION.SDK_INT >= 26 && - !TaskContract.LOCAL_ACCOUNT_TYPE.equals(accountType) && - !mAccountCache.get().contains(new Account(accountName, accountType))) - { + if (Build.VERSION.SDK_INT >= 26 && !TaskContract.LOCAL_ACCOUNT_TYPE.equals(accountType) + && !mAccountCache.get().contains(new Account(accountName, accountType))) { // store the fact that we have an unknown account in this transaction mStaleListCreated.set(true); - Log.d(TAG, String.format("List with unknown account %s inserted.", new Account(accountName, accountType))); + Log.d(TAG, String.format("List with unknown account %s inserted.", + new Account(accountName, accountType))); } break; } - case TASKS: + case TASKS : final TaskAdapter task = new ContentValuesTaskAdapter(values); mTaskProcessorChain.insert(db, task, isSyncAdapter); @@ -961,55 +860,54 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou break; - // inserting instances is currently disabled because we only expand one instance, - // so even though a new task (exception) would be created, no instance might show up - // we need to resolve this discrepancy. Until then this feature remains disabled. -// case INSTANCES: -// { -// InstanceAdapter instance = mInstanceProcessorChain.insert(db, new ContentValuesInstanceAdapter(values), isSyncAdapter); -// rowId = instance.id(); -// result_uri = TaskContract.Instances.getContentUri(mAuthority); -// -// postNotifyUri(Instances.getContentUri(mAuthority)); -// postNotifyUri(Tasks.getContentUri(mAuthority)); -// -// break; -// } - case PROPERTIES: + // inserting instances is currently disabled because we only expand one + // instance, + // so even though a new task (exception) would be created, no instance might + // show up + // we need to resolve this discrepancy. Until then this feature remains + // disabled. + // case INSTANCES: + // { + // InstanceAdapter instance = mInstanceProcessorChain.insert(db, new + // ContentValuesInstanceAdapter(values), isSyncAdapter); + // rowId = instance.id(); + // result_uri = TaskContract.Instances.getContentUri(mAuthority); + // + // postNotifyUri(Instances.getContentUri(mAuthority)); + // postNotifyUri(Tasks.getContentUri(mAuthority)); + // + // break; + // } + case PROPERTIES : String mimetype = values.getAsString(Properties.MIMETYPE); - if (mimetype == null) - { + if (mimetype == null) { throw new IllegalArgumentException("missing mimetype in property values"); } Long taskId = values.getAsLong(Properties.TASK_ID); - if (taskId == null) - { + if (taskId == null) { throw new IllegalArgumentException("missing task id in property values"); } - if (values.containsKey(Properties.PROPERTY_ID)) - { + if (values.containsKey(Properties.PROPERTY_ID)) { throw new IllegalArgumentException("property id can not be written"); } PropertyHandler handler = PropertyHandlerFactory.get(mimetype); rowId = handler.insert(db, taskId, values, isSyncAdapter); result_uri = TaskContract.Properties.getContentUri(mAuthority); - if (rowId >= 0) - { + if (rowId >= 0) { postNotifyUri(Tasks.getContentUri(mAuthority)); postNotifyUri(Instances.getContentUri(mAuthority)); } break; - default: + default : throw new IllegalArgumentException("Unknown URI " + uri); } - if (rowId > 0 && result_uri != null) - { + if (rowId > 0 && result_uri != null) { result_uri = ContentUris.withAppendedId(result_uri, rowId); postNotifyUri(result_uri); postNotifyUri(uri); @@ -1018,33 +916,26 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou throw new SQLException("Failed to insert row into " + uri); } - @Override - public int updateInTransaction(final SQLiteDatabase db, Uri uri, final ContentValues values, String selection, String[] selectionArgs, - final boolean isSyncAdapter) - { + public int updateInTransaction(final SQLiteDatabase db, Uri uri, final ContentValues values, String selection, + String[] selectionArgs, final boolean isSyncAdapter) { int count = 0; boolean dataChanged = false; - switch (mUriMatcher.match(uri)) - { - case SYNCSTATE_ID: + switch (mUriMatcher.match(uri)) { + case SYNCSTATE_ID : // the id is ignored, we only match by account type and name given in the Uri - case SYNCSTATE: - { - if (!isSyncAdapter) - { + case SYNCSTATE : { + if (!isSyncAdapter) { throw new IllegalAccessError("only sync adapters may access syncstate"); } String accountName = getAccountName(uri); String accountType = getAccountType(uri); - if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) - { + if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) { throw new IllegalArgumentException("uri must contain an account when accessing syncstate"); } - if (values.size() == 0) - { + if (values.size() == 0) { // we're done break; } @@ -1053,106 +944,92 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou values.put(SyncState.ACCOUNT_TYPE, accountType); long id = db.replace(Tables.SYNCSTATE, null, values); - if (id >= 0) - { + if (id >= 0) { count = 1; } break; } - case LIST_ID: + case LIST_ID : // update selection and fall through selection = updateSelection(selectId(uri), selection); - case LISTS: - { + case LISTS : { // iterate over all task lists that match the selection final Cursor cursor = db.query(Tables.LISTS, null, selection, selectionArgs, null, null, null, null); int idCol = cursor.getColumnIndex(TaskContract.TaskLists._ID); - try - { - while (cursor.moveToNext()) - { + try { + while (cursor.moveToNext()) { final long listId = cursor.getLong(idCol); // clone list values if we have more than one list to update // we need this, because the processors may change the values - final ListAdapter list = new CursorContentValuesListAdapter(listId, cursor, cursor.getCount() > 1 ? new ContentValues(values) : values); + final ListAdapter list = new CursorContentValuesListAdapter(listId, cursor, + cursor.getCount() > 1 ? new ContentValues(values) : values); - if (list.hasUpdates()) - { + if (list.hasUpdates()) { mListProcessorChain.update(db, list, isSyncAdapter); dataChanged |= !TASK_LIST_SYNC_COLUMNS.containsAll(values.keySet()); } // note we still count the row even if no update was necessary count++; } - } - finally - { + } finally { cursor.close(); } break; } - case TASK_ID: + case TASK_ID : // update selection and fall through selection = updateSelection(selectId(uri), selection); - case TASKS: - { + case TASKS : { // iterate over all tasks that match the selection - final Cursor cursor = db.query(Tables.TASKS_VIEW, null, selection, selectionArgs, null, null, null, null); + final Cursor cursor = db.query(Tables.TASKS_VIEW, null, selection, selectionArgs, null, null, null, + null); - try - { - while (cursor.moveToNext()) - { + try { + while (cursor.moveToNext()) { // clone task values if we have more than one task to update // we need this, because the processors may change the values - final TaskAdapter task = new CursorContentValuesTaskAdapter(cursor, cursor.getCount() > 1 ? new ContentValues(values) : values); + final TaskAdapter task = new CursorContentValuesTaskAdapter(cursor, + cursor.getCount() > 1 ? new ContentValues(values) : values); - if (task.hasUpdates()) - { + if (task.hasUpdates()) { mTaskProcessorChain.update(db, task, isSyncAdapter); dataChanged |= !TASK_LIST_SYNC_COLUMNS.containsAll(values.keySet()); } // note we still count the row even if no update was necessary count++; } - } - finally - { + } finally { cursor.close(); } - if (dataChanged) - { + if (dataChanged) { postNotifyUri(Instances.getContentUri(mAuthority)); postNotifyUri(Tasks.getContentUri(mAuthority)); } break; } - case INSTANCE_ID: + case INSTANCE_ID : // update selection and fall through selection = updateSelection(selectId(uri), selection); - case INSTANCES: - { + case INSTANCES : { // iterate over all instances that match the selection - try (Cursor cursor = db.query(Tables.INSTANCE_VIEW, null, selection, selectionArgs, null, null, null, null)) - { - while (cursor.moveToNext()) - { + try (Cursor cursor = db.query(Tables.INSTANCE_VIEW, null, selection, selectionArgs, null, null, null, + null)) { + while (cursor.moveToNext()) { // clone task values if we have more than one task to update // we need this, because the processors may change the values final InstanceAdapter instance = new CursorContentValuesInstanceAdapter(cursor, cursor.getCount() > 1 ? new ContentValues(values) : values); - if (instance.hasUpdates()) - { + if (instance.hasUpdates()) { mInstanceProcessorChain.update(db, instance, isSyncAdapter); dataChanged = true; } @@ -1161,82 +1038,71 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou } } - if (dataChanged) - { + if (dataChanged) { postNotifyUri(Instances.getContentUri(mAuthority)); postNotifyUri(Tasks.getContentUri(mAuthority)); } break; } - case PROPERTY_ID: + case PROPERTY_ID : selection = updateSelection(selectPropertyId(uri), selection); - case PROPERTIES: - if (values.containsKey(Properties.MIMETYPE)) - { + case PROPERTIES : + if (values.containsKey(Properties.MIMETYPE)) { throw new IllegalArgumentException("property mimetypes can not be modified"); } - if (values.containsKey(Properties.TASK_ID)) - { + if (values.containsKey(Properties.TASK_ID)) { throw new IllegalArgumentException("task id can not be changed"); } - if (values.containsKey(Properties.PROPERTY_ID)) - { + if (values.containsKey(Properties.PROPERTY_ID)) { throw new IllegalArgumentException("property id can not be changed"); } // fetch all properties that match the selection Cursor cursor = db.query(Tables.PROPERTIES, null, selection, selectionArgs, null, null, null); - try - { + try { int propIdCol = cursor.getColumnIndex(Properties.PROPERTY_ID); int taskIdCol = cursor.getColumnIndex(Properties.TASK_ID); int mimeTypeCol = cursor.getColumnIndex(Properties.MIMETYPE); - while (cursor.moveToNext()) - { + while (cursor.moveToNext()) { long propertyId = cursor.getLong(propIdCol); long taskId = cursor.getLong(taskIdCol); String mimeType = cursor.getString(mimeTypeCol); - if (mimeType != null) - { + if (mimeType != null) { PropertyHandler handler = PropertyHandlerFactory.get(mimeType); count += handler.update(db, taskId, propertyId, values, cursor, isSyncAdapter); } } - } - finally - { + } finally { cursor.close(); } postNotifyUri(Properties.getContentUri(mAuthority)); break; - case CATEGORY_ID: + case CATEGORY_ID : String newCategorySelection = updateSelection(selectId(uri), selection); validateCategoryValues(values, false, isSyncAdapter); count = db.update(Tables.CATEGORIES, values, newCategorySelection, selectionArgs); break; - case ALARM_ID: + case ALARM_ID : String newAlarmSelection = updateSelection(selectId(uri), selection); validateAlarmValues(values, false, isSyncAdapter); count = db.update(Tables.ALARMS, values, newAlarmSelection, selectionArgs); break; - default: + default : ContentOperation operation = ContentOperation.get(mUriMatcher.match(uri), OPERATIONS); - if (operation == null) - { + if (operation == null) { throw new IllegalArgumentException("Unknown URI " + uri); } operation.run(getContext(), mAsyncHandler, uri, db, values); } - if (dataChanged) - { + if (dataChanged) { // send notifications, because non-sync columns have been updated postNotifyUri(uri); mChanged.set(true); @@ -1245,151 +1111,124 @@ public final class TaskProvider extends SQLiteContentProvider implements OnAccou return count; } - - /** - * Update task due and task start notifications. - */ - private void updateNotifications() - { - mAsyncHandler.post(new Runnable() - { + /** Update task due and task start notifications. */ + private void updateNotifications() { + mAsyncHandler.post(new Runnable() { @Override - public void run() - { + public void run() { ContentOperation.UPDATE_NOTIFICATION_ALARM.fire(getContext(), null); } }); } - /** * Validate the given category values. * * @param values - * The category properties to validate. - * + * The category properties to validate. * @throws IllegalArgumentException - * if any of the values is invalid. + * if any of the values is invalid. */ - private void validateCategoryValues(ContentValues values, boolean isNew, boolean isSyncAdapter) - { + private void validateCategoryValues(ContentValues values, boolean isNew, boolean isSyncAdapter) { // row id can not be changed or set manually - if (values.containsKey(Categories._ID)) - { + if (values.containsKey(Categories._ID)) { throw new IllegalArgumentException("_ID can not be set manually"); } - if (isNew != values.containsKey(Categories.ACCOUNT_NAME) && (!isNew || values.get(Categories.ACCOUNT_NAME) != null)) - { + if (isNew != values.containsKey(Categories.ACCOUNT_NAME) + && (!isNew || values.get(Categories.ACCOUNT_NAME) != null)) { throw new IllegalArgumentException("ACCOUNT_NAME is write-once and required on INSERT"); } - if (isNew != values.containsKey(Categories.ACCOUNT_TYPE) && (!isNew || values.get(Categories.ACCOUNT_TYPE) != null)) - { + if (isNew != values.containsKey(Categories.ACCOUNT_TYPE) + && (!isNew || values.get(Categories.ACCOUNT_TYPE) != null)) { throw new IllegalArgumentException("ACCOUNT_TYPE is write-once and required on INSERT"); } } - /** * Validate the given alarm values. * * @param values - * The alarm values to validate - * + * The alarm values to validate * @throws IllegalArgumentException - * if any of the values is invalid. + * if any of the values is invalid. */ - private void validateAlarmValues(ContentValues values, boolean isNew, boolean isSyncAdapter) - { - if (values.containsKey(Alarms.ALARM_ID)) - { + private void validateAlarmValues(ContentValues values, boolean isNew, boolean isSyncAdapter) { + if (values.containsKey(Alarms.ALARM_ID)) { throw new IllegalArgumentException("ALARM_ID can not be set manually"); } } - @Override - public String getType(Uri uri) - { - switch (mUriMatcher.match(uri)) - { - case LISTS: + public String getType(Uri uri) { + switch (mUriMatcher.match(uri)) { + case LISTS : return ContentResolver.CURSOR_DIR_BASE_TYPE + "/org.dmfs.tasks." + TaskLists.CONTENT_URI_PATH; - case LIST_ID: + case LIST_ID : return ContentResolver.CURSOR_ITEM_BASE_TYPE + "/org.dmfs.tasks." + TaskLists.CONTENT_URI_PATH; - case TASKS: + case TASKS : return ContentResolver.CURSOR_DIR_BASE_TYPE + "/org.dmfs.tasks." + Tasks.CONTENT_URI_PATH; - case TASK_ID: + case TASK_ID : return ContentResolver.CURSOR_ITEM_BASE_TYPE + "/org.dmfs.tasks." + Tasks.CONTENT_URI_PATH; - case INSTANCES: + case INSTANCES : return ContentResolver.CURSOR_DIR_BASE_TYPE + "/org.dmfs.tasks." + Instances.CONTENT_URI_PATH; - case INSTANCE_ID: + case INSTANCE_ID : return ContentResolver.CURSOR_ITEM_BASE_TYPE + "/org.dmfs.tasks." + Instances.CONTENT_URI_PATH; - default: + default : throw new IllegalArgumentException("Unsupported URI: " + uri); } } - @Override - protected void onEndTransaction(boolean callerIsSyncAdapter) - { + protected void onEndTransaction(boolean callerIsSyncAdapter) { super.onEndTransaction(callerIsSyncAdapter); - if (mChanged.compareAndSet(true, false)) - { + if (mChanged.compareAndSet(true, false)) { updateNotifications(); Utils.sendActionProviderChangedBroadCast(getContext(), mAuthority); } - } - @Override - public SQLiteOpenHelper getDatabaseHelper(Context context) - { + public SQLiteOpenHelper getDatabaseHelper(Context context) { TaskDatabaseHelper helper = new TaskDatabaseHelper(context, this); return helper; } - @Override - public void onDatabaseCreated(SQLiteDatabase db) - { + public void onDatabaseCreated(SQLiteDatabase db) { // notify listeners that the database has been created Intent dbInitializedIntent = new Intent(TaskContract.ACTION_DATABASE_INITIALIZED); dbInitializedIntent.setDataAndType(TaskContract.getContentUri(mAuthority), TaskContract.MIMETYPE_AUTHORITY); - // Android SDK 26 doesn't allow us to send implicit broadcasts, this particular brodcast is only for internal use, so just make it explicit by setting our package name + // Android SDK 26 doesn't allow us to send implicit broadcasts, this particular + // brodcast is only + // for internal use, so just make it explicit by setting our package name dbInitializedIntent.setPackage(getContext().getPackageName()); getContext().sendBroadcast(dbInitializedIntent); } - @Override - public void onDatabaseUpdate(SQLiteDatabase db, int oldVersion, int newVersion) - { - if (oldVersion < 15) - { + public void onDatabaseUpdate(SQLiteDatabase db, int oldVersion, int newVersion) { + if (oldVersion < 15) { mAsyncHandler.post(() -> ContentOperation.UPDATE_TIMEZONE.fire(getContext(), null)); } } - @Override - protected boolean syncToNetwork(Uri uri) - { + protected boolean syncToNetwork(Uri uri) { return true; } - @Override - public void onAccountsUpdated(Account[] accounts) - { - // cache the known accounts so we can check whether we know accounts for which new lists are added + public void onAccountsUpdated(Account[] accounts) { + // cache the known accounts so we can check whether we know accounts for which + // new lists are + // added mAccountCache.set(new HashSet<>(Arrays.asList(accounts))); - // TODO: we probably can move the cleanup code here and get rid of the Utils class + // TODO: we probably can move the cleanup code here and get rid of the Utils + // class Utils.cleanUpLists(getContext(), getDatabaseHelper().getWritableDatabase(), accounts, mAuthority); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProviderBroadcastReceiver.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProviderBroadcastReceiver.java index 06764ac6888bf6a42b8e366e3ce597d6696385c2..7a4c6decc242ec9b140adbbfab993f134f1afd93 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProviderBroadcastReceiver.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProviderBroadcastReceiver.java @@ -22,77 +22,71 @@ import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.os.Build; - -import org.dmfs.rfc5545.DateTime; - import java.util.TimeZone; - +import org.dmfs.rfc5545.DateTime; /** - * A receiver for all task provider related broadcasts. This receiver merely forwards all incoming broadcasts to the provider, so they can be handled + * A receiver for all task provider related broadcasts. This receiver merely + * forwards all incoming broadcasts to the provider, so they can be handled * asynchronously in the provider context. * * @author Marten Gajda */ -public class TaskProviderBroadcastReceiver extends BroadcastReceiver -{ - private final static int REQUEST_CODE_ALARM = 1337; - - private final static String ACTION_NOTIFICATION_ALARM = "org.dmfs.tasks.provider.NOTIFICATION_ALARM"; +public class TaskProviderBroadcastReceiver extends BroadcastReceiver { + private static final int REQUEST_CODE_ALARM = 1337; + private static final String ACTION_NOTIFICATION_ALARM = "org.dmfs.tasks.provider.NOTIFICATION_ALARM"; /** * Registers a system alarm to update notifications at a specific time. * * @param context - * A Context. + * A Context. * @param updateTime - * When to fire the alarm. + * When to fire the alarm. */ @SuppressLint("NewApi") - static void planNotificationUpdate(Context context, DateTime updateTime) - { + static void planNotificationUpdate(Context context, DateTime updateTime) { AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent alarmIntent = new Intent(context, TaskProviderBroadcastReceiver.class); alarmIntent.setAction(ACTION_NOTIFICATION_ALARM); - PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE_ALARM, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE_ALARM, alarmIntent, + PendingIntent.FLAG_UPDATE_CURRENT); // cancel any previous alarm am.cancel(pendingIntent); - if (updateTime.isFloating()) - { + if (updateTime.isFloating()) { // convert floating times to absolute times - updateTime = new DateTime(TimeZone.getDefault(), updateTime.getYear(), updateTime.getMonth(), updateTime.getDayOfMonth(), updateTime.getHours(), - updateTime.getMinutes(), updateTime.getSeconds()); + updateTime = new DateTime(TimeZone.getDefault(), updateTime.getYear(), updateTime.getMonth(), + updateTime.getDayOfMonth(), updateTime.getHours(), updateTime.getMinutes(), + updateTime.getSeconds()); } - // AlarmManager API changed in v19 (KitKat) and the "set" method is not called at the exact time anymore + // AlarmManager API changed in v19 (KitKat) and the "set" method is not called + // at the exact time + // anymore am.setExact(AlarmManager.RTC_WAKEUP, updateTime.getTimestamp(), pendingIntent); } - @Override - public void onReceive(Context context, Intent intent) - { + public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - switch (action) - { - case Intent.ACTION_TIMEZONE_CHANGED: - { - // the local timezone has been changed, notify the provider to take the necessary steps. - // don't trigger the notifications update yet, because the timezone update will run asynhronously and we need to wait till that's finished + switch (action) { + case Intent.ACTION_TIMEZONE_CHANGED : { + // the local timezone has been changed, notify the provider to take the + // necessary steps. + // don't trigger the notifications update yet, because the timezone update will + // run + // asynhronously and we need to wait till that's finished ContentOperation.UPDATE_TIMEZONE.fire(context, null); } - case ACTION_NOTIFICATION_ALARM: - { + case ACTION_NOTIFICATION_ALARM : { // it's time for the next notification ContentOperation.POST_NOTIFICATIONS.fire(context, null); } - default: - { + default : { // at this time all other actions trigger an update of the notification alarm ContentOperation.UPDATE_NOTIFICATION_ALARM.fire(context, null); } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/Utils.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/Utils.java index 997fddbd23a282d62889c2ad6327060e76677339..11095381ae503f9d7e7bd8267ca7fbf969bd6801 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/Utils.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/Utils.java @@ -22,7 +22,9 @@ import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.dmfs.iterables.SingletonIterable; import org.dmfs.jems.iterable.composite.Joined; import org.dmfs.jems.iterable.decorators.Mapped; @@ -39,97 +41,77 @@ import org.dmfs.tasks.contract.TaskContract.TaskLists; import org.dmfs.tasks.contract.TaskContract.Tasks; import org.dmfs.tasks.provider.R; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - - /** * The Class Utils. * * @author Tobias Reinsch * @author Marten Gajda */ -public class Utils -{ - public static void sendActionProviderChangedBroadCast(Context context, String authority) - { - // TODO: Using the TaskContract content uri results in a "Unknown URI content" error message. Using the Tasks content uri instead will break the +public class Utils { + public static void sendActionProviderChangedBroadCast(Context context, String authority) { + // TODO: Using the TaskContract content uri results in a "Unknown URI content" + // error message. + // Using the Tasks content uri instead will break the // broadcast receiver. We have to find away around this - // TODO: coalesce fast consecutive broadcasts, a delay of up to 1 second should be acceptable + // TODO: coalesce fast consecutive broadcasts, a delay of up to 1 second should + // be acceptable new With<>(new Intent(Intent.ACTION_PROVIDER_CHANGED, TaskContract.getContentUri(authority))) - .process(providerChangedIntent -> - new Batch(context::sendBroadcast) - .process(new Mapped<>( - packageName -> new Intent(providerChangedIntent).setPackage(packageName), - // TODO: fow now we hard code 3rd party package names, this should be replaced by some sort or registry - // see https://github.com/dmfs/opentasks/issues/824 - new Joined<>( - new SingletonIterable<>(context.getPackageName()), - new ResourceArray(context, R.array.opentasks_provider_changed_receivers))))); + .process(providerChangedIntent -> new Batch(context::sendBroadcast) + .process(new Mapped<>(packageName -> new Intent(providerChangedIntent).setPackage(packageName), + // TODO: fow now we hard code 3rd party package names, this should be + // replaced by some sort or registry + // see https://github.com/dmfs/opentasks/issues/824 + new Joined<>(new SingletonIterable<>(context.getPackageName()), + new ResourceArray(context, R.array.opentasks_provider_changed_receivers))))); } - - public static void cleanUpLists(Context context, SQLiteDatabase db, Account[] accounts, String authority) - { + public static void cleanUpLists(Context context, SQLiteDatabase db, Account[] accounts, String authority) { // make a list of the accounts array List accountList = Arrays.asList(accounts); db.beginTransaction(); - try - { - Cursor c = db.query(Tables.LISTS, new String[] { TaskListColumns._ID, TaskListSyncColumns.ACCOUNT_NAME, TaskListSyncColumns.ACCOUNT_TYPE }, null, - null, null, null, null); + try { + Cursor c = db.query(Tables.LISTS, new String[]{TaskListColumns._ID, TaskListSyncColumns.ACCOUNT_NAME, + TaskListSyncColumns.ACCOUNT_TYPE}, null, null, null, null, null); // build a list of all task list ids that no longer have an account List obsoleteLists = new ArrayList(); - try - { - while (c.moveToNext()) - { + try { + while (c.moveToNext()) { String accountType = c.getString(2); // mark list for removal if it is non-local and the account // is not in accountList - if (!TaskContract.LOCAL_ACCOUNT_TYPE.equals(accountType)) - { + if (!TaskContract.LOCAL_ACCOUNT_TYPE.equals(accountType)) { Account account = new Account(c.getString(1), accountType); - if (!accountList.contains(account)) - { + if (!accountList.contains(account)) { obsoleteLists.add(c.getLong(0)); // remove syncstate for this account right away - db.delete(Tables.SYNCSTATE, SyncState.ACCOUNT_NAME + "=? and " + SyncState.ACCOUNT_TYPE + "=?", new String[] { - account.name, - account.type }); + db.delete(Tables.SYNCSTATE, + SyncState.ACCOUNT_NAME + "=? and " + SyncState.ACCOUNT_TYPE + "=?", + new String[]{account.name, account.type}); } } } - } - finally - { + } finally { c.close(); } - if (obsoleteLists.size() == 0) - { + if (obsoleteLists.size() == 0) { // nothing to do here return; } // remove all accounts in the list - for (Long id : obsoleteLists) - { - if (id != null) - { + for (Long id : obsoleteLists) { + if (id != null) { db.delete(Tables.LISTS, TaskListColumns._ID + "=" + id, null); } } db.setTransactionSuccessful(); - } - finally - { + } finally { db.endTransaction(); } // notify all observers @@ -141,5 +123,4 @@ public class Utils Utils.sendActionProviderChangedBroadCast(context, authority); } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/AlarmHandler.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/AlarmHandler.java index 4882d21998adad473e1c6255ce78fc42dd63b99d..589cbaafba87de1b8dc84b6d8e79efaebd31cb87 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/AlarmHandler.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/AlarmHandler.java @@ -19,114 +19,102 @@ package org.dmfs.provider.tasks.handler; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.tasks.contract.TaskContract.Property; - /** - * This class is used to handle alarm property values during database transactions. + * This class is used to handle alarm property values during database + * transactions. * * @author Tobias Reinsch */ -public class AlarmHandler extends PropertyHandler -{ +public class AlarmHandler extends PropertyHandler { // private static final String[] ALARM_ID_PROJECTION = { Alarms.ALARM_ID }; // private static final String ALARM_SELECTION = Alarms.ALARM_ID + " =?"; - /** * Validates the content of the alarm prior to insert and update transactions. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * The id of the task this property belongs to. + * The id of the task this property belongs to. * @param propertyId - * The id of the property if isNew is false. If isNew is true this value is ignored. + * The id of the property if isNew is + * false. If + * isNew is true this value is ignored. * @param isNew - * Indicates that the content is new and not an update. + * Indicates that the content is new and not an update. * @param values - * The {@link ContentValues} to validate. + * The {@link ContentValues} to validate. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return The valid {@link ContentValues}. - * * @throws IllegalArgumentException - * if the {@link ContentValues} are invalid. + * if the {@link ContentValues} are invalid. */ @Override - public ContentValues validateValues(SQLiteDatabase db, long taskId, long propertyId, boolean isNew, ContentValues values, boolean isSyncAdapter) - { + public ContentValues validateValues(SQLiteDatabase db, long taskId, long propertyId, boolean isNew, + ContentValues values, boolean isSyncAdapter) { // row id can not be changed or set manually - if (values.containsKey(Property.Alarm.PROPERTY_ID)) - { + if (values.containsKey(Property.Alarm.PROPERTY_ID)) { throw new IllegalArgumentException("_ID can not be set manually"); } - if (!values.containsKey(Property.Alarm.MINUTES_BEFORE)) - { + if (!values.containsKey(Property.Alarm.MINUTES_BEFORE)) { throw new IllegalArgumentException("alarm property requires a time offset"); } - if (!values.containsKey(Property.Alarm.REFERENCE) || values.getAsInteger(Property.Alarm.REFERENCE) < 0) - { + if (!values.containsKey(Property.Alarm.REFERENCE) || values.getAsInteger(Property.Alarm.REFERENCE) < 0) { throw new IllegalArgumentException("alarm property requires a valid reference date "); } - if (!values.containsKey(Property.Alarm.ALARM_TYPE)) - { + if (!values.containsKey(Property.Alarm.ALARM_TYPE)) { throw new IllegalArgumentException("alarm property requires an alarm type"); } return values; } - /** * Inserts the alarm into the database. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * The id of the task the new property belongs to. + * The id of the task the new property belongs to. * @param values - * The {@link ContentValues} to insert. + * The {@link ContentValues} to insert. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return The row id of the new alarm as long */ @Override - public long insert(SQLiteDatabase db, long taskId, ContentValues values, boolean isSyncAdapter) - { + public long insert(SQLiteDatabase db, long taskId, ContentValues values, boolean isSyncAdapter) { values = validateValues(db, taskId, -1, true, values, isSyncAdapter); return super.insert(db, taskId, values, isSyncAdapter); } - /** * Updates the alarm in the database. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * The id of the task this property belongs to. + * The id of the task this property belongs to. * @param propertyId - * The id of the property. + * The id of the property. * @param values - * The {@link ContentValues} to update. + * The {@link ContentValues} to update. * @param oldValues - * A {@link Cursor} pointing to the old values in the database. + * A {@link Cursor} pointing to the old values in the database. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return The number of rows affected. */ @Override - public int update(SQLiteDatabase db, long taskId, long propertyId, ContentValues values, Cursor oldValues, boolean isSyncAdapter) - { + public int update(SQLiteDatabase db, long taskId, long propertyId, ContentValues values, Cursor oldValues, + boolean isSyncAdapter) { values = validateValues(db, taskId, propertyId, false, values, isSyncAdapter); return super.update(db, taskId, propertyId, values, oldValues, isSyncAdapter); } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/CategoryHandler.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/CategoryHandler.java index 8c129cb04389769dedb7d932fd039a901985d085..5d2d0287d536a403a53e398bf09958fed350fbb9 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/CategoryHandler.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/CategoryHandler.java @@ -19,7 +19,6 @@ package org.dmfs.provider.tasks.handler; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper.CategoriesMapping; import org.dmfs.provider.tasks.TaskDatabaseHelper.Tables; import org.dmfs.tasks.contract.TaskContract.Categories; @@ -27,106 +26,97 @@ import org.dmfs.tasks.contract.TaskContract.Properties; import org.dmfs.tasks.contract.TaskContract.Property.Category; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** - * This class is used to handle category property values during database transactions. + * This class is used to handle category property values during database + * transactions. * * @author Tobias Reinsch */ -public class CategoryHandler extends PropertyHandler -{ +public class CategoryHandler extends PropertyHandler { - private static final String[] CATEGORY_ID_PROJECTION = { Categories._ID, Categories.NAME, Categories.COLOR }; + private static final String[] CATEGORY_ID_PROJECTION = {Categories._ID, Categories.NAME, Categories.COLOR}; - private static final String CATEGORY_ID_SELECTION = Categories._ID + "=? and " + Categories.ACCOUNT_NAME + "=? and " + Categories.ACCOUNT_TYPE + "=?"; - private static final String CATEGORY_NAME_SELECTION = Categories.NAME + "=? and " + Categories.ACCOUNT_NAME + "=? and " + Categories.ACCOUNT_TYPE + "=?"; + private static final String CATEGORY_ID_SELECTION = Categories._ID + "=? and " + Categories.ACCOUNT_NAME + "=? and " + + Categories.ACCOUNT_TYPE + "=?"; + private static final String CATEGORY_NAME_SELECTION = Categories.NAME + "=? and " + Categories.ACCOUNT_NAME + + "=? and " + Categories.ACCOUNT_TYPE + "=?"; public static final String IS_NEW_CATEGORY = "is_new_category"; - /** - * Validates the content of the category prior to insert and update transactions. + * Validates the content of the category prior to insert and update + * transactions. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * The id of the task this property belongs to. + * The id of the task this property belongs to. * @param propertyId - * The id of the property if isNew is false. If isNew is true this value is ignored. + * The id of the property if isNew is + * false. If + * isNew is true this value is ignored. * @param isNew - * Indicates that the content is new and not an update. + * Indicates that the content is new and not an update. * @param values - * The {@link ContentValues} to validate. + * The {@link ContentValues} to validate. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return The valid {@link ContentValues}. - * * @throws IllegalArgumentException - * if the {@link ContentValues} are invalid. + * if the {@link ContentValues} are invalid. */ @Override - public ContentValues validateValues(SQLiteDatabase db, long taskId, long propertyId, boolean isNew, ContentValues values, boolean isSyncAdapter) - { + public ContentValues validateValues(SQLiteDatabase db, long taskId, long propertyId, boolean isNew, + ContentValues values, boolean isSyncAdapter) { // the category requires a name or an id - if (!values.containsKey(Category.CATEGORY_ID) && !values.containsKey(Category.CATEGORY_NAME)) - { - throw new IllegalArgumentException("Neiter an id nor a category name was supplied for the category property."); + if (!values.containsKey(Category.CATEGORY_ID) && !values.containsKey(Category.CATEGORY_NAME)) { + throw new IllegalArgumentException( + "Neiter an id nor a category name was supplied for the category property."); } // get the matching task & account for the property - if (!values.containsKey(Properties.TASK_ID)) - { + if (!values.containsKey(Properties.TASK_ID)) { throw new IllegalArgumentException("No task id was supplied for the category property"); } - String[] queryArgs = { values.getAsString(Properties.TASK_ID) }; - String[] queryProjection = { Tasks.ACCOUNT_NAME, Tasks.ACCOUNT_TYPE }; + String[] queryArgs = {values.getAsString(Properties.TASK_ID)}; + String[] queryProjection = {Tasks.ACCOUNT_NAME, Tasks.ACCOUNT_TYPE}; String querySelection = Tasks._ID + "=?"; Cursor taskCursor = db.query(Tables.TASKS_VIEW, queryProjection, querySelection, queryArgs, null, null, null); String accountName = null; String accountType = null; - try - { - if (taskCursor.moveToNext()) - { + try { + if (taskCursor.moveToNext()) { accountName = taskCursor.getString(0); accountType = taskCursor.getString(1); values.put(Categories.ACCOUNT_NAME, accountName); values.put(Categories.ACCOUNT_TYPE, accountType); } - } - finally - { - if (taskCursor != null) - { + } finally { + if (taskCursor != null) { taskCursor.close(); } } - if (accountName != null && accountType != null) - { + if (accountName != null && accountType != null) { // search for matching categories String[] categoryArgs; Cursor cursor; - if (values.containsKey(Categories._ID)) - { + if (values.containsKey(Categories._ID)) { // serach by ID - categoryArgs = new String[] { values.getAsString(Category.CATEGORY_ID), accountName, accountType }; - cursor = db.query(Tables.CATEGORIES, CATEGORY_ID_PROJECTION, CATEGORY_ID_SELECTION, categoryArgs, null, null, null); - } - else - { + categoryArgs = new String[]{values.getAsString(Category.CATEGORY_ID), accountName, accountType}; + cursor = db.query(Tables.CATEGORIES, CATEGORY_ID_PROJECTION, CATEGORY_ID_SELECTION, categoryArgs, null, + null, null); + } else { // search by name - categoryArgs = new String[] { values.getAsString(Category.CATEGORY_NAME), accountName, accountType }; - cursor = db.query(Tables.CATEGORIES, CATEGORY_ID_PROJECTION, CATEGORY_NAME_SELECTION, categoryArgs, null, null, null); + categoryArgs = new String[]{values.getAsString(Category.CATEGORY_NAME), accountName, accountType}; + cursor = db.query(Tables.CATEGORIES, CATEGORY_ID_PROJECTION, CATEGORY_NAME_SELECTION, categoryArgs, + null, null, null); } - try - { - if (cursor != null && cursor.getCount() == 1) - { + try { + if (cursor != null && cursor.getCount() == 1) { cursor.moveToNext(); Long categoryID = cursor.getLong(0); String categoryName = cursor.getString(1); @@ -136,43 +126,34 @@ public class CategoryHandler extends PropertyHandler values.put(Category.CATEGORY_NAME, categoryName); values.put(Category.CATEGORY_COLOR, color); values.put(IS_NEW_CATEGORY, false); - } - else - { + } else { values.put(IS_NEW_CATEGORY, true); } - } - finally - { - if (cursor != null) - { + } finally { + if (cursor != null) { cursor.close(); } } - } return values; } - /** * Inserts the category into the database. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * The id of the task the new property belongs to. + * The id of the task the new property belongs to. * @param values - * The {@link ContentValues} to insert. + * The {@link ContentValues} to insert. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return The row id of the new category as long */ @Override - public long insert(SQLiteDatabase db, long taskId, ContentValues values, boolean isSyncAdapter) - { + public long insert(SQLiteDatabase db, long taskId, ContentValues values, boolean isSyncAdapter) { values = validateValues(db, taskId, -1, true, values, isSyncAdapter); values = getOrInsertCategory(db, values); @@ -185,33 +166,30 @@ public class CategoryHandler extends PropertyHandler return id; } - /** * Updates the category in the database. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * The id of the task this property belongs to. + * The id of the task this property belongs to. * @param propertyId - * The id of the property. + * The id of the property. * @param values - * The {@link ContentValues} to update. + * The {@link ContentValues} to update. * @param oldValues - * A {@link Cursor} pointing to the old values in the database. + * A {@link Cursor} pointing to the old values in the database. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return The number of rows affected. */ @Override - public int update(SQLiteDatabase db, long taskId, long propertyId, ContentValues values, Cursor oldValues, boolean isSyncAdapter) - { + public int update(SQLiteDatabase db, long taskId, long propertyId, ContentValues values, Cursor oldValues, + boolean isSyncAdapter) { values = validateValues(db, taskId, propertyId, false, values, isSyncAdapter); values = getOrInsertCategory(db, values); - if (values.containsKey(Category.CATEGORY_NAME)) - { + if (values.containsKey(Category.CATEGORY_NAME)) { // update FTS entry with new category name updateFTSEntry(db, taskId, propertyId, values.getAsString(Category.CATEGORY_NAME)); } @@ -219,21 +197,18 @@ public class CategoryHandler extends PropertyHandler return super.update(db, taskId, propertyId, values, oldValues, isSyncAdapter); } - /** - * Check if a category with matching {@link ContentValues} exists and returns the existing category or creates a new category in the database. + * Check if a category with matching {@link ContentValues} exists and returns + * the existing category or creates a new category in the database. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param values - * The {@link ContentValues} of the category. - * + * The {@link ContentValues} of the category. * @return The {@link ContentValues} of the existing or new category. */ - private ContentValues getOrInsertCategory(SQLiteDatabase db, ContentValues values) - { - if (values.getAsBoolean(IS_NEW_CATEGORY)) - { + private ContentValues getOrInsertCategory(SQLiteDatabase db, ContentValues values) { + if (values.getAsBoolean(IS_NEW_CATEGORY)) { // insert new category in category table ContentValues newCategoryValues = new ContentValues(4); newCategoryValues.put(Categories.ACCOUNT_NAME, values.getAsString(Categories.ACCOUNT_NAME)); @@ -253,21 +228,18 @@ public class CategoryHandler extends PropertyHandler return values; } - /** * Inserts a relation entry in the database to link task and category. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * The row id of the task. + * The row id of the task. * @param categoryId - * The row id of the category. - * + * The row id of the category. * @return The row id of the inserted relation. */ - private long insertRelation(SQLiteDatabase db, long taskId, long categoryId, long propertyId) - { + private long insertRelation(SQLiteDatabase db, long taskId, long categoryId, long propertyId) { ContentValues relationValues = new ContentValues(3); relationValues.put(CategoriesMapping.TASK_ID, taskId); relationValues.put(CategoriesMapping.CATEGORY_ID, categoryId); diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/DefaultPropertyHandler.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/DefaultPropertyHandler.java index 52d32d3870c3063100857290e26f87b106a59454..2f76c46f20f7fda38499e25c2eabfaa1fe0f22f2 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/DefaultPropertyHandler.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/DefaultPropertyHandler.java @@ -19,36 +19,32 @@ package org.dmfs.provider.tasks.handler; import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; - /** - * This class is used to handle properties with unknown / unsupported mime-types. + * This class is used to handle properties with unknown / unsupported + * mime-types. * * @author Tobias Reinsch */ -public class DefaultPropertyHandler extends PropertyHandler -{ +public class DefaultPropertyHandler extends PropertyHandler { /** * Validates the content of the alarm prior to insert and update transactions. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param isNew - * Indicates that the content is new and not an update. + * Indicates that the content is new and not an update. * @param values - * The {@link ContentValues} to validate. + * The {@link ContentValues} to validate. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return The valid {@link ContentValues}. - * * @throws IllegalArgumentException - * if the {@link ContentValues} are invalid. + * if the {@link ContentValues} are invalid. */ @Override - public ContentValues validateValues(SQLiteDatabase db, long taskId, long propertyId, boolean isNew, ContentValues values, boolean isSyncAdapter) - { + public ContentValues validateValues(SQLiteDatabase db, long taskId, long propertyId, boolean isNew, + ContentValues values, boolean isSyncAdapter) { return values; } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/PropertyHandler.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/PropertyHandler.java index a01e39d806de7c273eaf847deace1e90eb7d37e9..6e2ccf24b17a7bf7b16f6efdf4b5c3a334fe9952 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/PropertyHandler.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/PropertyHandler.java @@ -19,137 +19,121 @@ package org.dmfs.provider.tasks.handler; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.FTSDatabaseHelper; import org.dmfs.provider.tasks.TaskDatabaseHelper.Tables; import org.dmfs.tasks.contract.TaskContract.Properties; - /** * Abstract class that is used as template for specific property handlers. * * @author Tobias Reinsch */ -public abstract class PropertyHandler -{ +public abstract class PropertyHandler { /** - * Validates the content of the property prior to insert and update transactions. + * Validates the content of the property prior to insert and update + * transactions. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * The id of the task this property belongs to. + * The id of the task this property belongs to. * @param propertyId - * The id of the property if isNew is false. If isNew is true this value is ignored. + * The id of the property if isNew is + * false. If + * isNew is true this value is ignored. * @param isNew - * Indicates that the content is new and not an update. + * Indicates that the content is new and not an update. * @param values - * The {@link ContentValues} to validate. + * The {@link ContentValues} to validate. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return The valid {@link ContentValues}. - * * @throws IllegalArgumentException - * if the {@link ContentValues} are invalid. + * if the {@link ContentValues} are invalid. */ - public abstract ContentValues validateValues(SQLiteDatabase db, long taskId, long propertyId, boolean isNew, ContentValues values, boolean isSyncAdapter); - + public abstract ContentValues validateValues(SQLiteDatabase db, long taskId, long propertyId, boolean isNew, + ContentValues values, boolean isSyncAdapter); /** * Inserts the property {@link ContentValues} into the database. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * The id of the task the new property belongs to. + * The id of the task the new property belongs to. * @param values - * The {@link ContentValues} to insert. + * The {@link ContentValues} to insert. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return The row id of the new property as long */ - public long insert(SQLiteDatabase db, long taskId, ContentValues values, boolean isSyncAdapter) - { + public long insert(SQLiteDatabase db, long taskId, ContentValues values, boolean isSyncAdapter) { return db.insert(Tables.PROPERTIES, "", values); } - /** * Updates the property {@link ContentValues} in the database. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * The id of the task this property belongs to. + * The id of the task this property belongs to. * @param propertyId - * The id of the property. + * The id of the property. * @param values - * The {@link ContentValues} to update. + * The {@link ContentValues} to update. * @param oldValues - * A {@link Cursor} pointing to the old values in the database. + * A {@link Cursor} pointing to the old values in the database. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return The number of rows affected. */ - public int update(SQLiteDatabase db, long taskId, long propertyId, ContentValues values, Cursor oldValues, boolean isSyncAdapter) - { + public int update(SQLiteDatabase db, long taskId, long propertyId, ContentValues values, Cursor oldValues, + boolean isSyncAdapter) { return db.update(Tables.PROPERTIES, values, Properties.PROPERTY_ID + "=" + propertyId, null); } - /** * Deletes the property in the database. * * @param db - * The belonging database. + * The belonging database. * @param taskId - * The id of the task this property belongs to. + * The id of the task this property belongs to. * @param propertyId - * The id of the property. + * The id of the property. * @param oldValues - * A {@link Cursor} pointing to the old values in the database. + * A {@link Cursor} pointing to the old values in the database. * @param isSyncAdapter - * Indicates that the transaction was triggered from a SyncAdapter. - * + * Indicates that the transaction was triggered from a SyncAdapter. * @return */ - public int delete(SQLiteDatabase db, long taskId, long propertyId, Cursor oldValues, boolean isSyncAdapter) - { + public int delete(SQLiteDatabase db, long taskId, long propertyId, Cursor oldValues, boolean isSyncAdapter) { return db.delete(Tables.PROPERTIES, Properties.PROPERTY_ID + "=" + propertyId, null); - } - /** * Method hook to insert FTS entries on database migration. * * @param db - * The {@link SQLiteDatabase}. + * The {@link SQLiteDatabase}. * @param taskId - * the row id of the task this property belongs to + * the row id of the task this property belongs to * @param propertyId - * the id of the property + * the id of the property * @param text - * the searchable text of the property. If the property has multiple text snippets to search in, concat them separated by a space. + * the searchable text of the property. If the property has multiple + * text snippets to search in, concat them separated by a space. */ - protected void updateFTSEntry(SQLiteDatabase db, long taskId, long propertyId, String text) - { + protected void updateFTSEntry(SQLiteDatabase db, long taskId, long propertyId, String text) { FTSDatabaseHelper.updatePropertyFTSEntry(db, taskId, propertyId, text); } - - public ContentValues cloneForNewTask(long newTaskId, ContentValues values) - { + public ContentValues cloneForNewTask(long newTaskId, ContentValues values) { ContentValues newValues = new ContentValues(values); newValues.remove(Properties.PROPERTY_ID); newValues.put(Properties.TASK_ID, newTaskId); return newValues; - } - - - ; + }; } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/PropertyHandlerFactory.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/PropertyHandlerFactory.java index 0e19463387293353b9e7d44803932cace509a407..c4f082789e5d7e6d0679ab55a15b7ed7ac6ac7b6 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/PropertyHandlerFactory.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/PropertyHandlerFactory.java @@ -20,40 +20,34 @@ import org.dmfs.tasks.contract.TaskContract.Property.Alarm; import org.dmfs.tasks.contract.TaskContract.Property.Category; import org.dmfs.tasks.contract.TaskContract.Property.Relation; - /** - * A factory that creates the matching {@link PropertyHandler} for the given mimetype. + * A factory that creates the matching {@link PropertyHandler} for the given + * mimetype. * * @author Tobias Reinsch */ -public class PropertyHandlerFactory -{ - private final static PropertyHandler CATEGORY_HANDLER = new CategoryHandler(); - private final static PropertyHandler ALARM_HANDLER = new AlarmHandler(); - private final static PropertyHandler RELATION_HANDLER = new RelationHandler(); - private final static PropertyHandler DEFAULT_PROPERTY_HANDLER = new DefaultPropertyHandler(); - +public class PropertyHandlerFactory { + private static final PropertyHandler CATEGORY_HANDLER = new CategoryHandler(); + private static final PropertyHandler ALARM_HANDLER = new AlarmHandler(); + private static final PropertyHandler RELATION_HANDLER = new RelationHandler(); + private static final PropertyHandler DEFAULT_PROPERTY_HANDLER = new DefaultPropertyHandler(); /** * Creates a specific {@link PropertyHandler}. * * @param mimeType - * The mimetype of the property. - * - * @return The matching {@link PropertyHandler} for the given mimetype or null + * The mimetype of the property. + * @return The matching {@link PropertyHandler} for the given mimetype or + * null */ - public static PropertyHandler get(String mimeType) - { - if (Category.CONTENT_ITEM_TYPE.equals(mimeType)) - { + public static PropertyHandler get(String mimeType) { + if (Category.CONTENT_ITEM_TYPE.equals(mimeType)) { return CATEGORY_HANDLER; } - if (Alarm.CONTENT_ITEM_TYPE.equals(mimeType)) - { + if (Alarm.CONTENT_ITEM_TYPE.equals(mimeType)) { return ALARM_HANDLER; } - if (Relation.CONTENT_ITEM_TYPE.equals(mimeType)) - { + if (Relation.CONTENT_ITEM_TYPE.equals(mimeType)) { return RELATION_HANDLER; } return DEFAULT_PROPERTY_HANDLER; diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/RelationHandler.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/RelationHandler.java index 45677beca57696d07ef413113289a42641fa372c..0837cef8a961b4e8c486d68b58d89add538fbbf6 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/RelationHandler.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/handler/RelationHandler.java @@ -19,145 +19,118 @@ package org.dmfs.provider.tasks.handler; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.tasks.contract.TaskContract.Property.Relation; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * Handles any inserts, updates and deletes on the relations table. * * @author Marten Gajda */ -public class RelationHandler extends PropertyHandler -{ +public class RelationHandler extends PropertyHandler { @Override - public ContentValues validateValues(SQLiteDatabase db, long taskId, long propertyId, boolean isNew, ContentValues values, boolean isSyncAdapter) - { - if (values.containsKey(Relation.RELATED_CONTENT_URI)) - { + public ContentValues validateValues(SQLiteDatabase db, long taskId, long propertyId, boolean isNew, + ContentValues values, boolean isSyncAdapter) { + if (values.containsKey(Relation.RELATED_CONTENT_URI)) { throw new IllegalArgumentException("setting of RELATED_CONTENT_URI not allowed"); } Long id = values.getAsLong(Relation.RELATED_ID); String uid = values.getAsString(Relation.RELATED_UID); - if (id == null && uid != null) - { + if (id == null && uid != null) { values.putNull(Relation.RELATED_ID); - } - else if (id != null && uid == null) - { + } else if (id != null && uid == null) { values.putNull(Relation.RELATED_UID); - } - else - { - throw new IllegalArgumentException("exactly one of RELATED_ID, RELATED_UID and RELATED_URI must be non-null"); + } else { + throw new IllegalArgumentException( + "exactly one of RELATED_ID, RELATED_UID and RELATED_URI must be non-null"); } return values; } - @Override - public long insert(SQLiteDatabase db, long taskId, ContentValues values, boolean isSyncAdapter) - { + public long insert(SQLiteDatabase db, long taskId, ContentValues values, boolean isSyncAdapter) { validateValues(db, taskId, -1, true, values, isSyncAdapter); resolveFields(db, values); updateParentId(db, taskId, values, null); return super.insert(db, taskId, values, isSyncAdapter); } - @Override - public ContentValues cloneForNewTask(long newTaskId, ContentValues values) - { + public ContentValues cloneForNewTask(long newTaskId, ContentValues values) { ContentValues newValues = super.cloneForNewTask(newTaskId, values); newValues.remove(Relation.RELATED_CONTENT_URI); return newValues; } - @Override - public int update(SQLiteDatabase db, long taskId, long propertyId, ContentValues values, Cursor oldValues, boolean isSyncAdapter) - { + public int update(SQLiteDatabase db, long taskId, long propertyId, ContentValues values, Cursor oldValues, + boolean isSyncAdapter) { validateValues(db, taskId, propertyId, false, values, isSyncAdapter); resolveFields(db, values); updateParentId(db, taskId, values, oldValues); return super.update(db, taskId, propertyId, values, oldValues, isSyncAdapter); } - @Override - public int delete(SQLiteDatabase db, long taskId, long propertyId, Cursor oldValues, boolean isSyncAdapter) - { + public int delete(SQLiteDatabase db, long taskId, long propertyId, Cursor oldValues, boolean isSyncAdapter) { clearParentId(db, taskId, oldValues); return super.delete(db, taskId, propertyId, oldValues, isSyncAdapter); } - /** - * Resolve _id or _uid, depending of which value is given. + * Resolve _id or _uid, depending of which value is + * given. + * *

- * TODO: store links into the calendar provider if we find an event that matches the UID. - *

+ * TODO: store links into the calendar provider if we find an event that matches + * the UID. * * @param db - * The task database. + * The task database. * @param values - * The {@link ContentValues}. + * The {@link ContentValues}. */ - private void resolveFields(SQLiteDatabase db, ContentValues values) - { + private void resolveFields(SQLiteDatabase db, ContentValues values) { Long id = values.getAsLong(Relation.RELATED_ID); String uid = values.getAsString(Relation.RELATED_UID); - if (id != null) - { + if (id != null) { values.put(Relation.RELATED_UID, resolveTaskStringField(db, Tasks._ID, id.toString(), Tasks._UID)); - } - else if (uid != null) - { + } else if (uid != null) { values.put(Relation.RELATED_ID, resolveTaskLongField(db, Tasks._UID, uid, Tasks._ID)); } } - - private Long resolveTaskLongField(SQLiteDatabase db, String selectionField, String selectionValue, String resultField) - { + private Long resolveTaskLongField(SQLiteDatabase db, String selectionField, String selectionValue, + String resultField) { String result = resolveTaskStringField(db, selectionField, selectionValue, resultField); - if (result != null) - { + if (result != null) { return Long.parseLong(result); } return null; } - - private String resolveTaskStringField(SQLiteDatabase db, String selectionField, String selectionValue, String resultField) - { - Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, new String[] { resultField }, selectionField + "=?", new String[] { selectionValue }, null, null, - null); - if (c != null) - { - try - { - if (c.moveToNext()) - { + private String resolveTaskStringField(SQLiteDatabase db, String selectionField, String selectionValue, + String resultField) { + Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, new String[]{resultField}, selectionField + "=?", + new String[]{selectionValue}, null, null, null); + if (c != null) { + try { + if (c.moveToNext()) { return c.getString(0); } - } - finally - { + } finally { c.close(); } } return null; } - /** * Update {@link Tasks#PARENT_ID} when a parent is assigned to a child. * @@ -166,59 +139,53 @@ public class RelationHandler extends PropertyHandler * @param values * @param oldValues */ - private void updateParentId(SQLiteDatabase db, long taskId, ContentValues values, Cursor oldValues) - { + private void updateParentId(SQLiteDatabase db, long taskId, ContentValues values, Cursor oldValues) { int type; - if (values.containsKey(Relation.RELATED_TYPE)) - { + if (values.containsKey(Relation.RELATED_TYPE)) { type = values.getAsInteger(Relation.RELATED_TYPE); - } - else - { + } else { type = oldValues.getInt(oldValues.getColumnIndex(Relation.RELATED_TYPE)); } - if (type == Relation.RELTYPE_PARENT) - { - // this is a link to the parent, we need to update the PARENT_ID of this task, if we can + if (type == Relation.RELTYPE_PARENT) { + // this is a link to the parent, we need to update the PARENT_ID of this task, + // if we can - if (values.containsKey(Relation.RELATED_ID)) - { + if (values.containsKey(Relation.RELATED_ID)) { ContentValues taskValues = new ContentValues(1); taskValues.put(Tasks.PARENT_ID, values.getAsLong(Relation.RELATED_ID)); db.update(TaskDatabaseHelper.Tables.TASKS, taskValues, Tasks._ID + "=" + taskId, null); } - // else: the parent task is probably not synced yet, we have to fix this in RelationUpdaterHook - } - else if (type == Relation.RELTYPE_CHILD) - { + // else: the parent task is probably not synced yet, we have to fix this in + // RelationUpdaterHook + } else if (type == Relation.RELTYPE_CHILD) { // this is a link to a child, we need to update the PARENT_ID of the linked task - if (values.getAsLong(Relation.RELATED_ID) != null) - { + if (values.getAsLong(Relation.RELATED_ID) != null) { ContentValues taskValues = new ContentValues(1); taskValues.put(Tasks.PARENT_ID, taskId); - db.update(TaskDatabaseHelper.Tables.TASKS, taskValues, Tasks._ID + "=" + values.getAsLong(Relation.RELATED_ID), null); + db.update(TaskDatabaseHelper.Tables.TASKS, taskValues, + Tasks._ID + "=" + values.getAsLong(Relation.RELATED_ID), null); } - // else: the child task is probably not synced yet, we have to fix this in RelationUpdaterHook - } - else if (type == Relation.RELTYPE_SIBLING) - { - // this is a link to a sibling, we need to copy the PARENT_ID of the linked task to this task - if (values.getAsLong(Relation.RELATED_ID) != null) - { + // else: the child task is probably not synced yet, we have to fix this in + // RelationUpdaterHook + } else if (type == Relation.RELTYPE_SIBLING) { + // this is a link to a sibling, we need to copy the PARENT_ID of the linked task + // to this task + if (values.getAsLong(Relation.RELATED_ID) != null) { // get the parent of the other task first - Long otherParent = resolveTaskLongField(db, Tasks._ID, values.getAsString(Relation.RELATED_ID), Tasks.PARENT_ID); + Long otherParent = resolveTaskLongField(db, Tasks._ID, values.getAsString(Relation.RELATED_ID), + Tasks.PARENT_ID); ContentValues taskValues = new ContentValues(1); taskValues.put(Tasks.PARENT_ID, otherParent); db.update(TaskDatabaseHelper.Tables.TASKS, taskValues, Tasks._ID + "=" + taskId, null); } - // else: the sibling task is probably not synced yet, we have to fix this in RelationUpdaterHook + // else: the sibling task is probably not synced yet, we have to fix this in + // RelationUpdaterHook } } - /** * Clear {@link Tasks#PARENT_ID} if a link is removed. * @@ -226,41 +193,41 @@ public class RelationHandler extends PropertyHandler * @param taskId * @param oldValues */ - private void clearParentId(SQLiteDatabase db, long taskId, Cursor oldValues) - { + private void clearParentId(SQLiteDatabase db, long taskId, Cursor oldValues) { int type = oldValues.getInt(oldValues.getColumnIndex(Relation.RELATED_TYPE)); /* - * This is more complicated than it may sound. We don't know the order in which relations are created, updated or removed. So it's possible that a new - * parent relationship has been created and the old one is removed afterwards. In that case we can not simply clear the PARENT_ID. + * This is more complicated than it may sound. We don't know the order in which + * relations are created, updated or removed. So it's possible that a new parent + * relationship has been created and the old one is removed afterwards. In that + * case we can not simply clear the PARENT_ID. * * FIXME: For now we ignore that fact. But we should fix it. */ - if (type == Relation.RELTYPE_PARENT) - { - // this was a link to the parent, we're orphaned now, so clear PARENT_ID of this task + if (type == Relation.RELTYPE_PARENT) { + // this was a link to the parent, we're orphaned now, so clear PARENT_ID of this + // task ContentValues taskValues = new ContentValues(1); taskValues.putNull(Tasks.PARENT_ID); db.update(TaskDatabaseHelper.Tables.TASKS, taskValues, Tasks._ID + "=" + taskId, null); - } - else if (type == Relation.RELTYPE_CHILD) - { + } else if (type == Relation.RELTYPE_CHILD) { // this was a link to a child, the child is orphaned now, clear its PARENT_ID int relIdCol = oldValues.getColumnIndex(Relation.RELATED_ID); - if (!oldValues.isNull(relIdCol)) - { + if (!oldValues.isNull(relIdCol)) { ContentValues taskValues = new ContentValues(1); taskValues.putNull(Tasks.PARENT_ID); - db.update(TaskDatabaseHelper.Tables.TASKS, taskValues, Tasks._ID + "=" + oldValues.getLong(relIdCol), null); + db.update(TaskDatabaseHelper.Tables.TASKS, taskValues, Tasks._ID + "=" + oldValues.getLong(relIdCol), + null); } } // else if (type == Relation.RELTYPE_SIBLING) // { /* - * This was a link to a sibling, since it's no longer our sibling either it or we're orphaned now We won't know unless we check all relations. + * This was a link to a sibling, since it's no longer our sibling either it or + * we're orphaned now We won't know unless we check all relations. * * FIXME: properly handle this case */ diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractInstanceAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractInstanceAdapter.java index 4cae1c815af4a9691982ba3b13ed03de100cc60f..29cb22fc6c180f826a7baf7f30b2133b719097db 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractInstanceAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractInstanceAdapter.java @@ -18,20 +18,17 @@ package org.dmfs.provider.tasks.model; import android.content.ContentUris; import android.net.Uri; - import org.dmfs.tasks.contract.TaskContract; - /** - * An abstract implementation of a {@link InstanceAdapter} to server as the base for more concrete adapters. + * An abstract implementation of a {@link InstanceAdapter} to server as the base + * for more concrete adapters. * * @author Marten Gajda */ -public abstract class AbstractInstanceAdapter implements InstanceAdapter -{ +public abstract class AbstractInstanceAdapter implements InstanceAdapter { @Override - public final Uri uri(String authority) - { + public final Uri uri(String authority) { return ContentUris.withAppendedId(TaskContract.Instances.getContentUri(authority), id()); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractListAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractListAdapter.java index 80478e3e7948d3a2c7a812592cd09b453c7292ba..56ad354a161a80c073a1e41976f3961f34b03060 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractListAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractListAdapter.java @@ -19,38 +19,30 @@ package org.dmfs.provider.tasks.model; import android.content.ContentUris; import android.content.ContentValues; import android.net.Uri; - import org.dmfs.provider.tasks.model.adapters.FieldAdapter; import org.dmfs.tasks.contract.TaskContract; - /** - * An abstract implementation of a {@link ListAdapter} to server as the base for more concrete adapters. + * An abstract implementation of a {@link ListAdapter} to server as the base for + * more concrete adapters. * * @author Marten Gajda */ -public abstract class AbstractListAdapter implements ListAdapter -{ +public abstract class AbstractListAdapter implements ListAdapter { private final ContentValues mState = new ContentValues(10); - @Override - public Uri uri(String authority) - { + public Uri uri(String authority) { return ContentUris.withAppendedId(TaskContract.TaskLists.getContentUri(authority), id()); } - @Override - public T getState(FieldAdapter stateFieldAdater) - { + public T getState(FieldAdapter stateFieldAdater) { return stateFieldAdater.getFrom(mState); } - @Override - public void setState(FieldAdapter stateFieldAdater, T value) - { + public void setState(FieldAdapter stateFieldAdater, T value) { stateFieldAdater.setIn(mState, value); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractTaskAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractTaskAdapter.java index 1f23f77359241ca247919ee04542b85f4069885c..bcacac779516fe1a18814af15b75366d4746eab3 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractTaskAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/AbstractTaskAdapter.java @@ -19,53 +19,44 @@ package org.dmfs.provider.tasks.model; import android.content.ContentUris; import android.content.ContentValues; import android.net.Uri; - import org.dmfs.provider.tasks.model.adapters.FieldAdapter; import org.dmfs.tasks.contract.TaskContract; - /** - * An abstract implementation of a {@link TaskAdapter} to server as the base for more concrete adapters. + * An abstract implementation of a {@link TaskAdapter} to server as the base for + * more concrete adapters. * * @author Marten Gajda */ -public abstract class AbstractTaskAdapter implements TaskAdapter -{ +public abstract class AbstractTaskAdapter implements TaskAdapter { private final ContentValues mState = new ContentValues(10); - @Override - public Uri uri(String authority) - { + public Uri uri(String authority) { return ContentUris.withAppendedId(TaskContract.Tasks.getContentUri(authority), id()); } - @Override - public boolean isRecurring() - { - // recurring tasks must have an RRULE or RDATEs and at least one of DTSTART and DUE date - return (valueOf(RRULE) != null || valueOf(RDATE).iterator().hasNext()) && (valueOf(DTSTART) != null || valueOf(DUE) != null); + public boolean isRecurring() { + // recurring tasks must have an RRULE or RDATEs and at least one of DTSTART and + // DUE date + return (valueOf(RRULE) != null || valueOf(RDATE).iterator().hasNext()) + && (valueOf(DTSTART) != null || valueOf(DUE) != null); } - @Override - public boolean recurrenceUpdated() - { - return isUpdated(RRULE) || isUpdated(DTSTART) || isUpdated(DUE) || isUpdated(DURATION) || isUpdated(RDATE) || isUpdated(EXDATE); + public boolean recurrenceUpdated() { + return isUpdated(RRULE) || isUpdated(DTSTART) || isUpdated(DUE) || isUpdated(DURATION) || isUpdated(RDATE) + || isUpdated(EXDATE); } - @Override - public T getState(FieldAdapter stateFieldAdater) - { + public T getState(FieldAdapter stateFieldAdater) { return stateFieldAdater.getFrom(mState); } - @Override - public void setState(FieldAdapter stateFieldAdater, T value) - { + public void setState(FieldAdapter stateFieldAdater, T value) { stateFieldAdater.setIn(mState, value); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesInstanceAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesInstanceAdapter.java index 58a7e54cc47faa60d82a1c4a69564db819d10a7d..bbf763b38a7cd62dc892b91a7875fda77304fa81 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesInstanceAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesInstanceAdapter.java @@ -18,144 +18,104 @@ package org.dmfs.provider.tasks.model; import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.jems.single.elementary.Reduced; import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.adapters.FieldAdapter; import org.dmfs.tasks.contract.TaskContract; - /** * A {@link TaskAdapter} for tasks that are stored in a {@link ContentValues}. * * @author Marten Gajda */ -public class ContentValuesInstanceAdapter extends AbstractInstanceAdapter -{ +public class ContentValuesInstanceAdapter extends AbstractInstanceAdapter { private long mId; private final ContentValues mValues; - - public ContentValuesInstanceAdapter(ContentValues values) - { + public ContentValuesInstanceAdapter(ContentValues values) { this(-1L, values); } - - public ContentValuesInstanceAdapter(long id, ContentValues values) - { + public ContentValuesInstanceAdapter(long id, ContentValues values) { mId = id; mValues = values; } - @Override - public long id() - { + public long id() { return mId; } - @Override - public T valueOf(FieldAdapter fieldAdapter) - { + public T valueOf(FieldAdapter fieldAdapter) { return fieldAdapter.getFrom(mValues); } - @Override - public T oldValueOf(FieldAdapter fieldAdapter) - { + public T oldValueOf(FieldAdapter fieldAdapter) { return null; } - @Override - public boolean isUpdated(FieldAdapter fieldAdapter) - { + public boolean isUpdated(FieldAdapter fieldAdapter) { return fieldAdapter.isSetIn(mValues); } - @Override - public boolean isWriteable() - { + public boolean isWriteable() { return true; } - @Override - public boolean hasUpdates() - { + public boolean hasUpdates() { return mValues.size() > 0; } - @Override - public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException - { + public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException { fieldAdapter.setIn(mValues, value); } - @Override - public void unset(FieldAdapter fieldAdapter) throws IllegalStateException - { + public void unset(FieldAdapter fieldAdapter) throws IllegalStateException { fieldAdapter.removeFrom(mValues); } - @Override - public int commit(SQLiteDatabase db) - { - if (mValues.size() == 0) - { + public int commit(SQLiteDatabase db) { + if (mValues.size() == 0) { return 0; } - if (mId < 0) - { + if (mId < 0) { mId = db.insert(TaskDatabaseHelper.Tables.TASKS, null, mValues); return mId > 0 ? 1 : 0; - } - else - { + } else { return db.update(TaskDatabaseHelper.Tables.TASKS, mValues, TaskContract.TaskColumns._ID + "=" + mId, null); } } - @Override - public T getState(FieldAdapter stateFieldAdater) - { + public T getState(FieldAdapter stateFieldAdater) { return null; } - @Override - public void setState(FieldAdapter stateFieldAdater, T value) - { - + public void setState(FieldAdapter stateFieldAdater, T value) { } - @Override - public InstanceAdapter duplicate() - { + public InstanceAdapter duplicate() { return new ContentValuesInstanceAdapter(new ContentValues(mValues)); } - @Override - public TaskAdapter taskAdapter() - { + public TaskAdapter taskAdapter() { // make sure we remove any instance fields - return new ContentValuesTaskAdapter(new Reduced( - () -> new ContentValues(mValues), - (contentValues, column) -> { + return new ContentValuesTaskAdapter( + new Reduced(() -> new ContentValues(mValues), (contentValues, column) -> { contentValues.remove(column); return contentValues; - }, - INSTANCE_COLUMN_NAMES).value()); + }, INSTANCE_COLUMN_NAMES).value()); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesListAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesListAdapter.java index d44184819dd6b4f0285171edf7aee079de7d6405..3be60aeb07042aa177d875f433d9ff50fdebde93 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesListAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesListAdapter.java @@ -18,113 +18,83 @@ package org.dmfs.provider.tasks.model; import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.adapters.FieldAdapter; import org.dmfs.tasks.contract.TaskContract; - /** * @author Marten Gajda */ -public class ContentValuesListAdapter extends AbstractListAdapter -{ +public class ContentValuesListAdapter extends AbstractListAdapter { private long mId; private final ContentValues mValues; - - public ContentValuesListAdapter(ContentValues values) - { + public ContentValuesListAdapter(ContentValues values) { this(-1L, values); } - - public ContentValuesListAdapter(long id, ContentValues values) - { + public ContentValuesListAdapter(long id, ContentValues values) { mId = id; mValues = values; } - @Override - public long id() - { + public long id() { return mId; } - @Override - public T valueOf(FieldAdapter fieldAdapter) - { + public T valueOf(FieldAdapter fieldAdapter) { return fieldAdapter.getFrom(mValues); } - @Override - public T oldValueOf(FieldAdapter fieldAdapter) - { + public T oldValueOf(FieldAdapter fieldAdapter) { return null; } - @Override - public boolean isUpdated(FieldAdapter fieldAdapter) - { + public boolean isUpdated(FieldAdapter fieldAdapter) { return fieldAdapter.isSetIn(mValues); } - @Override - public boolean isWriteable() - { + public boolean isWriteable() { return true; } - @Override - public boolean hasUpdates() - { + public boolean hasUpdates() { return mValues.size() > 0; } - @Override - public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException - { + public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException { fieldAdapter.setIn(mValues, value); } - @Override - public void unset(FieldAdapter fieldAdapter) throws IllegalStateException - { + public void unset(FieldAdapter fieldAdapter) throws IllegalStateException { fieldAdapter.removeFrom(mValues); } - @Override - public int commit(SQLiteDatabase db) - { - if (mValues.size() == 0) - { + public int commit(SQLiteDatabase db) { + if (mValues.size() == 0) { return 0; } - if (mId < 0) - { + if (mId < 0) { mId = db.insert(TaskDatabaseHelper.Tables.LISTS, null, mValues); return mId > 0 ? 1 : 0; - } - else - { - return db.update(TaskDatabaseHelper.Tables.LISTS, mValues, TaskContract.TaskListColumns._ID + "=" + mId, null); + } else { + return db.update(TaskDatabaseHelper.Tables.LISTS, mValues, TaskContract.TaskListColumns._ID + "=" + mId, + null); } } - @Override - public ListAdapter duplicate() - { + public ListAdapter duplicate() { return new ContentValuesListAdapter(new ContentValues(mValues)); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesTaskAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesTaskAdapter.java index c8a3b8d13d8c2b75d348ff08aa10658f93eba400..5aa0e0cd352e6d73755a9641250faabb54cda961 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesTaskAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ContentValuesTaskAdapter.java @@ -18,115 +18,84 @@ package org.dmfs.provider.tasks.model; import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.adapters.FieldAdapter; import org.dmfs.tasks.contract.TaskContract; - /** * A {@link TaskAdapter} for tasks that are stored in a {@link ContentValues}. * * @author Marten Gajda */ -public class ContentValuesTaskAdapter extends AbstractTaskAdapter -{ +public class ContentValuesTaskAdapter extends AbstractTaskAdapter { private long mId; private final ContentValues mValues; - - public ContentValuesTaskAdapter(ContentValues values) - { + public ContentValuesTaskAdapter(ContentValues values) { this(-1L, values); } - - public ContentValuesTaskAdapter(long id, ContentValues values) - { + public ContentValuesTaskAdapter(long id, ContentValues values) { mId = id; mValues = values; } - @Override - public long id() - { + public long id() { return mId; } - @Override - public T valueOf(FieldAdapter fieldAdapter) - { + public T valueOf(FieldAdapter fieldAdapter) { return fieldAdapter.getFrom(mValues); } - @Override - public T oldValueOf(FieldAdapter fieldAdapter) - { + public T oldValueOf(FieldAdapter fieldAdapter) { return null; } - @Override - public boolean isUpdated(FieldAdapter fieldAdapter) - { + public boolean isUpdated(FieldAdapter fieldAdapter) { return fieldAdapter.isSetIn(mValues); } - @Override - public boolean isWriteable() - { + public boolean isWriteable() { return true; } - @Override - public boolean hasUpdates() - { + public boolean hasUpdates() { return mValues.size() > 0; } - @Override - public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException - { + public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException { fieldAdapter.setIn(mValues, value); } - @Override - public void unset(FieldAdapter fieldAdapter) throws IllegalStateException - { + public void unset(FieldAdapter fieldAdapter) throws IllegalStateException { fieldAdapter.removeFrom(mValues); } - @Override - public int commit(SQLiteDatabase db) - { - if (mValues.size() == 0) - { + public int commit(SQLiteDatabase db) { + if (mValues.size() == 0) { return 0; } - if (mId < 0) - { + if (mId < 0) { mId = db.insert(TaskDatabaseHelper.Tables.TASKS, null, mValues); return mId > 0 ? 1 : 0; - } - else - { + } else { return db.update(TaskDatabaseHelper.Tables.TASKS, mValues, TaskContract.TaskColumns._ID + "=" + mId, null); } } - @Override - public TaskAdapter duplicate() - { + public TaskAdapter duplicate() { return new ContentValuesTaskAdapter(new ContentValues(mValues)); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesInstanceAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesInstanceAdapter.java index 6213cb378f3816b85b9ec1d68f4e5a06f7cdde9e..06dd065f2099cfe0a381a0d03a07d9f49d10cf75 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesInstanceAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesInstanceAdapter.java @@ -20,7 +20,7 @@ import android.content.ContentValues; import android.database.Cursor; import android.database.MatrixCursor; import android.database.sqlite.SQLiteDatabase; - +import java.util.ArrayList; import org.dmfs.iterables.decorators.Sieved; import org.dmfs.iterables.elementary.Seq; import org.dmfs.jems.iterable.decorators.Mapped; @@ -31,75 +31,56 @@ import org.dmfs.provider.tasks.model.adapters.FieldAdapter; import org.dmfs.provider.tasks.utils.ContainsValues; import org.dmfs.tasks.contract.TaskContract; -import java.util.ArrayList; - - /** - * An {@link InstanceAdapter} that adapts a {@link Cursor} and a {@link ContentValues} instance. All changes are written to the {@link ContentValues} and can be - * stored in the database with {@link #commit(SQLiteDatabase)}. + * An {@link InstanceAdapter} that adapts a {@link Cursor} and a + * {@link ContentValues} instance. All changes are written to the + * {@link ContentValues} and can be stored in the database with + * {@link #commit(SQLiteDatabase)}. * * @author Marten Gajda */ -public class CursorContentValuesInstanceAdapter extends AbstractInstanceAdapter -{ +public class CursorContentValuesInstanceAdapter extends AbstractInstanceAdapter { private final long mId; private final Cursor mCursor; private final ContentValues mValues; - - public CursorContentValuesInstanceAdapter(Cursor cursor, ContentValues values) - { - if (cursor == null && !_ID.existsIn(values)) - { + public CursorContentValuesInstanceAdapter(Cursor cursor, ContentValues values) { + if (cursor == null && !_ID.existsIn(values)) { mId = -1L; - } - else - { + } else { mId = _ID.getFrom(cursor); } mCursor = cursor; mValues = values; } - - public CursorContentValuesInstanceAdapter(long id, Cursor cursor, ContentValues values) - { + public CursorContentValuesInstanceAdapter(long id, Cursor cursor, ContentValues values) { mId = id; mCursor = cursor; mValues = values; } - @Override - public long id() - { + public long id() { return mId; } - @Override - public T valueOf(FieldAdapter fieldAdapter) - { - if (mValues == null) - { + public T valueOf(FieldAdapter fieldAdapter) { + if (mValues == null) { return fieldAdapter.getFrom(mCursor); } return fieldAdapter.getFrom(mCursor, mValues); } - @Override - public T oldValueOf(FieldAdapter fieldAdapter) - { + public T oldValueOf(FieldAdapter fieldAdapter) { return fieldAdapter.getFrom(mCursor); } - @Override - public boolean isUpdated(FieldAdapter fieldAdapter) - { - if (mValues == null || !fieldAdapter.isSetIn(mValues)) - { + public boolean isUpdated(FieldAdapter fieldAdapter) { + if (mValues == null || !fieldAdapter.isSetIn(mValues)) { return false; } Object oldValue = fieldAdapter.getFrom(mCursor); @@ -108,72 +89,52 @@ public class CursorContentValuesInstanceAdapter extends AbstractInstanceAdapter return oldValue == null && newValue != null || oldValue != null && !oldValue.equals(newValue); } - @Override - public boolean isWriteable() - { + public boolean isWriteable() { return mValues != null; } - @Override - public boolean hasUpdates() - { + public boolean hasUpdates() { return mValues != null && mValues.size() > 0 && !new ContainsValues(mValues).satisfiedBy(mCursor); } - @Override - public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException - { + public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException { fieldAdapter.setIn(mValues, value); } - @Override - public void unset(FieldAdapter fieldAdapter) throws IllegalStateException - { + public void unset(FieldAdapter fieldAdapter) throws IllegalStateException { fieldAdapter.removeFrom(mValues); } - @Override - public int commit(SQLiteDatabase db) - { - if (mValues.size() == 0) - { + public int commit(SQLiteDatabase db) { + if (mValues.size() == 0) { return 0; } return db.update(TaskDatabaseHelper.Tables.TASKS, mValues, TaskContract.TaskColumns._ID + "=" + mId, null); } - @Override - public T getState(FieldAdapter stateFieldAdater) - { + public T getState(FieldAdapter stateFieldAdater) { return null; } - @Override - public void setState(FieldAdapter stateFieldAdater, T value) - { - + public void setState(FieldAdapter stateFieldAdater, T value) { } - @Override - public InstanceAdapter duplicate() - { + public InstanceAdapter duplicate() { ContentValues newValues = new ContentValues(mValues); // copy all columns (except _ID) that are not in the values yet - for (int i = 0, count = mCursor.getColumnCount(); i < count; ++i) - { + for (int i = 0, count = mCursor.getColumnCount(); i < count; ++i) { String column = mCursor.getColumnName(i); - if (!newValues.containsKey(column) && !TaskContract.Instances._ID.equals(column)) - { + if (!newValues.containsKey(column) && !TaskContract.Instances._ID.equals(column)) { newValues.put(column, mCursor.getString(i)); } } @@ -181,31 +142,26 @@ public class CursorContentValuesInstanceAdapter extends AbstractInstanceAdapter return new ContentValuesInstanceAdapter(newValues); } - @Override - public TaskAdapter taskAdapter() - { + public TaskAdapter taskAdapter() { // make sure we remove any instance fields - ContentValues values = new Reduced( - () -> new ContentValues(mValues), + ContentValues values = new Reduced(() -> new ContentValues(mValues), (contentValues, column) -> { contentValues.remove(column); return contentValues; - }, - INSTANCE_COLUMN_NAMES).value(); + }, INSTANCE_COLUMN_NAMES).value(); // create a new cursor which doesn't contain the instance columns - String[] cursorColumns = new Collected<>( - ArrayList::new, - new Sieved<>(col -> !INSTANCE_COLUMN_NAMES.contains(col), new Seq<>(mCursor.getColumnNames()))) - .value().toArray(new String[0]); + String[] cursorColumns = new Collected<>(ArrayList::new, + new Sieved<>(col -> !INSTANCE_COLUMN_NAMES.contains(col), new Seq<>(mCursor.getColumnNames()))).value() + .toArray(new String[0]); MatrixCursor cursor = new MatrixCursor(cursorColumns); cursor.addRow( new Mapped<>( - column -> mCursor.getType(column) == Cursor.FIELD_TYPE_BLOB ? mCursor.getBlob(column) : mCursor.getString(column), - new Mapped<>( - mCursor::getColumnIndex, - new Seq<>(cursorColumns)))); + column -> mCursor.getType(column) == Cursor.FIELD_TYPE_BLOB + ? mCursor.getBlob(column) + : mCursor.getString(column), + new Mapped<>(mCursor::getColumnIndex, new Seq<>(cursorColumns)))); cursor.moveToFirst(); return new CursorContentValuesTaskAdapter(valueOf(InstanceAdapter.TASK_ID), cursor, values); } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesListAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesListAdapter.java index 4bdffb58d0d0701a66185a40253969da7cb182ff..f41268b8fb351d594a8b4a36f9fb5b97fd74ced8 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesListAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesListAdapter.java @@ -19,57 +19,43 @@ package org.dmfs.provider.tasks.model; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.adapters.FieldAdapter; import org.dmfs.provider.tasks.utils.ContainsValues; import org.dmfs.tasks.contract.TaskContract; - /** * @author Marten Gajda */ -public class CursorContentValuesListAdapter extends AbstractListAdapter -{ +public class CursorContentValuesListAdapter extends AbstractListAdapter { private final long mId; private final Cursor mCursor; private final ContentValues mValues; - - public CursorContentValuesListAdapter(long id, Cursor cursor, ContentValues values) - { + public CursorContentValuesListAdapter(long id, Cursor cursor, ContentValues values) { mId = id; mCursor = cursor; mValues = values; } - @Override - public long id() - { + public long id() { return mId; } - @Override - public T valueOf(FieldAdapter fieldAdapter) - { + public T valueOf(FieldAdapter fieldAdapter) { return fieldAdapter.getFrom(mCursor, mValues); } - @Override - public T oldValueOf(FieldAdapter fieldAdapter) - { + public T oldValueOf(FieldAdapter fieldAdapter) { return fieldAdapter.getFrom(mCursor); } - @Override - public boolean isUpdated(FieldAdapter fieldAdapter) - { - if (mValues == null || !fieldAdapter.isSetIn(mValues)) - { + public boolean isUpdated(FieldAdapter fieldAdapter) { + if (mValues == null || !fieldAdapter.isSetIn(mValues)) { return false; } Object oldValue = fieldAdapter.getFrom(mCursor); @@ -78,58 +64,43 @@ public class CursorContentValuesListAdapter extends AbstractListAdapter return oldValue == null && newValue != null || oldValue != null && !oldValue.equals(newValue); } - @Override - public boolean isWriteable() - { + public boolean isWriteable() { return true; } - @Override - public boolean hasUpdates() - { + public boolean hasUpdates() { return mValues != null && mValues.size() > 0 && !new ContainsValues(mValues).satisfiedBy(mCursor); } - @Override - public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException - { + public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException { fieldAdapter.setIn(mValues, value); } - @Override - public void unset(FieldAdapter fieldAdapter) throws IllegalStateException - { + public void unset(FieldAdapter fieldAdapter) throws IllegalStateException { fieldAdapter.removeFrom(mValues); } - @Override - public int commit(SQLiteDatabase db) - { - if (mValues.size() == 0) - { + public int commit(SQLiteDatabase db) { + if (mValues.size() == 0) { return 0; } return db.update(TaskDatabaseHelper.Tables.LISTS, mValues, TaskContract.TaskListColumns._ID + "=" + mId, null); } - @Override - public ListAdapter duplicate() - { + public ListAdapter duplicate() { ContentValues newValues = new ContentValues(mValues); // copy all columns (except _ID) that are not in the values yet - for (int i = 0, count = mCursor.getColumnCount(); i < count; ++i) - { + for (int i = 0, count = mCursor.getColumnCount(); i < count; ++i) { String column = mCursor.getColumnName(i); - if (!newValues.containsKey(column) && !TaskContract.Tasks._ID.equals(column)) - { + if (!newValues.containsKey(column) && !TaskContract.Tasks._ID.equals(column)) { newValues.put(column, mCursor.getString(i)); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesTaskAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesTaskAdapter.java index 0ed20dfcdaa0858476ad14baeb0e15afb2c44cad..2ed4702d0d75c5ddc668c85c3c2ed73e1b7e2138 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesTaskAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/CursorContentValuesTaskAdapter.java @@ -19,147 +19,113 @@ package org.dmfs.provider.tasks.model; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.adapters.FieldAdapter; import org.dmfs.provider.tasks.utils.ContainsValues; import org.dmfs.tasks.contract.TaskContract; - /** - * A {@link TaskAdapter} that adapts a {@link Cursor} and a {@link ContentValues} instance. All changes are written to the {@link ContentValues} and can be - * stored in the database with {@link #commit(SQLiteDatabase)}. + * A {@link TaskAdapter} that adapts a {@link Cursor} and a + * {@link ContentValues} instance. All changes are written to the + * {@link ContentValues} and can be stored in the database with + * {@link #commit(SQLiteDatabase)}. * * @author Marten Gajda */ -public class CursorContentValuesTaskAdapter extends AbstractTaskAdapter -{ +public class CursorContentValuesTaskAdapter extends AbstractTaskAdapter { private final long mId; private final Cursor mCursor; private final ContentValues mValues; - - public CursorContentValuesTaskAdapter(Cursor cursor, ContentValues values) - { - if (cursor == null && !_ID.existsIn(values)) - { + public CursorContentValuesTaskAdapter(Cursor cursor, ContentValues values) { + if (cursor == null && !_ID.existsIn(values)) { mId = -1L; - } - else - { + } else { mId = _ID.getFrom(cursor); } mCursor = cursor; mValues = values; } - - public CursorContentValuesTaskAdapter(long id, Cursor cursor, ContentValues values) - { + public CursorContentValuesTaskAdapter(long id, Cursor cursor, ContentValues values) { mId = id; mCursor = cursor; mValues = values; } - @Override - public long id() - { + public long id() { return mId; } - @Override - public T valueOf(FieldAdapter fieldAdapter) - { - if (mValues == null) - { + public T valueOf(FieldAdapter fieldAdapter) { + if (mValues == null) { return fieldAdapter.getFrom(mCursor); } return fieldAdapter.getFrom(mCursor, mValues); } - @Override - public T oldValueOf(FieldAdapter fieldAdapter) - { + public T oldValueOf(FieldAdapter fieldAdapter) { return fieldAdapter.getFrom(mCursor); } - @Override - public boolean isUpdated(FieldAdapter fieldAdapter) - { - if (mValues == null || !fieldAdapter.isSetIn(mValues)) - { + public boolean isUpdated(FieldAdapter fieldAdapter) { + if (mValues == null || !fieldAdapter.isSetIn(mValues)) { return false; } Object oldValue = fieldAdapter.existsIn(mCursor) ? fieldAdapter.getFrom(mCursor) : null; Object newValue = fieldAdapter.getFrom(mValues); - // we need to special case RRULE, because RecurrenceRule doesn't support `equals` - if (fieldAdapter != TaskAdapter.RRULE) - { + // we need to special case RRULE, because RecurrenceRule doesn't support + // `equals` + if (fieldAdapter != TaskAdapter.RRULE) { return oldValue == null && newValue != null || oldValue != null && !oldValue.equals(newValue); - } - else - { + } else { // in case of RRULE we compare the String values. - return oldValue == null && newValue != null || oldValue != null && (newValue == null || !oldValue.toString().equals(newValue.toString())); + return oldValue == null && newValue != null + || oldValue != null && (newValue == null || !oldValue.toString().equals(newValue.toString())); } } - @Override - public boolean isWriteable() - { + public boolean isWriteable() { return mValues != null; } - @Override - public boolean hasUpdates() - { + public boolean hasUpdates() { return mValues != null && mValues.size() > 0 && !new ContainsValues(mValues).satisfiedBy(mCursor); } - @Override - public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException - { + public void set(FieldAdapter fieldAdapter, T value) throws IllegalStateException { fieldAdapter.setIn(mValues, value); } - @Override - public void unset(FieldAdapter fieldAdapter) throws IllegalStateException - { + public void unset(FieldAdapter fieldAdapter) throws IllegalStateException { fieldAdapter.removeFrom(mValues); } - @Override - public int commit(SQLiteDatabase db) - { - if (mValues.size() == 0) - { + public int commit(SQLiteDatabase db) { + if (mValues.size() == 0) { return 0; } return db.update(TaskDatabaseHelper.Tables.TASKS, mValues, TaskContract.TaskColumns._ID + "=" + mId, null); } - @Override - public TaskAdapter duplicate() - { + public TaskAdapter duplicate() { ContentValues newValues = new ContentValues(mValues); // copy all columns (except _ID) that are not in the values yet - for (int i = 0, count = mCursor.getColumnCount(); i < count; ++i) - { + for (int i = 0, count = mCursor.getColumnCount(); i < count; ++i) { String column = mCursor.getColumnName(i); - if (!newValues.containsKey(column) && !TaskContract.Tasks._ID.equals(column)) - { + if (!newValues.containsKey(column) && !TaskContract.Tasks._ID.equals(column)) { newValues.put(column, mCursor.getString(i)); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/EntityAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/EntityAdapter.java index b3d6c7e5b623b9bab8e285af6062569cacf0e29a..9c9980bf5d79343b9046371b11df1e1f01db8b0c 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/EntityAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/EntityAdapter.java @@ -20,19 +20,18 @@ import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; - import org.dmfs.provider.tasks.model.adapters.FieldAdapter; - /** - * Adapter to read values of a specific entity type from primitive data sets like {@link Cursor}s or {@link ContentValues}s. + * Adapter to read values of a specific entity type from primitive data sets + * like {@link Cursor}s or {@link ContentValues}s. * * @author Marten Gajda */ -public interface EntityAdapter -{ +public interface EntityAdapter { /** - * Returns the row id of the entity or -1 if the entity has not been stored yet. + * Returns the row id of the entity or -1 if the entity has not + * been stored yet. * * @return The entity row id or -1. */ @@ -42,9 +41,9 @@ public interface EntityAdapter * Returns the {@link Uri} of the entity using the given authority. * * @param authority - * The authority of this provider. - * - * @return A {@link Uri} or null if this entity has not been stored yet. + * The authority of this provider. + * @return A {@link Uri} or null if this entity has not been stored + * yet. */ Uri uri(String authority); @@ -52,19 +51,18 @@ public interface EntityAdapter * Returns the value identified by the given {@link FieldAdapter}. * * @param fieldAdapter - * The {@link FieldAdapter} of the value to return. - * + * The {@link FieldAdapter} of the value to return. * @return The value, maybe be null. */ T valueOf(FieldAdapter fieldAdapter); /** - * Returns the old value identified by the given {@link FieldAdapter}. This will be equal to the value returned by {@link #valueOf(FieldAdapter)} unless it + * Returns the old value identified by the given {@link FieldAdapter}. This will + * be equal to the value returned by {@link #valueOf(FieldAdapter)} unless it * has been overridden, in which case this returns the former value. * * @param fieldAdapter - * The {@link FieldAdapter} of the value to return. - * + * The {@link FieldAdapter} of the value to return. * @return The value, maybe be null. */ T oldValueOf(FieldAdapter fieldAdapter); @@ -73,16 +71,17 @@ public interface EntityAdapter * Returns whether the given field has been overridden or not. * * @param fieldAdapter - * The {@link FieldAdapter} of the field to check. - * - * @return true if the field has been overridden, false otherwise. + * The {@link FieldAdapter} of the field to check. + * @return true if the field has been overridden, + * false otherwise. */ boolean isUpdated(FieldAdapter fieldAdapter); /** * Returns whether this adapter supports modifying values. * - * @return true if the task values can be changed by this adapter, false otherwise. + * @return true if the task values can be changed by this adapter, + * false otherwise. */ boolean isWriteable(); @@ -94,20 +93,22 @@ public interface EntityAdapter boolean hasUpdates(); /** - * Sets a value of the adapted entity. The value is identified by a {@link FieldAdapter}. + * Sets a value of the adapted entity. The value is identified by a + * {@link FieldAdapter}. * * @param fieldAdapter - * The {@link FieldAdapter} of the value to set. + * The {@link FieldAdapter} of the value to set. * @param value - * The new value. + * The new value. */ void set(FieldAdapter fieldAdapter, T value); /** - * Remove a value from the change set. In effect the respective field will keep it's old value. + * Remove a value from the change set. In effect the respective field will keep + * it's old value. * * @param fieldAdapter - * The {@link FieldAdapter} of the field to un-set. + * The {@link FieldAdapter} of the field to un-set. */ void unset(FieldAdapter fieldAdapter); @@ -115,35 +116,37 @@ public interface EntityAdapter * Commit all changes to the database. * * @param db - * A writable database. - * - * @return The number of entries affected. This may be 0 if no fields have been changed. + * A writable database. + * @return The number of entries affected. This may be 0 if no + * fields have been changed. */ int commit(SQLiteDatabase db); /** - * Return the value of a temporary state field. The state of an entity is not committed to the database, it's only bound to the instances of this + * Return the value of a temporary state field. The state of an entity is not + * committed to the database, it's only bound to the instances of this * {@link EntityAdapter} and will be lost once it gets garbage collected. * * @param stateFieldAdater - * The {@link FieldAdapter} of a state field. - * + * The {@link FieldAdapter} of a state field. * @return The value of the state field. */ T getState(FieldAdapter stateFieldAdater); /** - * Set the value of a state field. This value is not stored in the database. Instead it only exists as long as this {@link EntityAdapter} exists. + * Set the value of a state field. This value is not stored in the database. + * Instead it only exists as long as this {@link EntityAdapter} exists. * * @param stateFieldAdater - * The {@link FieldAdapter} of the state field to set. + * The {@link FieldAdapter} of the state field to set. * @param value - * The new state value. + * The new state value. */ void setState(FieldAdapter stateFieldAdater, T value); /*** - * Creates a {@link EntityAdapter} for a new entity initialized with the values of this entity (except for _ID). + * Creates a {@link EntityAdapter} for a new entity initialized with the values + * of this entity (except for _ID). * * @return A new {@link EntityAdapter} having the same values. */ diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/InstanceAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/InstanceAdapter.java index b2c9de3c651b2f5ab52d5fd6adcfdf1bdf53802d..2a0f06dacf1b59e71325f8ebcf3d80d2da82d525 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/InstanceAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/InstanceAdapter.java @@ -16,9 +16,12 @@ package org.dmfs.provider.tasks.model; +import static java.util.Arrays.asList; + import android.content.ContentValues; import android.database.Cursor; - +import java.util.Collection; +import java.util.HashSet; import org.dmfs.provider.tasks.model.adapters.DateTimeFieldAdapter; import org.dmfs.provider.tasks.model.adapters.IntegerFieldAdapter; import org.dmfs.provider.tasks.model.adapters.LongFieldAdapter; @@ -27,74 +30,49 @@ import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Instances; import org.dmfs.tasks.contract.TaskContract.Tasks; -import java.util.Collection; -import java.util.HashSet; - -import static java.util.Arrays.asList; - - /** - * Adapter to read instance values from primitive data sets like {@link Cursor}s or {@link ContentValues}s. + * Adapter to read instance values from primitive data sets like {@link Cursor}s + * or {@link ContentValues}s. * * @author Marten Gajda */ -public interface InstanceAdapter extends EntityAdapter -{ - - Collection INSTANCE_COLUMN_NAMES = new HashSet<>(asList( - TaskContract.Instances.INSTANCE_START, - TaskContract.Instances.INSTANCE_START_SORTING, - TaskContract.Instances.INSTANCE_DUE, - TaskContract.Instances.INSTANCE_DUE_SORTING, - TaskContract.Instances.INSTANCE_DURATION, - TaskContract.Instances.INSTANCE_ORIGINAL_TIME, - TaskContract.Instances.TASK_ID, - TaskContract.Instances.DISTANCE_FROM_CURRENT, - "_id:1")); +public interface InstanceAdapter extends EntityAdapter { - /** - * Adapter for the row id of a task instance. - */ + Collection INSTANCE_COLUMN_NAMES = new HashSet<>( + asList(TaskContract.Instances.INSTANCE_START, TaskContract.Instances.INSTANCE_START_SORTING, + TaskContract.Instances.INSTANCE_DUE, TaskContract.Instances.INSTANCE_DUE_SORTING, + TaskContract.Instances.INSTANCE_DURATION, TaskContract.Instances.INSTANCE_ORIGINAL_TIME, + TaskContract.Instances.TASK_ID, TaskContract.Instances.DISTANCE_FROM_CURRENT, "_id:1")); + + /** Adapter for the row id of a task instance. */ LongFieldAdapter _ID = new LongFieldAdapter(Instances._ID); - /** - * Adapter for the due date of a task instance. - */ - DateTimeFieldAdapter INSTANCE_DUE = new DateTimeFieldAdapter<>(Instances.INSTANCE_DUE, Tasks.TZ, Tasks.IS_ALLDAY); + /** Adapter for the due date of a task instance. */ + DateTimeFieldAdapter INSTANCE_DUE = new DateTimeFieldAdapter<>(Instances.INSTANCE_DUE, Tasks.TZ, + Tasks.IS_ALLDAY); - /** - * Adapter for the start date of a task instance. - */ - DateTimeFieldAdapter INSTANCE_START = new DateTimeFieldAdapter<>(Instances.INSTANCE_START, Tasks.TZ, Tasks.IS_ALLDAY); + /** Adapter for the start date of a task instance. */ + DateTimeFieldAdapter INSTANCE_START = new DateTimeFieldAdapter<>(Instances.INSTANCE_START, + Tasks.TZ, Tasks.IS_ALLDAY); - /** - * Adapter for the start sorting of a task instance. - */ + /** Adapter for the start sorting of a task instance. */ LongFieldAdapter INSTANCE_START_SORTING = new LongFieldAdapter<>(Instances.INSTANCE_START_SORTING); - /** - * Adapter for the due sorting of a task instance. - */ + /** Adapter for the due sorting of a task instance. */ LongFieldAdapter INSTANCE_DUE_SORTING = new LongFieldAdapter<>(Instances.INSTANCE_DUE_SORTING); - /** - * Adapter for the original time of a task instance. - */ - DateTimeFieldAdapter INSTANCE_ORIGINAL_TIME = new DateTimeFieldAdapter<>(Instances.INSTANCE_ORIGINAL_TIME, Tasks.TZ, Tasks.IS_ALLDAY); + /** Adapter for the original time of a task instance. */ + DateTimeFieldAdapter INSTANCE_ORIGINAL_TIME = new DateTimeFieldAdapter<>( + Instances.INSTANCE_ORIGINAL_TIME, Tasks.TZ, Tasks.IS_ALLDAY); - /** - * Adapter for the distance of a task instance from the current instance. - */ - IntegerFieldAdapter DISTANCE_FROM_CURRENT = new IntegerFieldAdapter<>(Instances.DISTANCE_FROM_CURRENT); + /** Adapter for the distance of a task instance from the current instance. */ + IntegerFieldAdapter DISTANCE_FROM_CURRENT = new IntegerFieldAdapter<>( + Instances.DISTANCE_FROM_CURRENT); - /** - * Adapter for the title of a task instance. - */ + /** Adapter for the title of a task instance. */ StringFieldAdapter TITLE = new StringFieldAdapter<>(Tasks.TITLE); - /** - * Adapter for the row id of the task. - */ + /** Adapter for the row id of the task. */ LongFieldAdapter TASK_ID = new LongFieldAdapter(Instances.TASK_ID); @Override diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ListAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ListAdapter.java index d72a673864ec17e03fe09b2e82c05ddab6423787..e62072b4f612cca7a9a2bb463f6ab670c33b6818 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ListAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/ListAdapter.java @@ -18,62 +18,45 @@ package org.dmfs.provider.tasks.model; import android.content.ContentValues; import android.database.Cursor; - import org.dmfs.provider.tasks.model.adapters.IntegerFieldAdapter; import org.dmfs.provider.tasks.model.adapters.LongFieldAdapter; import org.dmfs.provider.tasks.model.adapters.StringFieldAdapter; import org.dmfs.tasks.contract.TaskContract.TaskLists; - /** - * Adapter to read list values from primitive data sets like {@link Cursor}s or {@link ContentValues}s. + * Adapter to read list values from primitive data sets like {@link Cursor}s or + * {@link ContentValues}s. * * @author Marten Gajda */ -public interface ListAdapter extends EntityAdapter -{ - /** - * Adapter for the row id of a task list. - */ +public interface ListAdapter extends EntityAdapter { + /** Adapter for the row id of a task list. */ LongFieldAdapter _ID = new LongFieldAdapter(TaskLists._ID); - /** - * Adapter for the _sync_id of a list. - */ + /** Adapter for the _sync_id of a list. */ StringFieldAdapter SYNC_ID = new StringFieldAdapter(TaskLists._SYNC_ID); - /** - * Adapter for the sync version of a list. - */ + /** Adapter for the sync version of a list. */ StringFieldAdapter SYNC_VERSION = new StringFieldAdapter(TaskLists.SYNC_VERSION); - /** - * Adapter for the account name of a list. - */ + /** Adapter for the account name of a list. */ StringFieldAdapter ACCOUNT_NAME = new StringFieldAdapter(TaskLists.ACCOUNT_NAME); - /** - * Adapter for the account type of a list. - */ + /** Adapter for the account type of a list. */ StringFieldAdapter ACCOUNT_TYPE = new StringFieldAdapter(TaskLists.ACCOUNT_TYPE); - /** - * Adapter for the owner of a list. - */ + /** Adapter for the owner of a list. */ StringFieldAdapter OWNER = new StringFieldAdapter(TaskLists.OWNER); - /** - * Adapter for the name of a list. - */ + /** Adapter for the name of a list. */ StringFieldAdapter LIST_NAME = new StringFieldAdapter(TaskLists.LIST_NAME); - /** - * Adapter for the color of a list. - */ + /** Adapter for the color of a list. */ IntegerFieldAdapter LIST_COLOR = new IntegerFieldAdapter(TaskLists.LIST_COLOR); /*** - * Creates a {@link ListAdapter} for a new task initialized with the values of this task (except for _ID). + * Creates a {@link ListAdapter} for a new task initialized with the values of + * this task (except for _ID). * * @return A new task having the same values. */ diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/TaskAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/TaskAdapter.java index 4668cce310995396909be1fff987fde1f512e030..bf221040f1fee5a034a56cd39ed6c0c8c52a5e8c 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/TaskAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/TaskAdapter.java @@ -18,7 +18,6 @@ package org.dmfs.provider.tasks.model; import android.content.ContentValues; import android.database.Cursor; - import org.dmfs.provider.tasks.model.adapters.BinaryFieldAdapter; import org.dmfs.provider.tasks.model.adapters.BooleanFieldAdapter; import org.dmfs.provider.tasks.model.adapters.DateTimeFieldAdapter; @@ -33,327 +32,223 @@ import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Instances; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** - * Adapter to read task values from primitive data sets like {@link Cursor}s or {@link ContentValues}s. + * Adapter to read task values from primitive data sets like {@link Cursor}s or + * {@link ContentValues}s. * * @author Marten Gajda */ -public interface TaskAdapter extends EntityAdapter -{ - /** - * Adapter for the row id of a task. - */ +public interface TaskAdapter extends EntityAdapter { + /** Adapter for the row id of a task. */ LongFieldAdapter _ID = new LongFieldAdapter(Tasks._ID); - /** - * Adapter for the version of a task. - */ + /** Adapter for the version of a task. */ LongFieldAdapter VERSION = new LongFieldAdapter<>(Tasks.VERSION); - /** - * Adapter for the task row id of as instance. - */ + /** Adapter for the task row id of as instance. */ LongFieldAdapter INSTANCE_TASK_ID = new LongFieldAdapter(Instances.TASK_ID); - /** - * Adapter for the row id of the list of a task. - */ + /** Adapter for the row id of the list of a task. */ LongFieldAdapter LIST_ID = new LongFieldAdapter(Tasks.LIST_ID); - /** - * Adapter for the owner of the list of a task. - */ + /** Adapter for the owner of the list of a task. */ StringFieldAdapter LIST_OWNER = new StringFieldAdapter(Tasks.LIST_OWNER); - /** - * Adapter for the row id of original instance of a task. - */ + /** Adapter for the row id of original instance of a task. */ LongFieldAdapter ORIGINAL_INSTANCE_ID = new LongFieldAdapter(Tasks.ORIGINAL_INSTANCE_ID); - /** - * Adapter for the sync_id of original instance of a task. - */ - StringFieldAdapter ORIGINAL_INSTANCE_SYNC_ID = new StringFieldAdapter(Tasks.ORIGINAL_INSTANCE_SYNC_ID); + /** Adapter for the sync_id of original instance of a task. */ + StringFieldAdapter ORIGINAL_INSTANCE_SYNC_ID = new StringFieldAdapter( + Tasks.ORIGINAL_INSTANCE_SYNC_ID); - /** - * Adapter for the original instance all day flag of a task. - */ - BooleanFieldAdapter ORIGINAL_INSTANCE_ALLDAY = new BooleanFieldAdapter(Tasks.ORIGINAL_INSTANCE_ALLDAY); + /** Adapter for the original instance all day flag of a task. */ + BooleanFieldAdapter ORIGINAL_INSTANCE_ALLDAY = new BooleanFieldAdapter( + Tasks.ORIGINAL_INSTANCE_ALLDAY); - /** - * Adapter for the parent_id of a task. - */ + /** Adapter for the parent_id of a task. */ LongFieldAdapter PARENT_ID = new LongFieldAdapter(Tasks.PARENT_ID); - /** - * Adapter for the all day flag of a task. - */ + /** Adapter for the all day flag of a task. */ BooleanFieldAdapter IS_ALLDAY = new BooleanFieldAdapter(Tasks.IS_ALLDAY); - /** - * Adapter for the percent complete value of a task. - */ + /** Adapter for the percent complete value of a task. */ IntegerFieldAdapter PERCENT_COMPLETE = new IntegerFieldAdapter(Tasks.PERCENT_COMPLETE); - /** - * Adapter for the status of a task. - */ + /** Adapter for the status of a task. */ IntegerFieldAdapter STATUS = new IntegerFieldAdapter(Tasks.STATUS); - /** - * Adapter for the priority value of a task. - */ + /** Adapter for the priority value of a task. */ IntegerFieldAdapter PRIORITY = new IntegerFieldAdapter(Tasks.PRIORITY); - /** - * Adapter for the classification value of a task. - */ + /** Adapter for the classification value of a task. */ IntegerFieldAdapter CLASSIFICATION = new IntegerFieldAdapter(Tasks.CLASSIFICATION); - /** - * Adapter for the list name of a task. - */ + /** Adapter for the list name of a task. */ StringFieldAdapter LIST_NAME = new StringFieldAdapter(Tasks.LIST_NAME); - /** - * Adapter for the account name of a task. - */ + /** Adapter for the account name of a task. */ StringFieldAdapter ACCOUNT_NAME = new StringFieldAdapter(Tasks.ACCOUNT_NAME); - /** - * Adapter for the account type of a task. - */ + /** Adapter for the account type of a task. */ StringFieldAdapter ACCOUNT_TYPE = new StringFieldAdapter(Tasks.ACCOUNT_TYPE); - /** - * Adapter for the title of a task. - */ + /** Adapter for the title of a task. */ StringFieldAdapter TITLE = new StringFieldAdapter(Tasks.TITLE); - /** - * Adapter for the location of a task. - */ + /** Adapter for the location of a task. */ StringFieldAdapter LOCATION = new StringFieldAdapter(Tasks.LOCATION); - /** - * Adapter for the description of a task. - */ + /** Adapter for the description of a task. */ StringFieldAdapter DESCRIPTION = new StringFieldAdapter(Tasks.DESCRIPTION); - /** - * Adapter for the start date of a task. - */ - DateTimeFieldAdapter DTSTART = new DateTimeFieldAdapter(Tasks.DTSTART, Tasks.TZ, Tasks.IS_ALLDAY); + /** Adapter for the start date of a task. */ + DateTimeFieldAdapter DTSTART = new DateTimeFieldAdapter(Tasks.DTSTART, Tasks.TZ, + Tasks.IS_ALLDAY); - /** - * Adapter for the original date of a task. - */ - DateTimeFieldAdapter ORIGINAL_INSTANCE_TIME = new DateTimeFieldAdapter(Tasks.ORIGINAL_INSTANCE_TIME, Tasks.TZ, - Tasks.ORIGINAL_INSTANCE_ALLDAY); + /** Adapter for the original date of a task. */ + DateTimeFieldAdapter ORIGINAL_INSTANCE_TIME = new DateTimeFieldAdapter( + Tasks.ORIGINAL_INSTANCE_TIME, Tasks.TZ, Tasks.ORIGINAL_INSTANCE_ALLDAY); - /** - * Adapter for the raw start date timestamp of a task. - */ + /** Adapter for the raw start date timestamp of a task. */ LongFieldAdapter DTSTART_RAW = new LongFieldAdapter(Tasks.DTSTART); - /** - * Adapter for the due date of a task. - */ + /** Adapter for the due date of a task. */ DateTimeFieldAdapter DUE = new DateTimeFieldAdapter(Tasks.DUE, Tasks.TZ, Tasks.IS_ALLDAY); - /** - * Adapter for the raw due date timestamp of a task. - */ + /** Adapter for the raw due date timestamp of a task. */ LongFieldAdapter DUE_RAW = new LongFieldAdapter(Tasks.DUE); - /** - * Adapter for the start date of a task. - */ + /** Adapter for the start date of a task. */ DurationFieldAdapter DURATION = new DurationFieldAdapter(Tasks.DURATION); - /** - * Adapter for the dirty flag of a task. - */ + /** Adapter for the dirty flag of a task. */ BooleanFieldAdapter _DIRTY = new BooleanFieldAdapter(Tasks._DIRTY); - /** - * Adapter for the deleted flag of a task. - */ + /** Adapter for the deleted flag of a task. */ BooleanFieldAdapter _DELETED = new BooleanFieldAdapter(Tasks._DELETED); - /** - * Adapter for the completed date of a task. - */ + /** Adapter for the completed date of a task. */ DateTimeFieldAdapter COMPLETED = new DateTimeFieldAdapter(Tasks.COMPLETED, null, null); - /** - * Adapter for the created date of a task. - */ + /** Adapter for the created date of a task. */ DateTimeFieldAdapter CREATED = new DateTimeFieldAdapter(Tasks.CREATED, null, null); - /** - * Adapter for the last modified date of a task. - */ - DateTimeFieldAdapter LAST_MODIFIED = new DateTimeFieldAdapter(Tasks.LAST_MODIFIED, null, null); + /** Adapter for the last modified date of a task. */ + DateTimeFieldAdapter LAST_MODIFIED = new DateTimeFieldAdapter(Tasks.LAST_MODIFIED, null, + null); - /** - * Adapter for the URL of a task. - */ + /** Adapter for the URL of a task. */ UrlFieldAdapter URL = new UrlFieldAdapter(TaskContract.Tasks.URL); - /** - * Adapter for the UID of a task. - */ + /** Adapter for the UID of a task. */ StringFieldAdapter _UID = new StringFieldAdapter(TaskContract.Tasks._UID); - /** - * Adapter for the raw time zone of a task. - */ + /** Adapter for the raw time zone of a task. */ StringFieldAdapter TIMEZONE_RAW = new StringFieldAdapter(TaskContract.Tasks.TZ); - /** - * Adapter for the Color of the task. - */ + /** Adapter for the Color of the task. */ IntegerFieldAdapter LIST_COLOR = new IntegerFieldAdapter(TaskContract.Tasks.LIST_COLOR); - /** - * Adapter for the access level of the task list. - */ - IntegerFieldAdapter LIST_ACCESS_LEVEL = new IntegerFieldAdapter(TaskContract.Tasks.LIST_ACCESS_LEVEL); + /** Adapter for the access level of the task list. */ + IntegerFieldAdapter LIST_ACCESS_LEVEL = new IntegerFieldAdapter( + TaskContract.Tasks.LIST_ACCESS_LEVEL); - /** - * Adapter for the visibility setting of the task list. - */ + /** Adapter for the visibility setting of the task list. */ BooleanFieldAdapter LIST_VISIBLE = new BooleanFieldAdapter(TaskContract.Tasks.VISIBLE); - /** - * Adpater for the ID of the task. - */ + /** Adpater for the ID of the task. */ IntegerFieldAdapter TASK_ID = new IntegerFieldAdapter(TaskContract.Tasks._ID); - /** - * Adapter for the IS_CLOSED flag of a task. - */ + /** Adapter for the IS_CLOSED flag of a task. */ BooleanFieldAdapter IS_CLOSED = new BooleanFieldAdapter(TaskContract.Tasks.IS_CLOSED); - /** - * Adapter for the IS_NEW flag of a task. - */ + /** Adapter for the IS_NEW flag of a task. */ BooleanFieldAdapter IS_NEW = new BooleanFieldAdapter(TaskContract.Tasks.IS_NEW); - /** - * Adapter for the PINNED flag of a task. - */ + /** Adapter for the PINNED flag of a task. */ BooleanFieldAdapter PINNED = new BooleanFieldAdapter(TaskContract.Tasks.PINNED); - /** - * Adapter for the HAS_ALARMS flag of a task. - */ + /** Adapter for the HAS_ALARMS flag of a task. */ BooleanFieldAdapter HAS_ALARMS = new BooleanFieldAdapter(TaskContract.Tasks.HAS_ALARMS); - /** - * Adapter for the HAS_PROPERTIES flag of a task. - */ - BooleanFieldAdapter HAS_PROPERTIES = new BooleanFieldAdapter(TaskContract.Tasks.HAS_PROPERTIES); + /** Adapter for the HAS_PROPERTIES flag of a task. */ + BooleanFieldAdapter HAS_PROPERTIES = new BooleanFieldAdapter( + TaskContract.Tasks.HAS_PROPERTIES); - /** - * Adapter for the RRULE of a task. - */ + /** Adapter for the RRULE of a task. */ RRuleFieldAdapter RRULE = new RRuleFieldAdapter(TaskContract.Tasks.RRULE); - /** - * Adapter for the RDATE of a task. - */ - DateTimeIterableFieldAdapter RDATE = new DateTimeIterableFieldAdapter(TaskContract.Tasks.RDATE, - TaskContract.Tasks.TZ); + /** Adapter for the RDATE of a task. */ + DateTimeIterableFieldAdapter RDATE = new DateTimeIterableFieldAdapter( + TaskContract.Tasks.RDATE, TaskContract.Tasks.TZ); - /** - * Adapter for the EXDATE of a task. - */ - DateTimeIterableFieldAdapter EXDATE = new DateTimeIterableFieldAdapter(TaskContract.Tasks.EXDATE, - TaskContract.Tasks.TZ); + /** Adapter for the EXDATE of a task. */ + DateTimeIterableFieldAdapter EXDATE = new DateTimeIterableFieldAdapter( + TaskContract.Tasks.EXDATE, TaskContract.Tasks.TZ); - /** - * Adapter for the SYNC1 field of a task. - */ + /** Adapter for the SYNC1 field of a task. */ BinaryFieldAdapter SYNC1 = new BinaryFieldAdapter(TaskContract.Tasks.SYNC1); - /** - * Adapter for the SYNC2 field of a task. - */ + /** Adapter for the SYNC2 field of a task. */ BinaryFieldAdapter SYNC2 = new BinaryFieldAdapter(TaskContract.Tasks.SYNC2); - /** - * Adapter for the SYNC3 field of a task. - */ + /** Adapter for the SYNC3 field of a task. */ BinaryFieldAdapter SYNC3 = new BinaryFieldAdapter(TaskContract.Tasks.SYNC3); - /** - * Adapter for the SYNC4 field of a task. - */ + /** Adapter for the SYNC4 field of a task. */ BinaryFieldAdapter SYNC4 = new BinaryFieldAdapter(TaskContract.Tasks.SYNC4); - /** - * Adapter for the SYNC5 field of a task. - */ + /** Adapter for the SYNC5 field of a task. */ BinaryFieldAdapter SYNC5 = new BinaryFieldAdapter(TaskContract.Tasks.SYNC5); - /** - * Adapter for the SYNC6 field of a task. - */ + /** Adapter for the SYNC6 field of a task. */ BinaryFieldAdapter SYNC6 = new BinaryFieldAdapter(TaskContract.Tasks.SYNC6); - /** - * Adapter for the SYNC7 field of a task. - */ + /** Adapter for the SYNC7 field of a task. */ BinaryFieldAdapter SYNC7 = new BinaryFieldAdapter(TaskContract.Tasks.SYNC7); - /** - * Adapter for the SYNC8 field of a task. - */ + /** Adapter for the SYNC8 field of a task. */ BinaryFieldAdapter SYNC8 = new BinaryFieldAdapter(TaskContract.Tasks.SYNC8); - /** - * Adapter for the SYNC_VERSION field of a task. - */ + /** Adapter for the SYNC_VERSION field of a task. */ BinaryFieldAdapter SYNC_VERSION = new BinaryFieldAdapter(TaskContract.Tasks.SYNC_VERSION); - /** - * Adapter for the SYNC_ID field of a task. - */ + /** Adapter for the SYNC_ID field of a task. */ StringFieldAdapter SYNC_ID = new StringFieldAdapter(TaskContract.Tasks._SYNC_ID); - /** - * Adapter for the due date of a task instance. - */ - DateTimeFieldAdapter INSTANCE_DUE = new DateTimeFieldAdapter(Instances.INSTANCE_DUE, Tasks.TZ, - Tasks.IS_ALLDAY); + /** Adapter for the due date of a task instance. */ + DateTimeFieldAdapter INSTANCE_DUE = new DateTimeFieldAdapter(Instances.INSTANCE_DUE, + Tasks.TZ, Tasks.IS_ALLDAY); - /** - * Adapter for the start date of a task instance. - */ - DateTimeFieldAdapter INSTANCE_START = new DateTimeFieldAdapter(Instances.INSTANCE_START, Tasks.TZ, - Tasks.IS_ALLDAY); + /** Adapter for the start date of a task instance. */ + DateTimeFieldAdapter INSTANCE_START = new DateTimeFieldAdapter(Instances.INSTANCE_START, + Tasks.TZ, Tasks.IS_ALLDAY); /** * Returns whether the adapted task is recurring. * - * @return true if the task is recurring, false otherwise. + * @return true if the task is recurring, false + * otherwise. */ boolean isRecurring(); /** - * Returns whether any value that's relevant for recurrence has been modified thought this adapter. This returns true if any of - * {@link TaskContract.TaskColumns#DTSTART}, {@link TaskContract.TaskColumns#DUE},{@link TaskContract.TaskColumns#DURATION}, - * {@link TaskContract.TaskColumns#RRULE}, {@link TaskContract.TaskColumns#RDATE} or {@link TaskContract.TaskColumns#EXDATE} has been modified. + * Returns whether any value that's relevant for recurrence has been modified + * thought this adapter. This returns true if any of + * {@link TaskContract.TaskColumns#DTSTART}, + * {@link TaskContract.TaskColumns#DUE},{@link TaskContract.TaskColumns#DURATION}, + * {@link TaskContract.TaskColumns#RRULE}, + * {@link TaskContract.TaskColumns#RDATE} or + * {@link TaskContract.TaskColumns#EXDATE} has been modified. * - * @return true if the recurrence set has changed, false otherwise. + * @return true if the recurrence set has changed, + * false otherwise. */ boolean recurrenceUpdated(); /*** - * Creates a {@link TaskAdapter} for a new task initialized with the values of this task (except for _ID). + * Creates a {@link TaskAdapter} for a new task initialized with the values of + * this task (except for _ID). * * @return A new task having the same values. */ diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/BinaryFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/BinaryFieldAdapter.java index 0d6c24df4c2cfc1835bf2f42c087c1fe899cc8d9..fbec6268f61de08927b3b4a4320a673d2418f7ba 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/BinaryFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/BinaryFieldAdapter.java @@ -19,77 +19,57 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - /** - * Knows how to load and store a binary value from a {@link Cursor} or {@link ContentValues}. + * Knows how to load and store a binary value from a {@link Cursor} or + * {@link ContentValues}. * * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class BinaryFieldAdapter extends SimpleFieldAdapter -{ +public final class BinaryFieldAdapter extends SimpleFieldAdapter { - /** - * The field name this adapter uses to store the values. - */ + /** The field name this adapter uses to store the values. */ private final String mFieldName; - /** * Constructor for a new {@link BinaryFieldAdapter}. * * @param fieldName - * The name of the field to use when loading or storing the value. + * The name of the field to use when loading or storing the value. */ - public BinaryFieldAdapter(String fieldName) - { - if (fieldName == null) - { + public BinaryFieldAdapter(String fieldName) { + if (fieldName == null) { throw new IllegalArgumentException("fieldName must not be null"); } mFieldName = fieldName; } - @Override - String fieldName() - { + String fieldName() { return mFieldName; } - @Override - public byte[] getFrom(ContentValues values) - { + public byte[] getFrom(ContentValues values) { return values.getAsByteArray(mFieldName); } - @Override - public byte[] getFrom(Cursor cursor) - { + public byte[] getFrom(Cursor cursor) { int columnIdx = cursor.getColumnIndex(mFieldName); - if (columnIdx < 0) - { + if (columnIdx < 0) { throw new IllegalArgumentException("The column '" + mFieldName + "' is missing in cursor."); } return cursor.isNull(columnIdx) ? null : cursor.getBlob(columnIdx); } - @Override - public void setIn(ContentValues values, byte[] value) - { - if (value != null) - { + public void setIn(ContentValues values, byte[] value) { + if (value != null) { values.put(mFieldName, value); - } - else - { + } else { values.putNull(mFieldName); } } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/BooleanFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/BooleanFieldAdapter.java index ef7e948396441705594ac79d07bcf55bbb4c19b0..d460524a0a1a79653eb7d7c165ed2884ed609261 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/BooleanFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/BooleanFieldAdapter.java @@ -19,76 +19,62 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - /** - * Knows how to load and store a {@link Boolean} value from a {@link Cursor} or {@link ContentValues}. - *

+ * Knows how to load and store a {@link Boolean} value from a {@link Cursor} or + * {@link ContentValues}. + * + *

* Implementation detail: - *

- * The values are loaded and stored as 0 (for false) and 1 (for true). * - * @param - * The type of the entity the field belongs to. + *

+ * The values are loaded and stored as 0 (for false) + * and 1 (for true). * + * @param + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class BooleanFieldAdapter extends SimpleFieldAdapter -{ +public final class BooleanFieldAdapter extends SimpleFieldAdapter { - /** - * The field name this adapter uses to store the values. - */ + /** The field name this adapter uses to store the values. */ private final String mFieldName; - /** * Constructor for a new {@link BooleanFieldAdapter}. * * @param fieldName - * The name of the field to use when loading or storing the value. + * The name of the field to use when loading or storing the value. */ - public BooleanFieldAdapter(String fieldName) - { - if (fieldName == null) - { + public BooleanFieldAdapter(String fieldName) { + if (fieldName == null) { throw new IllegalArgumentException("fieldName must not be null"); } mFieldName = fieldName; } - @Override - String fieldName() - { + String fieldName() { return mFieldName; } - @Override - public Boolean getFrom(ContentValues values) - { + public Boolean getFrom(ContentValues values) { Integer value = values.getAsInteger(mFieldName); return value != null && value > 0; } - @Override - public Boolean getFrom(Cursor cursor) - { + public Boolean getFrom(Cursor cursor) { int columnIdx = cursor.getColumnIndex(mFieldName); - if (columnIdx < 0) - { + if (columnIdx < 0) { throw new IllegalArgumentException("The column '" + mFieldName + "' is missing in cursor."); } return !cursor.isNull(columnIdx) && cursor.getInt(columnIdx) > 0; } - @Override - public void setIn(ContentValues values, Boolean value) - { + public void setIn(ContentValues values, Boolean value) { values.put(mFieldName, value ? 1 : 0); } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DateTimeFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DateTimeFieldAdapter.java index 5c9159bef875713fe98c7aa7d3150ac844ee3adb..209ec6780cfa35d64a62b1c1b00340afd8d7398f 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DateTimeFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DateTimeFieldAdapter.java @@ -18,52 +18,51 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - -import org.dmfs.rfc5545.DateTime; - import java.util.TimeZone; - +import org.dmfs.rfc5545.DateTime; /** - * Knows how to load and store {@link DateTime} values from a {@link Cursor} or {@link ContentValues}. + * Knows how to load and store {@link DateTime} values from a {@link Cursor} or + * {@link ContentValues}. + * *

* {@link DateTime} values are stored as three separate values: + * *

    - *
  • a timestamp in milliseconds since the epoch
  • - *
  • a time zone
  • - *
  • an allday flag
  • + *
  • a timestamp in milliseconds since the epoch + *
  • a time zone + *
  • an allday flag *
+ * *

- * This adapter combines those three fields to a {@link DateTime} value. If the time zone field is null the time zone is always set to UTC. + * This adapter combines those three fields to a {@link DateTime} value. If the + * time zone field is null the time zone is always set to UTC. * * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class DateTimeFieldAdapter extends SimpleFieldAdapter -{ +public final class DateTimeFieldAdapter extends SimpleFieldAdapter { private final String mTimestampField; private final String mTzField; private final String mAllDayField; private final boolean mAllDayDefault; - /** * Constructor for a new {@link DateTimeFieldAdapter}. * * @param timestampField - * The name of the field that holds the time stamp in milliseconds. + * The name of the field that holds the time stamp in milliseconds. * @param tzField - * The name of the field that holds the time zone (as Olson ID). If the field name is null the time is always set to UTC. + * The name of the field that holds the time zone (as Olson ID). If + * the field name is null the time is always set to UTC. * @param alldayField - * The name of the field that indicated that this time is a date not a date-time. If this fieldName is null all loaded values are - * non-allday. + * The name of the field that indicated that this time is a date not + * a date-time. If this fieldName is null all loaded + * values are non-allday. */ - public DateTimeFieldAdapter(String timestampField, String tzField, String alldayField) - { - if (timestampField == null) - { + public DateTimeFieldAdapter(String timestampField, String tzField, String alldayField) { + if (timestampField == null) { throw new IllegalArgumentException("timestampField must not be null"); } mTimestampField = timestampField; @@ -72,20 +71,15 @@ public final class DateTimeFieldAdapter extends SimpleFieldAdapter extends SimpleFieldAdapter extends SimpleFieldAdapter extends SimpleFieldAdapter= 0) - { - if (cursor.isNull(tsIdx)) - { + } else if (cursor != null && (tsIdx = cursor.getColumnIndex(mTimestampField)) >= 0) { + if (cursor.isNull(tsIdx)) { // if the time stamp is null we return null return null; } timestamp = cursor.getLong(tsIdx); - } - else - { + } else { throw new IllegalArgumentException("Missing timestamp column."); } - if (mTzField != null) - { - if (values != null && values.containsKey(mTzField)) - { + if (mTzField != null) { + if (values != null && values.containsKey(mTzField)) { timeZoneId = values.getAsString(mTzField); - } - else if (cursor != null && (tzIdx = cursor.getColumnIndex(mTzField)) >= 0) - { + } else if (cursor != null && (tzIdx = cursor.getColumnIndex(mTzField)) >= 0) { timeZoneId = cursor.getString(tzIdx); - } - else - { + } else { throw new IllegalArgumentException("Missing timezone column."); } } - if (mAllDayField != null) - { - if (values != null && values.containsKey(mAllDayField)) - { + if (mAllDayField != null) { + if (values != null && values.containsKey(mAllDayField)) { allDay = values.getAsInteger(mAllDayField); - } - else if (cursor != null && (adIdx = cursor.getColumnIndex(mAllDayField)) >= 0) - { + } else if (cursor != null && (adIdx = cursor.getColumnIndex(mAllDayField)) >= 0) { allDay = cursor.getInt(adIdx); - } - else - { + } else { throw new IllegalArgumentException("Missing timezone column."); } } DateTime value = new DateTime(timeZoneId == null ? null : TimeZone.getTimeZone(timeZoneId), timestamp); - if (allDay != 0) - { + if (allDay != 0) { value = value.toAllDay(); } return value; } - @Override - public void setIn(ContentValues values, DateTime value) - { - if (value != null) - { + public void setIn(ContentValues values, DateTime value) { + if (value != null) { // just store all three parts separately values.put(mTimestampField, value.getTimestamp()); - if (mTzField != null) - { + if (mTzField != null) { TimeZone timezone = value.getTimeZone(); values.put(mTzField, timezone == null ? null : timezone.getID()); } - if (mAllDayField != null) - { + if (mAllDayField != null) { values.put(mAllDayField, value.isAllDay() ? 1 : 0); } - } - else - { + } else { // write timestamp only, other fields may still use allday and timezone values.put(mTimestampField, (Long) null); } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DateTimeIterableFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DateTimeIterableFieldAdapter.java index 3f1ebbc369700d128aa882ce66c8115bf67a965a..a4d321f728eee61c0e4c6e5f940ddd62393d47b5 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DateTimeIterableFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DateTimeIterableFieldAdapter.java @@ -19,62 +19,50 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; import android.text.TextUtils; - +import java.util.TimeZone; import org.dmfs.iterables.EmptyIterable; import org.dmfs.iterables.Split; import org.dmfs.iterables.decorators.DelegatingIterable; import org.dmfs.jems.iterable.decorators.Mapped; import org.dmfs.rfc5545.DateTime; -import java.util.TimeZone; - - /** - * Knows how to load and store {@link Iterable}s of {@link DateTime} values from a {@link Cursor} or {@link ContentValues}. + * Knows how to load and store {@link Iterable}s of {@link DateTime} values from + * a {@link Cursor} or {@link ContentValues}. * * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class DateTimeIterableFieldAdapter extends SimpleFieldAdapter, EntityType> -{ +public final class DateTimeIterableFieldAdapter extends SimpleFieldAdapter, EntityType> { private final String mDateTimeListFieldName; private final String mTimeZoneFieldName; - /** * Constructor for a new {@link DateTimeIterableFieldAdapter}. * * @param datetimeListFieldName - * The name of the field that holds the {@link DateTime} list. + * The name of the field that holds the {@link DateTime} list. * @param timezoneFieldName - * The name of the field that holds the time zone name. + * The name of the field that holds the time zone name. */ - public DateTimeIterableFieldAdapter(String datetimeListFieldName, String timezoneFieldName) - { - if (datetimeListFieldName == null) - { + public DateTimeIterableFieldAdapter(String datetimeListFieldName, String timezoneFieldName) { + if (datetimeListFieldName == null) { throw new IllegalArgumentException("datetimeListFieldName must not be null"); } mDateTimeListFieldName = datetimeListFieldName; mTimeZoneFieldName = timezoneFieldName; } - @Override - String fieldName() - { + String fieldName() { return mDateTimeListFieldName; } - @Override - public Iterable getFrom(ContentValues values) - { + public Iterable getFrom(ContentValues values) { String datetimeList = values.getAsString(mDateTimeListFieldName); - if (datetimeList == null) - { + if (datetimeList == null) { // no list, return an empty Iterable return EmptyIterable.instance(); } @@ -86,20 +74,16 @@ public final class DateTimeIterableFieldAdapter extends SimpleFieldA return new DateTimeList(timeZone, datetimeList); } - @Override - public Iterable getFrom(Cursor cursor) - { + public Iterable getFrom(Cursor cursor) { int tdLIdx = cursor.getColumnIndex(mDateTimeListFieldName); int tzIdx = mTimeZoneFieldName == null ? -1 : cursor.getColumnIndex(mTimeZoneFieldName); - if (tdLIdx < 0 || (mTimeZoneFieldName != null && tzIdx < 0)) - { + if (tdLIdx < 0 || (mTimeZoneFieldName != null && tzIdx < 0)) { throw new IllegalArgumentException("At least one column is missing in cursor."); } - if (cursor.isNull(tdLIdx)) - { + if (cursor.isNull(tdLIdx)) { // if the time stamp list is null we return an empty Iterable return EmptyIterable.instance(); } @@ -113,50 +97,35 @@ public final class DateTimeIterableFieldAdapter extends SimpleFieldA return new DateTimeList(timeZone, datetimeList); } - @Override - public Iterable getFrom(Cursor cursor, ContentValues values) - { + public Iterable getFrom(Cursor cursor, ContentValues values) { int tsIdx; int tzIdx; String datetimeList; String timeZoneId = null; - if (values != null && values.containsKey(mDateTimeListFieldName)) - { - if (values.getAsString(mDateTimeListFieldName) == null) - { + if (values != null && values.containsKey(mDateTimeListFieldName)) { + if (values.getAsString(mDateTimeListFieldName) == null) { // the date times are null, so we return null return EmptyIterable.instance(); } datetimeList = values.getAsString(mDateTimeListFieldName); - } - else if (cursor != null && (tsIdx = cursor.getColumnIndex(mDateTimeListFieldName)) >= 0) - { - if (cursor.isNull(tsIdx)) - { + } else if (cursor != null && (tsIdx = cursor.getColumnIndex(mDateTimeListFieldName)) >= 0) { + if (cursor.isNull(tsIdx)) { // the date times are null, so we return an empty Iterable. return EmptyIterable.instance(); } datetimeList = cursor.getString(tsIdx); - } - else - { + } else { throw new IllegalArgumentException("Missing date time list column."); } - if (mTimeZoneFieldName != null) - { - if (values != null && values.containsKey(mTimeZoneFieldName)) - { + if (mTimeZoneFieldName != null) { + if (values != null && values.containsKey(mTimeZoneFieldName)) { timeZoneId = values.getAsString(mTimeZoneFieldName); - } - else if (cursor != null && (tzIdx = cursor.getColumnIndex(mTimeZoneFieldName)) >= 0) - { + } else if (cursor != null && (tzIdx = cursor.getColumnIndex(mTimeZoneFieldName)) >= 0) { timeZoneId = cursor.getString(tzIdx); - } - else - { + } else { throw new IllegalArgumentException("Missing timezone column."); } } @@ -167,29 +136,24 @@ public final class DateTimeIterableFieldAdapter extends SimpleFieldA return new DateTimeList(timeZone, datetimeList); } - @Override - public void setIn(ContentValues values, Iterable value) - { - if (value != null) - { - String stringValue = TextUtils.join(",", new Mapped<>(dt -> dt.isFloating() ? dt : dt.shiftTimeZone(DateTime.UTC), value)); + public void setIn(ContentValues values, Iterable value) { + if (value != null) { + String stringValue = TextUtils.join(",", + new Mapped<>(dt -> dt.isFloating() ? dt : dt.shiftTimeZone(DateTime.UTC), value)); values.put(mDateTimeListFieldName, stringValue.isEmpty() ? null : stringValue); - } - else - { + } else { values.put(mDateTimeListFieldName, (String) null); } } + private final class DateTimeList extends DelegatingIterable { - private final class DateTimeList extends DelegatingIterable - { - - public DateTimeList(TimeZone timeZone, String dateTimeList) - { + public DateTimeList(TimeZone timeZone, String dateTimeList) { super(new Mapped<>( - datetime -> !datetime.isFloating() && timeZone != null ? datetime.shiftTimeZone(timeZone) : datetime, + datetime -> !datetime.isFloating() && timeZone != null + ? datetime.shiftTimeZone(timeZone) + : datetime, new Mapped( charSequence -> DateTime.parse(timeZone, charSequence.toString()), new Split(dateTimeList, ',')))); diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DurationFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DurationFieldAdapter.java index 5a5f8eb8d50bbc1f7613ef23f007c76ec4abe339..7b556d99dbb48efeb7ce98289d4eab902204adf9 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DurationFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/DurationFieldAdapter.java @@ -18,89 +18,68 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - import org.dmfs.rfc5545.Duration; - /** - * Knows how to load and store {@link Duration} values from a {@link Cursor} or {@link ContentValues}. + * Knows how to load and store {@link Duration} values from a {@link Cursor} or + * {@link ContentValues}. * * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class DurationFieldAdapter extends SimpleFieldAdapter -{ +public final class DurationFieldAdapter extends SimpleFieldAdapter { private final String mFieldName; - /** * Constructor for a new {@link DurationFieldAdapter}. * * @param urlField - * The field name that holds the {@link Duration}. + * The field name that holds the {@link Duration}. */ - public DurationFieldAdapter(String urlField) - { - if (urlField == null) - { + public DurationFieldAdapter(String urlField) { + if (urlField == null) { throw new IllegalArgumentException("urlField must not be null"); } mFieldName = urlField; } - @Override - String fieldName() - { + String fieldName() { return mFieldName; } - @Override - public Duration getFrom(ContentValues values) - { + public Duration getFrom(ContentValues values) { String rawValue = values.getAsString(mFieldName); - if (rawValue == null) - { + if (rawValue == null) { return null; } return Duration.parse(rawValue); } - @Override - public Duration getFrom(Cursor cursor) - { + public Duration getFrom(Cursor cursor) { int columnIdx = cursor.getColumnIndex(mFieldName); - if (columnIdx < 0) - { + if (columnIdx < 0) { throw new IllegalArgumentException("The column '" + mFieldName + "' is missing in cursor."); } - if (cursor.isNull(columnIdx)) - { + if (cursor.isNull(columnIdx)) { return null; } return Duration.parse(cursor.getString(columnIdx)); } - @Override - public void setIn(ContentValues values, Duration value) - { - if (value != null) - { + public void setIn(ContentValues values, Duration value) { + if (value != null) { values.put(mFieldName, value.toString()); - } - else - { + } else { values.putNull(mFieldName); } } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/FieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/FieldAdapter.java index e9fe287f1d40c80ae051aab01d44444e23ffdde8..0f38bd29b7bceb4ae2c18d3f3736e81025ca8e11 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/FieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/FieldAdapter.java @@ -19,36 +19,34 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - /** - * Knows how to load and store a specific field from or to {@link ContentValues} or from {@link Cursor}s. + * Knows how to load and store a specific field from or to {@link ContentValues} + * or from {@link Cursor}s. * * @param - * The type of the value this adapter stores. + * The type of the value this adapter stores. * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public interface FieldAdapter -{ +public interface FieldAdapter { /** - * Check if a value is present and non-null in the given {@link ContentValues}. + * Check if a value is present and non-null in the given + * {@link ContentValues}. * * @param values - * The {@link ContentValues} to check. - * + * The {@link ContentValues} to check. * @return */ boolean existsIn(ContentValues values); /** - * Check if a value is present (may be null) in the given {@link ContentValues}. + * Check if a value is present (may be null) in the given + * {@link ContentValues}. * * @param values - * The {@link ContentValues} to check. - * + * The {@link ContentValues} to check. * @return */ boolean isSetIn(ContentValues values); @@ -57,18 +55,17 @@ public interface FieldAdapter * Get the value from the given {@link ContentValues} * * @param values - * The {@link ContentValues} that contain the value to return. - * + * The {@link ContentValues} that contain the value to return. * @return The value. */ FieldType getFrom(ContentValues values); /** - * Check if a value is present and non-null in the given {@link Cursor}. + * Check if a value is present and non-null in the given + * {@link Cursor}. * * @param cursor - * The {@link Cursor} that contains the value to check. - * + * The {@link Cursor} that contains the value to check. * @return */ boolean existsIn(Cursor cursor); @@ -77,32 +74,31 @@ public interface FieldAdapter * Get the value from the given {@link Cursor} * * @param cursor - * The {@link Cursor} that contain the value to return. - * + * The {@link Cursor} that contain the value to return. * @return The value. */ FieldType getFrom(Cursor cursor); /** - * Check if a value is present and non-null in the given {@link Cursor} or {@link ContentValues}. + * Check if a value is present and non-null in the given + * {@link Cursor} or {@link ContentValues}. * * @param cursor - * The {@link Cursor} that contains the value to check. + * The {@link Cursor} that contains the value to check. * @param values - * The {@link ContentValues} that contains the value to check. - * + * The {@link ContentValues} that contains the value to check. * @return */ boolean existsIn(Cursor cursor, ContentValues values); /** - * Get the value from the given {@link Cursor} or {@link ContentValues}, with the {@link ContentValues} taking precedence over the cursor values. + * Get the value from the given {@link Cursor} or {@link ContentValues}, with + * the {@link ContentValues} taking precedence over the cursor values. * * @param cursor - * The {@link Cursor} that contains the value to return. + * The {@link Cursor} that contains the value to return. * @param values - * The {@link ContentValues} that contains the value to return. - * + * The {@link ContentValues} that contains the value to return. * @return The value. */ FieldType getFrom(Cursor cursor, ContentValues values); @@ -111,9 +107,9 @@ public interface FieldAdapter * Set a value in the given {@link ContentValues}. * * @param values - * The {@link ContentValues} to store the new value in. + * The {@link ContentValues} to store the new value in. * @param value - * The new value to store. + * The new value to store. */ void setIn(ContentValues values, FieldType value); @@ -121,7 +117,7 @@ public interface FieldAdapter * Remove a value from the given {@link ContentValues}. * * @param values - * The {@link ContentValues} from which to remove the value. + * The {@link ContentValues} from which to remove the value. */ void removeFrom(ContentValues values); @@ -129,20 +125,20 @@ public interface FieldAdapter * Copy the value from a {@link Cursor} to the given {@link ContentValues}. * * @param source - * The {@link Cursor} that contains the value to copy. + * The {@link Cursor} that contains the value to copy. * @param dest - * The {@link ContentValues} to receive the value. + * The {@link ContentValues} to receive the value. */ void copyValue(Cursor source, ContentValues dest); /** - * Copy the value from {@link ContentValues} to another {@link ContentValues} object. + * Copy the value from {@link ContentValues} to another {@link ContentValues} + * object. * * @param source - * The {@link ContentValues} that contains the value to copy. + * The {@link ContentValues} that contains the value to copy. * @param dest - * The {@link ContentValues} to receive the value. + * The {@link ContentValues} to receive the value. */ void copyValue(ContentValues source, ContentValues dest); - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/FloatFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/FloatFieldAdapter.java index 28b8a0140e9b7fbf1e3c878bd4635d6f5cfd0d4d..c0e93e677518d8c112586826c35946c2cd562f53 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/FloatFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/FloatFieldAdapter.java @@ -19,77 +19,57 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - /** - * Knows how to load and store a {@link Float} value from a {@link Cursor} or {@link ContentValues}. + * Knows how to load and store a {@link Float} value from a {@link Cursor} or + * {@link ContentValues}. * * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class FloatFieldAdapter extends SimpleFieldAdapter -{ +public final class FloatFieldAdapter extends SimpleFieldAdapter { - /** - * The field name this adapter uses to store the values. - */ + /** The field name this adapter uses to store the values. */ private final String mFieldName; - /** * Constructor for a new {@link FloatFieldAdapter}. * * @param fieldName - * The name of the field to use when loading or storing the value. + * The name of the field to use when loading or storing the value. */ - public FloatFieldAdapter(String fieldName) - { - if (fieldName == null) - { + public FloatFieldAdapter(String fieldName) { + if (fieldName == null) { throw new IllegalArgumentException("fieldName must not be null"); } mFieldName = fieldName; } - @Override - String fieldName() - { + String fieldName() { return mFieldName; } - @Override - public Float getFrom(ContentValues values) - { + public Float getFrom(ContentValues values) { return values.getAsFloat(mFieldName); } - @Override - public Float getFrom(Cursor cursor) - { + public Float getFrom(Cursor cursor) { int columnIdx = cursor.getColumnIndex(mFieldName); - if (columnIdx < 0) - { + if (columnIdx < 0) { throw new IllegalArgumentException("The column '" + mFieldName + "' is missing in cursor."); } return cursor.isNull(columnIdx) ? null : cursor.getFloat(columnIdx); } - @Override - public void setIn(ContentValues values, Float value) - { - if (value != null) - { + public void setIn(ContentValues values, Float value) { + if (value != null) { values.put(mFieldName, value); - } - else - { + } else { values.putNull(mFieldName); } } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/IntegerFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/IntegerFieldAdapter.java index 933c5e80faf76101750a1d39668a61009097933d..376a04690dd55547aecba0d7b6cfef7d01d3234d 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/IntegerFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/IntegerFieldAdapter.java @@ -19,78 +19,58 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - /** - * Knows how to load and store an {@link Integer} from a {@link Cursor} or {@link ContentValues}. + * Knows how to load and store an {@link Integer} from a {@link Cursor} or + * {@link ContentValues}. * * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class IntegerFieldAdapter extends SimpleFieldAdapter -{ +public final class IntegerFieldAdapter extends SimpleFieldAdapter { - /** - * The field name this adapter uses to store the values. - */ + /** The field name this adapter uses to store the values. */ private final String mFieldName; - /** * Constructor for a new {@link IntegerFieldAdapter}. * * @param fieldName - * The name of the field to use when loading or storing the value. + * The name of the field to use when loading or storing the value. */ - public IntegerFieldAdapter(String fieldName) - { - if (fieldName == null) - { + public IntegerFieldAdapter(String fieldName) { + if (fieldName == null) { throw new IllegalArgumentException("fieldName must not be null"); } mFieldName = fieldName; } - @Override - String fieldName() - { + String fieldName() { return mFieldName; } - @Override - public Integer getFrom(ContentValues values) - { + public Integer getFrom(ContentValues values) { // return the value as Integer return values.getAsInteger(mFieldName); } - @Override - public Integer getFrom(Cursor cursor) - { + public Integer getFrom(Cursor cursor) { int columnIdx = cursor.getColumnIndex(mFieldName); - if (columnIdx < 0) - { + if (columnIdx < 0) { throw new IllegalArgumentException("The column '" + mFieldName + "' is missing in cursor."); } return cursor.isNull(columnIdx) ? null : cursor.getInt(columnIdx); } - @Override - public void setIn(ContentValues values, Integer value) - { - if (value != null) - { + public void setIn(ContentValues values, Integer value) { + if (value != null) { values.put(mFieldName, value); - } - else - { + } else { values.putNull(mFieldName); } } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/LongFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/LongFieldAdapter.java index 517ca23372f1e0775ef6bece7ce8ef412b38a295..97c3eaa8fa1dc4c24852f993371f2f46167900ed 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/LongFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/LongFieldAdapter.java @@ -19,75 +19,56 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - /** - * Knows how to load and store a {@link Long} value from a {@link Cursor} or {@link ContentValues}. + * Knows how to load and store a {@link Long} value from a {@link Cursor} or + * {@link ContentValues}. * * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class LongFieldAdapter extends SimpleFieldAdapter -{ +public final class LongFieldAdapter extends SimpleFieldAdapter { - /** - * The field name this adapter uses to store the values. - */ + /** The field name this adapter uses to store the values. */ private final String mFieldName; - /** * Constructor for a new {@link LongFieldAdapter}. * * @param fieldName - * The name of the field to use when loading or storing the value. + * The name of the field to use when loading or storing the value. */ - public LongFieldAdapter(String fieldName) - { - if (fieldName == null) - { + public LongFieldAdapter(String fieldName) { + if (fieldName == null) { throw new IllegalArgumentException("fieldName must not be null"); } mFieldName = fieldName; } - @Override - String fieldName() - { + String fieldName() { return mFieldName; } - @Override - public Long getFrom(ContentValues values) - { + public Long getFrom(ContentValues values) { return values.getAsLong(mFieldName); } - @Override - public Long getFrom(Cursor cursor) - { + public Long getFrom(Cursor cursor) { int columnIdx = cursor.getColumnIndex(mFieldName); - if (columnIdx < 0) - { + if (columnIdx < 0) { throw new IllegalArgumentException("The column '" + mFieldName + "' is missing in cursor."); } return cursor.isNull(columnIdx) ? null : cursor.getLong(columnIdx); } - @Override - public void setIn(ContentValues values, Long value) - { - if (value != null) - { + public void setIn(ContentValues values, Long value) { + if (value != null) { values.put(mFieldName, value); - } - else - { + } else { values.putNull(mFieldName); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/RRuleFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/RRuleFieldAdapter.java index 201b075f04f1922d1998c58f56f7e00e7d50182a..ac28c1c8edd932db84be22b2ee6eb1db4c1eb101 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/RRuleFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/RRuleFieldAdapter.java @@ -18,105 +18,76 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - import org.dmfs.rfc5545.recur.InvalidRecurrenceRuleException; import org.dmfs.rfc5545.recur.RecurrenceRule; - /** - * Knows how to load and store a {@link RecurrenceRule} from a {@link Cursor} or {@link ContentValues}. + * Knows how to load and store a {@link RecurrenceRule} from a {@link Cursor} or + * {@link ContentValues}. * * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class RRuleFieldAdapter extends SimpleFieldAdapter -{ +public final class RRuleFieldAdapter extends SimpleFieldAdapter { - /** - * The field name this adapter uses to store the values. - */ + /** The field name this adapter uses to store the values. */ private final String mFieldName; - /** * Constructor for a new {@link RRuleFieldAdapter}. * * @param fieldName - * The name of the field to use when loading or storing the value. + * The name of the field to use when loading or storing the value. */ - public RRuleFieldAdapter(String fieldName) - { - if (fieldName == null) - { + public RRuleFieldAdapter(String fieldName) { + if (fieldName == null) { throw new IllegalArgumentException("fieldName must not be null"); } mFieldName = fieldName; } - @Override - String fieldName() - { + String fieldName() { return mFieldName; } - @Override - public RecurrenceRule getFrom(ContentValues values) - { + public RecurrenceRule getFrom(ContentValues values) { String rrule = values.getAsString(mFieldName); - if (rrule == null) - { + if (rrule == null) { return null; } - try - { + try { return new RecurrenceRule(rrule); - } - catch (InvalidRecurrenceRuleException e) - { + } catch (InvalidRecurrenceRuleException e) { throw new IllegalArgumentException("can not parse RRULE '" + rrule + "'", e); } } - @Override - public RecurrenceRule getFrom(Cursor cursor) - { + public RecurrenceRule getFrom(Cursor cursor) { int columnIdx = cursor.getColumnIndex(mFieldName); - if (columnIdx < 0) - { + if (columnIdx < 0) { throw new IllegalArgumentException("The column '" + mFieldName + "' is missing in cursor."); } - if (cursor.isNull(columnIdx)) - { + if (cursor.isNull(columnIdx)) { return null; } - try - { + try { return new RecurrenceRule(cursor.getString(columnIdx)); - } - catch (InvalidRecurrenceRuleException e) - { + } catch (InvalidRecurrenceRuleException e) { throw new IllegalArgumentException("can not parse RRULE '" + cursor.getString(columnIdx) + "'", e); } } - @Override - public void setIn(ContentValues values, RecurrenceRule value) - { - if (value != null) - { + public void setIn(ContentValues values, RecurrenceRule value) { + if (value != null) { values.put(mFieldName, value.toString()); - } - else - { + } else { values.putNull(mFieldName); } } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/SimpleFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/SimpleFieldAdapter.java index 2752ba9655f9468089c468549893b33e008c8ea4..01bc4233729e1f5381852ac93b8aae41e9db31c4 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/SimpleFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/SimpleFieldAdapter.java @@ -19,19 +19,17 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - /** - * An abstract {@link FieldAdapter} that implements a couple of methods as used by most simple FieldAdapters. + * An abstract {@link FieldAdapter} that implements a couple of methods as used + * by most simple FieldAdapters. * * @param - * The Type of the field this adapter handles. + * The Type of the field this adapter handles. * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public abstract class SimpleFieldAdapter implements FieldAdapter -{ +public abstract class SimpleFieldAdapter implements FieldAdapter { /** * Returns the sole field name of this adapter. @@ -40,61 +38,44 @@ public abstract class SimpleFieldAdapter implements Field */ abstract String fieldName(); - @Override - public boolean existsIn(ContentValues values) - { + public boolean existsIn(ContentValues values) { return values.get(fieldName()) != null; } - @Override - public boolean isSetIn(ContentValues values) - { + public boolean isSetIn(ContentValues values) { return values.containsKey(fieldName()); } - @Override - public boolean existsIn(Cursor cursor) - { + public boolean existsIn(Cursor cursor) { int columnIdx = cursor.getColumnIndex(fieldName()); return columnIdx >= 0 && !cursor.isNull(columnIdx); } - @Override - public FieldType getFrom(Cursor cursor, ContentValues values) - { + public FieldType getFrom(Cursor cursor, ContentValues values) { return values.containsKey(fieldName()) ? getFrom(values) : getFrom(cursor); } - @Override - public boolean existsIn(Cursor cursor, ContentValues values) - { + public boolean existsIn(Cursor cursor, ContentValues values) { return existsIn(values) || existsIn(cursor); } - @Override - public void removeFrom(ContentValues values) - { + public void removeFrom(ContentValues values) { values.remove(fieldName()); } - @Override - public void copyValue(Cursor cursor, ContentValues values) - { + public void copyValue(Cursor cursor, ContentValues values) { setIn(values, getFrom(cursor)); } - @Override - public void copyValue(ContentValues oldValues, ContentValues newValues) - { + public void copyValue(ContentValues oldValues, ContentValues newValues) { setIn(newValues, getFrom(oldValues)); } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/StringFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/StringFieldAdapter.java index 4c5311af2c61459862bf0cdb08e500023e9efd27..7e70babd6472e12731bd604a0600c17e27566119 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/StringFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/StringFieldAdapter.java @@ -19,76 +19,57 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - /** - * Knows how to load and store a {@link String} value from a {@link Cursor} or {@link ContentValues}. + * Knows how to load and store a {@link String} value from a {@link Cursor} or + * {@link ContentValues}. * * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class StringFieldAdapter extends SimpleFieldAdapter -{ +public final class StringFieldAdapter extends SimpleFieldAdapter { - /** - * The field name this adapter uses to store the values. - */ + /** The field name this adapter uses to store the values. */ private final String mFieldName; - /** * Constructor for a new {@link StringFieldAdapter}. * * @param fieldName - * The name of the field to use when loading or storing the value. + * The name of the field to use when loading or storing the value. */ - public StringFieldAdapter(String fieldName) - { - if (fieldName == null) - { + public StringFieldAdapter(String fieldName) { + if (fieldName == null) { throw new IllegalArgumentException("fieldName must not be null"); } mFieldName = fieldName; } - @Override - String fieldName() - { + String fieldName() { return mFieldName; } - @Override - public String getFrom(ContentValues values) - { + public String getFrom(ContentValues values) { // return the value as String return values.getAsString(mFieldName); } - @Override - public String getFrom(Cursor cursor) - { + public String getFrom(Cursor cursor) { int columnIdx = cursor.getColumnIndex(mFieldName); - if (columnIdx < 0) - { + if (columnIdx < 0) { throw new IllegalArgumentException("The column '" + mFieldName + "' is missing in cursor."); } return cursor.getString(columnIdx); } - @Override - public void setIn(ContentValues values, String value) - { - if (value != null) - { + public void setIn(ContentValues values, String value) { + if (value != null) { values.put(mFieldName, value); - } - else - { + } else { values.putNull(mFieldName); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/UrlFieldAdapter.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/UrlFieldAdapter.java index 53496b8da605b803b219c40a3d07570ea5e6fa9d..6cba7610e9b0f85393bf3d37913e560e6f42d000 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/UrlFieldAdapter.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/model/adapters/UrlFieldAdapter.java @@ -18,77 +18,59 @@ package org.dmfs.provider.tasks.model.adapters; import android.content.ContentValues; import android.database.Cursor; - import java.net.URI; import java.net.URL; - /** - * Knows how to load and store {@link URL} values from a {@link Cursor} or {@link ContentValues}. + * Knows how to load and store {@link URL} values from a {@link Cursor} or + * {@link ContentValues}. * * @param - * The type of the entity the field belongs to. - * + * The type of the entity the field belongs to. * @author Marten Gajda */ -public final class UrlFieldAdapter extends SimpleFieldAdapter -{ +public final class UrlFieldAdapter extends SimpleFieldAdapter { private final String mFieldName; - /** * Constructor for a new {@link UrlFieldAdapter}. * * @param urlField - * The field name that holds the URL. + * The field name that holds the URL. */ - public UrlFieldAdapter(String urlField) - { - if (urlField == null) - { + public UrlFieldAdapter(String urlField) { + if (urlField == null) { throw new IllegalArgumentException("urlField must not be null"); } mFieldName = urlField; } - @Override - String fieldName() - { + String fieldName() { return mFieldName; } - @Override - public URI getFrom(ContentValues values) - { + public URI getFrom(ContentValues values) { return values.get(mFieldName) == null ? null : URI.create(values.getAsString(mFieldName)); } - @Override - public URI getFrom(Cursor cursor) - { + public URI getFrom(Cursor cursor) { int columnIdx = cursor.getColumnIndex(mFieldName); - if (columnIdx < 0) - { + if (columnIdx < 0) { throw new IllegalArgumentException("The column '" + mFieldName + "' is missing in cursor."); } return cursor.isNull(columnIdx) ? null : URI.create(cursor.getString(columnIdx)); } - @Override - public void setIn(ContentValues values, URI value) - { - if (value != null) - { + public void setIn(ContentValues values, URI value) { + if (value != null) { values.put(mFieldName, value.toASCIIString()); - } - else - { + } else { values.putNull(mFieldName); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/EntityProcessor.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/EntityProcessor.java index 8ae6323f61621042ec96a450482ff19494a0e00f..0c7fe475f1c526ef4ad02776a9556cdcc3f901b6 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/EntityProcessor.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/EntityProcessor.java @@ -17,19 +17,15 @@ package org.dmfs.provider.tasks.processors; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.model.EntityAdapter; - /** * @author Marten Gajda */ -public interface EntityProcessor> -{ +public interface EntityProcessor> { T insert(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter); T update(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter); void delete(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter); - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/Logging.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/Logging.java index 87f7379fe6fdbf701a0cedd010567fd8feccd1bd..06b1c057a1204e99a3bfb32203d8417fcc9298a0 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/Logging.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/Logging.java @@ -18,48 +18,37 @@ package org.dmfs.provider.tasks.processors; import android.database.sqlite.SQLiteDatabase; import android.util.Log; - import org.dmfs.provider.tasks.model.EntityAdapter; - /** * @author Marten Gajda */ -public final class Logging> implements EntityProcessor -{ +public final class Logging> implements EntityProcessor { public static final String TAG = "Logging EntityProcessor"; private final EntityProcessor mDelegate; - - public Logging(EntityProcessor delegate) - { + public Logging(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public T insert(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) - { + public T insert(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) { Log.d(TAG, "before insert"); T result = mDelegate.insert(db, entityAdapter, isSyncAdapter); Log.d(TAG, "after insert on " + entityAdapter.id()); return result; } - @Override - public T update(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) - { + public T update(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) { Log.d(TAG, "before update of " + entityAdapter.id()); T result = mDelegate.update(db, entityAdapter, isSyncAdapter); Log.d(TAG, "after update of " + entityAdapter.id()); return result; } - @Override - public void delete(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) { Log.d(TAG, "before delete of " + entityAdapter.id()); mDelegate.delete(db, entityAdapter, isSyncAdapter); Log.d(TAG, "after delete of " + entityAdapter.id()); diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/NoOpProcessor.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/NoOpProcessor.java index d86f026af19f59d400baab7a5be81215c38f6683..12180a7623d59e327573b59f6ad7dfdf81ec69f1 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/NoOpProcessor.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/NoOpProcessor.java @@ -17,34 +17,26 @@ package org.dmfs.provider.tasks.processors; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.model.EntityAdapter; - /** * A simple No-Op {@link EntityProcessor}. * * @author Marten Gajda */ -public final class NoOpProcessor> implements EntityProcessor -{ +public final class NoOpProcessor> implements EntityProcessor { @Override - public T insert(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) - { + public T insert(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) { return entityAdapter; } - @Override - public T update(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) - { + public T update(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) { return entityAdapter; } - @Override - public void delete(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, T entityAdapter, boolean isSyncAdapter) { // do nothing } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/Detaching.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/Detaching.java index 8c98fd048a17b08f74cbdd86187eb9011a73ec43..3fe2bee1c18b570b78b8e2197d82a709436b7f5a 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/Detaching.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/Detaching.java @@ -16,10 +16,13 @@ package org.dmfs.provider.tasks.processors.instances; +import static java.util.Arrays.asList; + import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - +import java.util.HashSet; +import java.util.TimeZone; import org.dmfs.iterables.SingletonIterable; import org.dmfs.iterables.decorators.Sieved; import org.dmfs.jems.iterable.composite.Joined; @@ -45,60 +48,52 @@ import org.dmfs.rfc5545.recurrenceset.RecurrenceSet; import org.dmfs.rfc5545.recurrenceset.RecurrenceSetIterator; import org.dmfs.tasks.contract.TaskContract; -import java.util.HashSet; -import java.util.TimeZone; - -import static java.util.Arrays.asList; - - /** - * An instance {@link EntityProcessor} detaches completed instances at the start of a recurring task. + * An instance {@link EntityProcessor} detaches completed instances at the start + * of a recurring task. * * @author Marten Gajda */ -public final class Detaching implements EntityProcessor -{ +public final class Detaching implements EntityProcessor { private final EntityProcessor mDelegate; private final EntityProcessor mTaskDelegate; - - public Detaching(EntityProcessor delegate, EntityProcessor taskDelegate) - { + public Detaching(EntityProcessor delegate, EntityProcessor taskDelegate) { mDelegate = delegate; mTaskDelegate = taskDelegate; } - @Override - public InstanceAdapter insert(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) - { + public InstanceAdapter insert(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) { // just delegate for now - // if we ever support inserting instances, we'll have to make sure that inserting a completed instance results in a detached task + // if we ever support inserting instances, we'll have to make sure that + // inserting a completed + // instance results in a detached task return mDelegate.insert(db, entityAdapter, isSyncAdapter); } - /** * Detach the given instance if all of the following conditions are met + * *

- * - The instance is a recurrence instance (INSTANCE_ORIGINAL_TIME != null) - * - and the task has been closed (IS_CLOSED != 0) - * - and the instance is the first non-closed instance (DISTANCE_FROM_CURRENT==0). + * - The instance is a recurrence instance (INSTANCE_ORIGINAL_TIME != null) - + * and the task has been closed (IS_CLOSED != 0) - and the instance is the first + * non-closed instance (DISTANCE_FROM_CURRENT==0). + * *

*/ @Override - public InstanceAdapter update(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) - { + public InstanceAdapter update(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) { if (entityAdapter.valueOf(InstanceAdapter.DISTANCE_FROM_CURRENT) != 0 // not the first open task - // not closed, note we can't use IS_CLOSED at this point because its not updated yet - || (!new HashSet<>(asList(TaskContract.Tasks.STATUS_COMPLETED, TaskContract.Tasks.STATUS_CANCELLED)).contains( - entityAdapter.valueOf(new IntegerFieldAdapter<>(TaskContract.Tasks.STATUS)))) + // not closed, note we can't use IS_CLOSED at this point because its not updated + // yet + || (!new HashSet<>(asList(TaskContract.Tasks.STATUS_COMPLETED, TaskContract.Tasks.STATUS_CANCELLED)) + .contains(entityAdapter.valueOf(new IntegerFieldAdapter<>(TaskContract.Tasks.STATUS)))) // not recurring - || entityAdapter.valueOf(InstanceAdapter.INSTANCE_ORIGINAL_TIME) == null) - { + || entityAdapter.valueOf(InstanceAdapter.INSTANCE_ORIGINAL_TIME) == null) { // not a detachable instance return mDelegate.update(db, entityAdapter, isSyncAdapter); } @@ -106,57 +101,43 @@ public final class Detaching implements EntityProcessor return detachAll(db, mDelegate.update(db, entityAdapter, isSyncAdapter)); } - @Override - public void delete(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) { // just delegate mDelegate.delete(db, entityAdapter, isSyncAdapter); } - /** * Detach all closed instances preceding the given one. + * *

* TODO: this method needs some refactoring */ - private InstanceAdapter detachAll(SQLiteDatabase db, InstanceAdapter entityAdapter) - { + private InstanceAdapter detachAll(SQLiteDatabase db, InstanceAdapter entityAdapter) { // keep some values for later long masterId = new FirstPresent<>( - new NullSafe<>(entityAdapter.valueOf(new LongFieldAdapter<>(TaskContract.Instances.ORIGINAL_INSTANCE_ID))), + new NullSafe<>( + entityAdapter.valueOf(new LongFieldAdapter<>(TaskContract.Instances.ORIGINAL_INSTANCE_ID))), new NullSafe<>(entityAdapter.valueOf(new LongFieldAdapter<>(TaskContract.Instances.TASK_ID)))).value(); DateTime instanceOriginalTime = entityAdapter.valueOf(InstanceAdapter.INSTANCE_ORIGINAL_TIME); // detach instances which are completed - try (Cursor instances = db.query(TaskDatabaseHelper.Tables.INSTANCE_VIEW, - null, - String.format("%s < 0 and %s == ?", TaskContract.Instances.DISTANCE_FROM_CURRENT, TaskContract.Instances.ORIGINAL_INSTANCE_ID), - new String[] { String.valueOf(masterId) }, - null, - null, - null)) - { - while (instances.moveToNext()) - { + try (Cursor instances = db.query(TaskDatabaseHelper.Tables.INSTANCE_VIEW, null, + String.format("%s < 0 and %s == ?", TaskContract.Instances.DISTANCE_FROM_CURRENT, + TaskContract.Instances.ORIGINAL_INSTANCE_ID), + new String[]{String.valueOf(masterId)}, null, null, null)) { + while (instances.moveToNext()) { detachSingle(db, new CursorContentValuesInstanceAdapter(instances, new ContentValues())); } } // move the master to the first incomplete task - try (Cursor task = db.query(TaskDatabaseHelper.Tables.TASKS_VIEW, - null, - String.format("%s == ?", TaskContract.Tasks._ID), - new String[] { String.valueOf(masterId) }, - null, - null, - null)) - { - if (task.moveToFirst()) - { + try (Cursor task = db.query(TaskDatabaseHelper.Tables.TASKS_VIEW, null, + String.format("%s == ?", TaskContract.Tasks._ID), new String[]{String.valueOf(masterId)}, null, null, + null)) { + if (task.moveToFirst()) { TaskAdapter masterTask = new CursorContentValuesTaskAdapter(task, new ContentValues()); - DateTime oldStart = new FirstPresent<>( - new NullSafe<>(masterTask.valueOf(TaskAdapter.DTSTART)), + DateTime oldStart = new FirstPresent<>(new NullSafe<>(masterTask.valueOf(TaskAdapter.DTSTART)), new NullSafe<>(masterTask.valueOf(TaskAdapter.DUE))).value(); // assume we have no instances left @@ -165,26 +146,22 @@ public final class Detaching implements EntityProcessor // update RRULE, if existent RecurrenceRule rule = masterTask.valueOf(TaskAdapter.RRULE); int count = 0; - if (rule != null) - { + if (rule != null) { RecurrenceSet ruleSet = new RecurrenceSet(); ruleSet.addInstances(new RecurrenceRuleAdapter(rule)); - if (rule.getCount() == null) - { + if (rule.getCount() == null) { // rule has no count limit, allowing us to exclude exdates - ruleSet.addExceptions(new RecurrenceList(new Timestamps(masterTask.valueOf(TaskAdapter.EXDATE)).value())); + ruleSet.addExceptions( + new RecurrenceList(new Timestamps(masterTask.valueOf(TaskAdapter.EXDATE)).value())); } - RecurrenceSetIterator ruleIterator = ruleSet.iterator( - oldStart.getTimeZone(), + RecurrenceSetIterator ruleIterator = ruleSet.iterator(oldStart.getTimeZone(), oldStart.getTimestamp()); // move DTSTART to next RRULE instance which is > instanceOriginalTime // reduce COUNT by the number of skipped instances, if present - while (count < 1000 && ruleIterator.hasNext()) - { + while (count < 1000 && ruleIterator.hasNext()) { DateTime inst = new DateTime(oldStart.getTimeZone(), ruleIterator.next()); - if (instanceOriginalTime.before(inst)) - { + if (instanceOriginalTime.before(inst)) { updateStart(masterTask, inst); noInstances = false; // just found another instance break; @@ -192,60 +169,55 @@ public final class Detaching implements EntityProcessor count += 1; } - if (noInstances) - { + if (noInstances) { // remove the RRULE but keep a mask for the old start - masterTask.set(TaskAdapter.EXDATE, - new Joined<>(new SingletonIterable<>(oldStart), new Sieved<>(new Not<>(oldStart::equals), masterTask.valueOf(TaskAdapter.EXDATE)))); + masterTask.set(TaskAdapter.EXDATE, new Joined<>(new SingletonIterable<>(oldStart), + new Sieved<>(new Not<>(oldStart::equals), masterTask.valueOf(TaskAdapter.EXDATE)))); masterTask.set(TaskAdapter.RRULE, null); - } - else - { + } else { // adjust COUNT if present - if (rule.getCount() != null) - { + if (rule.getCount() != null) { rule.setCount(rule.getCount() - count); masterTask.set(TaskAdapter.RRULE, rule); } } } - DateTime newStart = new FirstPresent<>( - new NullSafe<>(masterTask.valueOf(TaskAdapter.DTSTART)), + DateTime newStart = new FirstPresent<>(new NullSafe<>(masterTask.valueOf(TaskAdapter.DTSTART)), new NullSafe<>(masterTask.valueOf(TaskAdapter.DUE))).value(); // update RDATE and EXDATE - masterTask.set(TaskAdapter.RDATE, new Sieved<>(instanceOriginalTime::before, masterTask.valueOf(TaskAdapter.RDATE))); + masterTask.set(TaskAdapter.RDATE, + new Sieved<>(instanceOriginalTime::before, masterTask.valueOf(TaskAdapter.RDATE))); masterTask.set(TaskAdapter.EXDATE, - new Sieved<>(new AnyOf<>(instanceOriginalTime::before, newStart::equals), masterTask.valueOf(TaskAdapter.EXDATE))); + new Sieved<>(new AnyOf<>(instanceOriginalTime::before, newStart::equals), + masterTask.valueOf(TaskAdapter.EXDATE))); // First check if we still have any RDATE instances left - // TODO: 6 lines for something we should be able to express in one simple expression, we need to straighten lib-recur!! + // TODO: 6 lines for something we should be able to express in one simple + // expression, we + // need to straighten lib-recur!! RecurrenceSet rdateSet = new RecurrenceSet(); - rdateSet.addInstances(new RecurrenceList(new Timestamps(masterTask.valueOf(TaskAdapter.RDATE)).value())); - rdateSet.addExceptions(new RecurrenceList(new Timestamps(masterTask.valueOf(TaskAdapter.EXDATE)).value())); + rdateSet.addInstances( + new RecurrenceList(new Timestamps(masterTask.valueOf(TaskAdapter.RDATE)).value())); + rdateSet.addExceptions( + new RecurrenceList(new Timestamps(masterTask.valueOf(TaskAdapter.EXDATE)).value())); RecurrenceSetIterator iterator = rdateSet.iterator(DateTime.UTC, Long.MIN_VALUE); iterator.fastForward(Long.MIN_VALUE + 1); // skip bogus start noInstances &= !iterator.hasNext(); - if (noInstances) - { + if (noInstances) { // no more instances left, remove the master mTaskDelegate.delete(db, masterTask, false); - } - else - { - if (masterTask.valueOf(TaskAdapter.RRULE) == null) - { + } else { + if (masterTask.valueOf(TaskAdapter.RRULE) == null) { // we don't have any RRULE, allowing us to adjust DTSTART/DUE to the first RDATE DateTime start = new DateTime(iterator.next()); - if (masterTask.valueOf(TaskAdapter.IS_ALLDAY)) - { + if (masterTask.valueOf(TaskAdapter.IS_ALLDAY)) { start = start.toAllDay(); - } - else if (masterTask.valueOf(TaskAdapter.TIMEZONE_RAW) != null) - { - start = start.shiftTimeZone(TimeZone.getTimeZone(masterTask.valueOf(TaskAdapter.TIMEZONE_RAW))); + } else if (masterTask.valueOf(TaskAdapter.TIMEZONE_RAW) != null) { + start = start + .shiftTimeZone(TimeZone.getTimeZone(masterTask.valueOf(TaskAdapter.TIMEZONE_RAW))); } updateStart(masterTask, start); } @@ -259,44 +231,37 @@ public final class Detaching implements EntityProcessor return entityAdapter; } - - private void updateStart(TaskAdapter task, DateTime newStart) - { + private void updateStart(TaskAdapter task, DateTime newStart) { // this new instance becomes the new start (or due if we don't have a start) - if (task.valueOf(TaskAdapter.DTSTART) != null) - { + if (task.valueOf(TaskAdapter.DTSTART) != null) { DateTime oldStart = task.valueOf(TaskAdapter.DTSTART); task.set(TaskAdapter.DTSTART, newStart); - if (task.valueOf(TaskAdapter.DUE) != null) - { + if (task.valueOf(TaskAdapter.DUE) != null) { long duration = task.valueOf(TaskAdapter.DUE).getTimestamp() - oldStart.getTimestamp(); - task.set(TaskAdapter.DUE, - newStart.addDuration( - new Duration(1, (int) (duration / (3600 * 24 * 1000)), (int) (duration % (3600 * 24 * 1000)) / 1000))); + task.set(TaskAdapter.DUE, newStart.addDuration(new Duration(1, (int) (duration / (3600 * 24 * 1000)), + (int) (duration % (3600 * 24 * 1000)) / 1000))); } - } - else - { + } else { task.set(TaskAdapter.DUE, newStart); } - } - /** * Detach the given instance. + * *

- * - clone the override into a new deleted task (set _DELETED == 1) - * - detach the original override by removing the ORIGINAL_INSTANCE_ID, ORIGINAL_INSTANCE_SYNC_ID, ORIGINAL_INSTANCE_START and ORIGINAL_INSTANCE_ALLDAY - * (i.e. all columns which relate this to the original) + * - clone the override into a new deleted task (set _DELETED == 1) - detach the + * original override by removing the ORIGINAL_INSTANCE_ID, + * ORIGINAL_INSTANCE_SYNC_ID, ORIGINAL_INSTANCE_START and + * ORIGINAL_INSTANCE_ALLDAY (i.e. all columns which relate this to the original) * - wipe _SYNC_ID, _UID and all sync columns (make this an unsynced task) */ - private void detachSingle(SQLiteDatabase db, InstanceAdapter entityAdapter) - { + private void detachSingle(SQLiteDatabase db, InstanceAdapter entityAdapter) { TaskAdapter original = entityAdapter.taskAdapter(); TaskAdapter cloneAdapter = original.duplicate(); - // first prepare the original to resemble the same instance but as a new, detached task + // first prepare the original to resemble the same instance but as a new, + // detached task original.set(TaskAdapter.SYNC_ID, null); original.set(TaskAdapter.SYNC_VERSION, null); original.set(TaskAdapter.SYNC1, null); @@ -318,7 +283,8 @@ public final class Detaching implements EntityProcessor // wipe INSTANCE_ORIGINAL_TIME from instances entry ContentValues noOriginalTime = new ContentValues(); noOriginalTime.putNull(TaskContract.Instances.INSTANCE_ORIGINAL_TIME); - db.update(TaskDatabaseHelper.Tables.INSTANCES, noOriginalTime, "_ID = ?", new String[] { String.valueOf(entityAdapter.id()) }); + db.update(TaskDatabaseHelper.Tables.INSTANCES, noOriginalTime, "_ID = ?", + new String[]{String.valueOf(entityAdapter.id())}); // reset the clone to be a deleted instance cloneAdapter.set(TaskAdapter._DELETED, true); diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/TaskValueDelegate.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/TaskValueDelegate.java index f02ed1da305bfb024c40d267cc02b0e2b3d9f4d0..688cfe85fafe1b285926a7b8dca1fcfe14496cfb 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/TaskValueDelegate.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/TaskValueDelegate.java @@ -20,7 +20,7 @@ import android.content.ContentValues; import android.database.Cursor; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; - +import java.util.Locale; import org.dmfs.iterables.decorators.Filtered; import org.dmfs.iterables.elementary.Seq; import org.dmfs.iterators.filters.NoneOf; @@ -40,85 +40,57 @@ import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; -import java.util.Locale; - - /** - * An instance {@link EntityProcessor} which delegates to the appropriate task {@link EntityProcessor}. + * An instance {@link EntityProcessor} which delegates to the appropriate task + * {@link EntityProcessor}. * * @author Marten Gajda */ -public final class TaskValueDelegate implements EntityProcessor -{ - private final static Iterable> SPECIAL_FIELD_ADAPTERS = new Seq<>( - TaskAdapter.SYNC1, - TaskAdapter.SYNC2, - TaskAdapter.SYNC3, - TaskAdapter.SYNC4, - TaskAdapter.SYNC5, - TaskAdapter.SYNC6, - TaskAdapter.SYNC7, - TaskAdapter.SYNC8, - TaskAdapter.SYNC_ID, - TaskAdapter.SYNC_VERSION, +public final class TaskValueDelegate implements EntityProcessor { + private static final Iterable> SPECIAL_FIELD_ADAPTERS = new Seq<>(TaskAdapter.SYNC1, + TaskAdapter.SYNC2, TaskAdapter.SYNC3, TaskAdapter.SYNC4, TaskAdapter.SYNC5, TaskAdapter.SYNC6, + TaskAdapter.SYNC7, TaskAdapter.SYNC8, TaskAdapter.SYNC_ID, TaskAdapter.SYNC_VERSION, // unset any list and read-only fields - TaskAdapter.VERSION, - TaskAdapter.ACCOUNT_NAME, - TaskAdapter.ACCOUNT_TYPE, - TaskAdapter.LIST_VISIBLE, - TaskAdapter.LIST_COLOR, - TaskAdapter.LIST_NAME, - TaskAdapter.LIST_ACCESS_LEVEL, - TaskAdapter.LIST_OWNER, - TaskAdapter._DELETED, - TaskAdapter._DIRTY, - TaskAdapter.IS_NEW, - TaskAdapter.IS_CLOSED, - TaskAdapter.HAS_PROPERTIES, - TaskAdapter.HAS_ALARMS, - TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID, /* this will be resolved automatically */ + TaskAdapter.VERSION, TaskAdapter.ACCOUNT_NAME, TaskAdapter.ACCOUNT_TYPE, TaskAdapter.LIST_VISIBLE, + TaskAdapter.LIST_COLOR, TaskAdapter.LIST_NAME, TaskAdapter.LIST_ACCESS_LEVEL, TaskAdapter.LIST_OWNER, + TaskAdapter._DELETED, TaskAdapter._DIRTY, TaskAdapter.IS_NEW, TaskAdapter.IS_CLOSED, + TaskAdapter.HAS_PROPERTIES, TaskAdapter.HAS_ALARMS, TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID, /* + * this will be + * resolved + * automatically + */ // also unset any recurrence fields - TaskAdapter.RRULE, - TaskAdapter.RDATE, - TaskAdapter.EXDATE, - TaskAdapter.CREATED, - TaskAdapter.LAST_MODIFIED - ); + TaskAdapter.RRULE, TaskAdapter.RDATE, TaskAdapter.EXDATE, TaskAdapter.CREATED, TaskAdapter.LAST_MODIFIED); private final EntityProcessor mDelegate; - - public TaskValueDelegate(EntityProcessor delegate) - { + public TaskValueDelegate(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public InstanceAdapter insert(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) - { + public InstanceAdapter insert(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) { TaskAdapter taskAdapter = entityAdapter.taskAdapter(); Long masterTaskId = null; - if (taskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null) - { - // this is going to be an override to an existing task - make sure we add an RDATE first + if (taskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null) { + // this is going to be an override to an existing task - make sure we add an + // RDATE first masterTaskId = taskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID); DateTime originalTime = taskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_TIME); // get the master and add an rdate - try (Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, null /* all */, TaskContract.Tasks._ID + "=" + masterTaskId, null, null, null, null)) - { - if (c.moveToFirst()) - { - TaskAdapter masterTaskAdapter = new CursorContentValuesTaskAdapter(masterTaskId, c, new ContentValues()); - if (masterTaskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null) - { + try (Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, null /* all */, + TaskContract.Tasks._ID + "=" + masterTaskId, null, null, null, null)) { + if (c.moveToFirst()) { + TaskAdapter masterTaskAdapter = new CursorContentValuesTaskAdapter(masterTaskId, c, + new ContentValues()); + if (masterTaskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null) { throw new IllegalArgumentException("Can't add an instance to an override instance"); } - DateTime masterDate = new Backed(new FirstPresent<>(new Seq<>( - new NullSafe<>(masterTaskAdapter.valueOf(TaskAdapter.DTSTART)), - new NullSafe<>(masterTaskAdapter.valueOf(TaskAdapter.DUE)))), () -> null).value(); - if (!masterTaskAdapter.isRecurring() && masterDate != null) - { + DateTime masterDate = new Backed( + new FirstPresent<>(new Seq<>(new NullSafe<>(masterTaskAdapter.valueOf(TaskAdapter.DTSTART)), + new NullSafe<>(masterTaskAdapter.valueOf(TaskAdapter.DUE)))), + () -> null).value(); + if (!masterTaskAdapter.isRecurring() && masterDate != null) { // master is not recurring yet, also add its start as an RDATE appendDate(masterTaskAdapter, TaskAdapter.RDATE, TaskAdapter.EXDATE, masterDate); } @@ -126,10 +98,9 @@ public final class TaskValueDelegate implements EntityProcessor appendDate(masterTaskAdapter, TaskAdapter.RDATE, TaskAdapter.EXDATE, originalTime); mDelegate.update(db, masterTaskAdapter, false); - } - else - { - throw new IllegalArgumentException(String.format(Locale.ENGLISH, "No task with _ID %d found", masterTaskId)); + } else { + throw new IllegalArgumentException( + String.format(Locale.ENGLISH, "No task with _ID %d found", masterTaskId)); } } } @@ -137,48 +108,46 @@ public final class TaskValueDelegate implements EntityProcessor // move on with inserting the instance TaskAdapter taskResult = mDelegate.insert(db, entityAdapter.taskAdapter(), false); - if (masterTaskId != null) - { - // we just cloned the master task into a new instance, we need to copy the properties as well + if (masterTaskId != null) { + // we just cloned the master task into a new instance, we need to copy the + // properties as well copyProperties(db, masterTaskId, taskResult.id()); } - try (Cursor c = db.query(TaskDatabaseHelper.Tables.INSTANCES, new String[] { TaskContract.Instances._ID }, - TaskContract.Instances.TASK_ID + "=" + taskResult.id(), null, null, null, null)) - { + try (Cursor c = db.query(TaskDatabaseHelper.Tables.INSTANCES, new String[]{TaskContract.Instances._ID}, + TaskContract.Instances.TASK_ID + "=" + taskResult.id(), null, null, null, null)) { // the cursor should contain exactly one row after this operation c.moveToFirst(); return new ContentValuesInstanceAdapter(c.getLong(0), new ContentValues()); } } - @Override - public InstanceAdapter update(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) - { - // if this is the master of a recurring task, we create a new instance or update an existing one for this override, otherwise we just delegate + public InstanceAdapter update(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) { + // if this is the master of a recurring task, we create a new instance or update + // an existing one + // for this override, otherwise we just delegate TaskAdapter taskAdapter = entityAdapter.taskAdapter(); - if (taskAdapter.isRecurring()) - { + if (taskAdapter.isRecurring()) { // clone the task to create an unsynced override InstanceAdapter newInstanceAdapter = entityAdapter.duplicate(); TaskAdapter override = newInstanceAdapter.taskAdapter(); override.set(TaskAdapter.ORIGINAL_INSTANCE_ID, entityAdapter.valueOf(InstanceAdapter.TASK_ID)); - override.set(TaskAdapter.ORIGINAL_INSTANCE_TIME, entityAdapter.valueOf(InstanceAdapter.INSTANCE_ORIGINAL_TIME)); + override.set(TaskAdapter.ORIGINAL_INSTANCE_TIME, + entityAdapter.valueOf(InstanceAdapter.INSTANCE_ORIGINAL_TIME)); // unset all fields which have special meaning - for (FieldAdapter specialFieldAdapter : SPECIAL_FIELD_ADAPTERS) - { + for (FieldAdapter specialFieldAdapter : SPECIAL_FIELD_ADAPTERS) { override.unset(specialFieldAdapter); } - // make sure we update DTSTART and DUE to match the instance values (unless they are set explicitly) - if (!taskAdapter.isUpdated(TaskAdapter.DTSTART)) - { + // make sure we update DTSTART and DUE to match the instance values (unless they + // are set + // explicitly) + if (!taskAdapter.isUpdated(TaskAdapter.DTSTART)) { // set DTSTART to the instance start override.set(TaskAdapter.DTSTART, newInstanceAdapter.valueOf(InstanceAdapter.INSTANCE_START)); } - if (!taskAdapter.isUpdated(TaskAdapter.DUE) && !taskAdapter.isUpdated(TaskAdapter.DURATION)) - { + if (!taskAdapter.isUpdated(TaskAdapter.DUE) && !taskAdapter.isUpdated(TaskAdapter.DURATION)) { // set DUE to the effective instance DUE and wipe any duration override.set(TaskAdapter.DUE, newInstanceAdapter.valueOf(InstanceAdapter.INSTANCE_DUE)); override.set(TaskAdapter.DURATION, null); @@ -189,31 +158,30 @@ public final class TaskValueDelegate implements EntityProcessor TaskAdapter newTask = mDelegate.insert(db, override, false); copyProperties(db, taskAdapter.id(), newTask.id()); - } - else - { - // this is a non-recurring task or it's already an override, just delegate the update + } else { + // this is a non-recurring task or it's already an override, just delegate the + // update mDelegate.update(db, taskAdapter, false); } return entityAdapter; } - @Override - public void delete(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) - { - // deleted instances are converted to deleted tasks (for non-recurring tasks) or exdates (for recurring tasks). + public void delete(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) { + // deleted instances are converted to deleted tasks (for non-recurring tasks) or + // exdates (for + // recurring tasks). TaskAdapter taskAdapter = entityAdapter.taskAdapter(); - if (taskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null) - { - /* this is an override - we have to: - * - mark it deleted - * - add an exclusion to the master task + if (taskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null) { + /* + * this is an override - we have to: - mark it deleted - add an exclusion to the + * master task * - * TODO: if this instance was added by an RDATE, just remove the RDATE - * TODO: if this is the first instance, consider moving the recurrence start instead of adding an exdate - * TODO: if this is the last instance of a finite task, consider just setting a new recurrence end + * TODO: if this instance was added by an RDATE, just remove the RDATE TODO: if + * this is the first instance, consider moving the recurrence start instead of + * adding an exdate TODO: if this is the last instance of a finite task, + * consider just setting a new recurrence end */ long masterTaskId = taskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID); DateTime originalTime = entityAdapter.valueOf(InstanceAdapter.INSTANCE_ORIGINAL_TIME); @@ -222,58 +190,59 @@ public final class TaskValueDelegate implements EntityProcessor mDelegate.delete(db, taskAdapter, false); // get the master and add an exdate - try (Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, null /* all */, TaskContract.Tasks._ID + "=" + masterTaskId, null, null, null, null)) - { - if (c.moveToFirst()) - { - TaskAdapter masterTaskAdapter = new CursorContentValuesTaskAdapter(masterTaskId, c, new ContentValues()); + try (Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, null /* all */, + TaskContract.Tasks._ID + "=" + masterTaskId, null, null, null, null)) { + if (c.moveToFirst()) { + TaskAdapter masterTaskAdapter = new CursorContentValuesTaskAdapter(masterTaskId, c, + new ContentValues()); appendDate(masterTaskAdapter, TaskAdapter.EXDATE, TaskAdapter.RDATE, originalTime); mDelegate.update(db, masterTaskAdapter, false); } } - } - else if (taskAdapter.isRecurring()) - { - // TODO: if this is the first instance, consider moving the recurrence start instead of adding an exdate - // TODO: if this is the last instance of a finite task, consider just setting a new recurrence end - appendDate(taskAdapter, TaskAdapter.EXDATE, TaskAdapter.RDATE, entityAdapter.valueOf(InstanceAdapter.INSTANCE_ORIGINAL_TIME)); + } else if (taskAdapter.isRecurring()) { + // TODO: if this is the first instance, consider moving the recurrence start + // instead of adding + // an exdate + // TODO: if this is the last instance of a finite task, consider just setting a + // new recurrence + // end + appendDate(taskAdapter, TaskAdapter.EXDATE, TaskAdapter.RDATE, + entityAdapter.valueOf(InstanceAdapter.INSTANCE_ORIGINAL_TIME)); mDelegate.update(db, taskAdapter, false); - } - else - { - // task is non-recurring, delete it as a non-sync-adapter (effectively setting the _deleted flag) + } else { + // task is non-recurring, delete it as a non-sync-adapter (effectively setting + // the _deleted + // flag) mDelegate.delete(db, taskAdapter, false); } } - - private void appendDate(TaskAdapter taskAdapter, FieldAdapter, TaskAdapter> addfieldAdapter, FieldAdapter, TaskAdapter> removefieldAdapter, DateTime dateTime) - { - taskAdapter.set(addfieldAdapter, new Joined<>(new Filtered<>(taskAdapter.valueOf(addfieldAdapter), new NoneOf<>(dateTime)), new Seq<>(dateTime))); - taskAdapter.set(removefieldAdapter, new Filtered<>(taskAdapter.valueOf(removefieldAdapter), new NoneOf<>(dateTime))); + private void appendDate(TaskAdapter taskAdapter, FieldAdapter, TaskAdapter> addfieldAdapter, + FieldAdapter, TaskAdapter> removefieldAdapter, DateTime dateTime) { + taskAdapter.set(addfieldAdapter, new Joined<>( + new Filtered<>(taskAdapter.valueOf(addfieldAdapter), new NoneOf<>(dateTime)), new Seq<>(dateTime))); + taskAdapter.set(removefieldAdapter, + new Filtered<>(taskAdapter.valueOf(removefieldAdapter), new NoneOf<>(dateTime))); } - /** * Copy the properties from the give original task to the new task. * * @param db - * The {@link SQLiteDatabase} + * The {@link SQLiteDatabase} * @param originalId - * The ID of the task of which to copy the properties + * The ID of the task of which to copy the properties * @param newId - * The ID of the task to copy the properties to. + * The ID of the task to copy the properties to. */ - private void copyProperties(SQLiteDatabase db, long originalId, long newId) - { + private void copyProperties(SQLiteDatabase db, long originalId, long newId) { // for each property of the original task try (Cursor c = db.query(TaskDatabaseHelper.Tables.PROPERTIES, null /* all */, - String.format(Locale.ENGLISH, "%s = %d", TaskContract.Properties.TASK_ID, originalId), null, null, null, null)) - { + String.format(Locale.ENGLISH, "%s = %d", TaskContract.Properties.TASK_ID, originalId), null, null, null, + null)) { // load the property and insert it for the new task ContentValues values = new ContentValues(c.getColumnCount()); - while (c.moveToNext()) - { + while (c.moveToNext()) { values.clear(); DatabaseUtils.cursorRowToContentValues(c, values); PropertyHandler ph = PropertyHandlerFactory.get(values.getAsString(TaskContract.Properties.MIMETYPE)); diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/Validating.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/Validating.java index 238e65015ccd7aee9bff8abd01393f4418fec058..5410e0446db3caf7bd3e6cfd1cce4c8bad66a5c5 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/Validating.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/instances/Validating.java @@ -18,7 +18,7 @@ package org.dmfs.provider.tasks.processors.instances; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - +import java.util.Locale; import org.dmfs.iterables.decorators.Sieved; import org.dmfs.iterables.elementary.Seq; import org.dmfs.jems.optional.Optional; @@ -32,49 +32,32 @@ import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; -import java.util.Locale; - - /** * An {@link EntityProcessor} which validates the instance data. * * @author Marten Gajda */ -public final class Validating implements EntityProcessor -{ - private final static Iterable> INSTANCE_FIELD_ADAPTERS = new Seq<>( - InstanceAdapter._ID, - InstanceAdapter.INSTANCE_START, - InstanceAdapter.INSTANCE_START_SORTING, - InstanceAdapter.INSTANCE_DUE, - InstanceAdapter.INSTANCE_DUE_SORTING, - InstanceAdapter.INSTANCE_ORIGINAL_TIME, - InstanceAdapter.DISTANCE_FROM_CURRENT, - InstanceAdapter.TASK_ID); - - private final static Iterable> RECURRENCE_FIELD_ADAPTERS = new Seq<>( - TaskAdapter.RRULE, - TaskAdapter.RDATE, - TaskAdapter.EXDATE); +public final class Validating implements EntityProcessor { + private static final Iterable> INSTANCE_FIELD_ADAPTERS = new Seq<>( + InstanceAdapter._ID, InstanceAdapter.INSTANCE_START, InstanceAdapter.INSTANCE_START_SORTING, + InstanceAdapter.INSTANCE_DUE, InstanceAdapter.INSTANCE_DUE_SORTING, InstanceAdapter.INSTANCE_ORIGINAL_TIME, + InstanceAdapter.DISTANCE_FROM_CURRENT, InstanceAdapter.TASK_ID); + + private static final Iterable> RECURRENCE_FIELD_ADAPTERS = new Seq<>(TaskAdapter.RRULE, + TaskAdapter.RDATE, TaskAdapter.EXDATE); private static final Iterable> ORIGINAL_INSTANCE_FIELD_ADAPTERS = new Seq<>( - TaskAdapter.ORIGINAL_INSTANCE_ID, - TaskAdapter.ORIGINAL_INSTANCE_TIME, - TaskAdapter.ORIGINAL_INSTANCE_ALLDAY, + TaskAdapter.ORIGINAL_INSTANCE_ID, TaskAdapter.ORIGINAL_INSTANCE_TIME, TaskAdapter.ORIGINAL_INSTANCE_ALLDAY, TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID); private final EntityProcessor mDelegate; - - public Validating(EntityProcessor delegate) - { + public Validating(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public InstanceAdapter insert(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) - { + public InstanceAdapter insert(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) { validateIsSyncAdapter(isSyncAdapter); validateValues(entityAdapter); validateInstanceIsNew(db, entityAdapter); @@ -82,105 +65,91 @@ public final class Validating implements EntityProcessor return mDelegate.insert(db, entityAdapter, false); } - @Override - public InstanceAdapter update(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) - { + public InstanceAdapter update(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) { validateIsSyncAdapter(isSyncAdapter); validateValues(entityAdapter); validateOriginalInstanceValues(entityAdapter); return mDelegate.update(db, entityAdapter, false); } - @Override - public void delete(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, InstanceAdapter entityAdapter, boolean isSyncAdapter) { validateIsSyncAdapter(isSyncAdapter); mDelegate.delete(db, entityAdapter, false); } - - private void validateIsSyncAdapter(boolean isSyncAdapter) - { - if (isSyncAdapter) - { + private void validateIsSyncAdapter(boolean isSyncAdapter) { + if (isSyncAdapter) { throw new UnsupportedOperationException("Sync adapters are not expected to write to the instances table."); } } + private void validateInstanceIsNew(SQLiteDatabase db, InstanceAdapter entityAdapter) { + Optional instanceId = new NullSafe<>( + entityAdapter.taskAdapter().valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID)); + Optional instanceTime = new NullSafe<>( + entityAdapter.taskAdapter().valueOf(TaskAdapter.ORIGINAL_INSTANCE_TIME)); - private void validateInstanceIsNew(SQLiteDatabase db, InstanceAdapter entityAdapter) - { - Optional instanceId = new NullSafe<>(entityAdapter.taskAdapter().valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID)); - Optional instanceTime = new NullSafe<>(entityAdapter.taskAdapter().valueOf(TaskAdapter.ORIGINAL_INSTANCE_TIME)); - - // check if ORIGINAL_INSTANCE_ID and ORIGINAL_INSTANCE_TIME are both present/absent at the same time - if (instanceId.isPresent() != instanceTime.isPresent()) - { + // check if ORIGINAL_INSTANCE_ID and ORIGINAL_INSTANCE_TIME are both + // present/absent at the same + // time + if (instanceId.isPresent() != instanceTime.isPresent()) { throw new IllegalArgumentException(String.format("%s and %s must either be both absent or both present", TaskContract.Tasks.ORIGINAL_INSTANCE_ID, TaskContract.Tasks.ORIGINAL_INSTANCE_TIME)); } - if (instanceId.isPresent()) - { + if (instanceId.isPresent()) { String timeStampString = Long.toString(instanceTime.value().getTimestamp()); // Make sure there is no instance at the given time already - try (Cursor c = db.query( - TaskDatabaseHelper.Tables.INSTANCE_VIEW, - new String[] { TaskContract.Instances._ID }, - // find any instance which refers to the given original ID and has the same instance time - // for recurring tasks this matches the INSTANCE_ORIGINAL_TIME, for non-recurring tasks this matches start or due (whichever is present). - String.format("(%1$s == ? or %2$s == ?) and (%3$s == ? or %3$s is null and %4$s == ? or %3$s is null and %4$s is null and %5$s == ?) ", - TaskContract.Instances.TASK_ID, - TaskContract.Instances.ORIGINAL_INSTANCE_ID, - TaskContract.Instances.INSTANCE_ORIGINAL_TIME, - TaskContract.Instances.INSTANCE_START, + try (Cursor c = db.query(TaskDatabaseHelper.Tables.INSTANCE_VIEW, new String[]{TaskContract.Instances._ID}, + // find any instance which refers to the given original ID and has the same + // instance + // time + // for recurring tasks this matches the INSTANCE_ORIGINAL_TIME, for + // non-recurring + // tasks this matches start or due (whichever is present). + String.format( + "(%1$s == ? or %2$s == ?) and (%3$s == ? or %3$s is null and %4$s == ? or %3$s is null and %4$s is null and %5$s == ?) ", + TaskContract.Instances.TASK_ID, TaskContract.Instances.ORIGINAL_INSTANCE_ID, + TaskContract.Instances.INSTANCE_ORIGINAL_TIME, TaskContract.Instances.INSTANCE_START, TaskContract.Instances.INSTANCE_DUE), - new String[] { - instanceId.value().toString(), - instanceId.value().toString(), - timeStampString, - timeStampString, - timeStampString }, - null, - null, - null)) - { - if (c.getCount() > 0) - { - throw new IllegalArgumentException(String.format(Locale.ENGLISH, "Instance %s of task %d already exists", - entityAdapter.taskAdapter().valueOf(TaskAdapter.ORIGINAL_INSTANCE_TIME).toString(), instanceId.value())); + new String[]{instanceId.value().toString(), instanceId.value().toString(), timeStampString, + timeStampString, timeStampString}, + null, null, null)) { + if (c.getCount() > 0) { + throw new IllegalArgumentException( + String.format(Locale.ENGLISH, "Instance %s of task %d already exists", + entityAdapter.taskAdapter().valueOf(TaskAdapter.ORIGINAL_INSTANCE_TIME).toString(), + instanceId.value())); } } } } - - private void validateValues(InstanceAdapter instanceAdapter) - { - // actually, no instance value can be changed, the instance table only allows for updating task values - if (new First<>(new Sieved<>(instanceAdapter::isUpdated, INSTANCE_FIELD_ADAPTERS)).isPresent()) - { + private void validateValues(InstanceAdapter instanceAdapter) { + // actually, no instance value can be changed, the instance table only allows + // for updating task + // values + if (new First<>(new Sieved<>(instanceAdapter::isUpdated, INSTANCE_FIELD_ADAPTERS)).isPresent()) { throw new IllegalArgumentException("Instance columns are read-only."); } TaskAdapter taskAdapter = instanceAdapter.taskAdapter(); - // By definition, single instances don't have a recurrence set on their own, hence changes to the recurrence fields are not allowed. - if (new First<>(new Sieved<>(taskAdapter::isUpdated, RECURRENCE_FIELD_ADAPTERS)).isPresent()) - { + // By definition, single instances don't have a recurrence set on their own, + // hence changes to + // the recurrence fields are not allowed. + if (new First<>(new Sieved<>(taskAdapter::isUpdated, RECURRENCE_FIELD_ADAPTERS)).isPresent()) { throw new IllegalArgumentException("Recurrence values can not be modified through the instances table."); } } - - private void validateOriginalInstanceValues(InstanceAdapter instanceAdapter) - { + private void validateOriginalInstanceValues(InstanceAdapter instanceAdapter) { TaskAdapter taskAdapter = instanceAdapter.taskAdapter(); // Updates of ORIGINAL_INSTANCE_* fields are not allowed - if (new First<>(new Sieved<>(taskAdapter::isUpdated, ORIGINAL_INSTANCE_FIELD_ADAPTERS)).isPresent()) - { - throw new IllegalArgumentException("ORIGINAL_INSTANCE_* fields can not be updated through the instances table."); + if (new First<>(new Sieved<>(taskAdapter::isUpdated, ORIGINAL_INSTANCE_FIELD_ADAPTERS)).isPresent()) { + throw new IllegalArgumentException( + "ORIGINAL_INSTANCE_* fields can not be updated through the instances table."); } } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/lists/ListCommitProcessor.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/lists/ListCommitProcessor.java index 0e3336988a597a1b232b6afd1f1fb06e300baee9..a8048e0608016ff26943a9166a05f69cf48c2bd0 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/lists/ListCommitProcessor.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/lists/ListCommitProcessor.java @@ -17,40 +17,32 @@ package org.dmfs.provider.tasks.processors.lists; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.ListAdapter; import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.tasks.contract.TaskContract; - /** * A processor that performs the actual operations on task lists. * * @author Marten Gajda */ -public final class ListCommitProcessor implements EntityProcessor -{ +public final class ListCommitProcessor implements EntityProcessor { @Override - public ListAdapter insert(SQLiteDatabase db, ListAdapter list, boolean isSyncAdapter) - { + public ListAdapter insert(SQLiteDatabase db, ListAdapter list, boolean isSyncAdapter) { list.commit(db); return list; } - @Override - public ListAdapter update(SQLiteDatabase db, ListAdapter list, boolean isSyncAdapter) - { + public ListAdapter update(SQLiteDatabase db, ListAdapter list, boolean isSyncAdapter) { list.commit(db); return list; } - @Override - public void delete(SQLiteDatabase db, ListAdapter list, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, ListAdapter list, boolean isSyncAdapter) { db.delete(TaskDatabaseHelper.Tables.LISTS, TaskContract.TaskLists._ID + "=" + list.id(), null); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/lists/Validating.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/lists/Validating.java index 8b272153b9c00b322955b51ef8716920ac89ee9c..1363ca3a59bceef6eb2cab5f262ba91fbbd4b32e 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/lists/Validating.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/lists/Validating.java @@ -18,42 +18,32 @@ package org.dmfs.provider.tasks.processors.lists; import android.database.sqlite.SQLiteDatabase; import android.text.TextUtils; - import org.dmfs.provider.tasks.model.ListAdapter; import org.dmfs.provider.tasks.processors.EntityProcessor; - /** * A processor to validate the values of a task list. * * @author Marten Gajda */ -public final class Validating implements EntityProcessor -{ +public final class Validating implements EntityProcessor { private final EntityProcessor mDelegate; - - public Validating(EntityProcessor delegate) - { + public Validating(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public ListAdapter insert(SQLiteDatabase db, ListAdapter list, boolean isSyncAdapter) - { - if (!isSyncAdapter) - { + public ListAdapter insert(SQLiteDatabase db, ListAdapter list, boolean isSyncAdapter) { + if (!isSyncAdapter) { throw new UnsupportedOperationException("Caller must be a sync adapter to create task lists"); } - if (TextUtils.isEmpty(list.valueOf(ListAdapter.ACCOUNT_NAME))) - { + if (TextUtils.isEmpty(list.valueOf(ListAdapter.ACCOUNT_NAME))) { throw new IllegalArgumentException("ACCOUNT_NAME is required on INSERT"); } - if (TextUtils.isEmpty(list.valueOf(ListAdapter.ACCOUNT_TYPE))) - { + if (TextUtils.isEmpty(list.valueOf(ListAdapter.ACCOUNT_TYPE))) { throw new IllegalArgumentException("ACCOUNT_TYPE is required on INSERT"); } @@ -61,17 +51,13 @@ public final class Validating implements EntityProcessor return mDelegate.insert(db, list, isSyncAdapter); } - @Override - public ListAdapter update(SQLiteDatabase db, ListAdapter list, boolean isSyncAdapter) - { - if (list.isUpdated(ListAdapter.ACCOUNT_NAME)) - { + public ListAdapter update(SQLiteDatabase db, ListAdapter list, boolean isSyncAdapter) { + if (list.isUpdated(ListAdapter.ACCOUNT_NAME)) { throw new IllegalArgumentException("ACCOUNT_NAME is write-once"); } - if (list.isUpdated(ListAdapter.ACCOUNT_TYPE)) - { + if (list.isUpdated(ListAdapter.ACCOUNT_TYPE)) { throw new IllegalArgumentException("ACCOUNT_TYPE is write-once"); } @@ -79,58 +65,47 @@ public final class Validating implements EntityProcessor return mDelegate.update(db, list, isSyncAdapter); } - @Override - public void delete(SQLiteDatabase db, ListAdapter entityAdapter, boolean isSyncAdapter) - { - if (!isSyncAdapter) - { + public void delete(SQLiteDatabase db, ListAdapter entityAdapter, boolean isSyncAdapter) { + if (!isSyncAdapter) { throw new UnsupportedOperationException("Caller must be a sync adapter to delete task lists"); } mDelegate.delete(db, entityAdapter, isSyncAdapter); } - /** * Performs tests that are common to insert an update operations. * * @param list - * The {@link ListAdapter} to verify. + * The {@link ListAdapter} to verify. * @param isSyncAdapter - * true if the caller is a sync adapter, false otherwise. + * true if the caller is a sync adapter, false + * otherwise. */ - private void verifyCommon(ListAdapter list, boolean isSyncAdapter) - { + private void verifyCommon(ListAdapter list, boolean isSyncAdapter) { // row id can not be changed or set manually - if (list.isUpdated(ListAdapter._ID)) - { + if (list.isUpdated(ListAdapter._ID)) { throw new IllegalArgumentException("_ID can not be set manually"); } - if (isSyncAdapter) - { + if (isSyncAdapter) { // sync adapters may do all the stuff below return; } - if (list.isUpdated(ListAdapter.LIST_COLOR)) - { + if (list.isUpdated(ListAdapter.LIST_COLOR)) { throw new IllegalArgumentException("Only sync adapters can change the LIST_COLOR."); } - if (list.isUpdated(ListAdapter.LIST_NAME)) - { + if (list.isUpdated(ListAdapter.LIST_NAME)) { throw new IllegalArgumentException("Only sync adapters can change the LIST_NAME."); } - if (list.isUpdated(ListAdapter.SYNC_ID)) - { + if (list.isUpdated(ListAdapter.SYNC_ID)) { throw new IllegalArgumentException("Only sync adapters can change the _SYNC_ID."); } - if (list.isUpdated(ListAdapter.SYNC_VERSION)) - { + if (list.isUpdated(ListAdapter.SYNC_VERSION)) { throw new IllegalArgumentException("Only sync adapters can change SYNC_VERSION."); } - if (list.isUpdated(ListAdapter.OWNER)) - { + if (list.isUpdated(ListAdapter.OWNER)) { throw new IllegalArgumentException("Only sync adapters can change the list OWNER."); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/AutoCompleting.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/AutoCompleting.java index 65bbe9ade34cb49d5856cee05509156932c5c7e7..077a24bb9c93eb78922af4f93192b244efd2ae48 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/AutoCompleting.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/AutoCompleting.java @@ -19,190 +19,166 @@ package org.dmfs.provider.tasks.processors.tasks; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.TaskAdapter; import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; - /** * A processor to adjust some task values automatically. - *

- * Other then recurrence exceptions no relations are handled by this code. Relation specific changes go to {@link Relating}. + * + *

+ * Other then recurrence exceptions no relations are handled by this code. + * Relation specific changes go to {@link Relating}. * * @author Marten Gajda */ -public final class AutoCompleting implements EntityProcessor -{ +public final class AutoCompleting implements EntityProcessor { private final EntityProcessor mDelegate; - private static final String[] TASK_ID_PROJECTION = { TaskContract.Tasks._ID }; - private static final String[] TASK_SYNC_ID_PROJECTION = { TaskContract.Tasks._SYNC_ID }; + private static final String[] TASK_ID_PROJECTION = {TaskContract.Tasks._ID}; + private static final String[] TASK_SYNC_ID_PROJECTION = {TaskContract.Tasks._SYNC_ID}; private static final String SYNC_ID_SELECTION = TaskContract.Tasks._SYNC_ID + "=?"; private static final String TASK_ID_SELECTION = TaskContract.Tasks._ID + "=?"; - - public AutoCompleting(EntityProcessor delegate) - { + public AutoCompleting(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { updateFields(db, task, isSyncAdapter); - if (!isSyncAdapter) - { + if (!isSyncAdapter) { // set created date for tasks created on the device task.set(TaskAdapter.CREATED, DateTime.now()); } TaskAdapter result = mDelegate.insert(db, task, isSyncAdapter); - if (isSyncAdapter && result.isRecurring()) - { - // task is recurring, update ORIGINAL_INSTANCE_ID of all exceptions that may already exists + if (isSyncAdapter && result.isRecurring()) { + // task is recurring, update ORIGINAL_INSTANCE_ID of all exceptions that may + // already exists ContentValues values = new ContentValues(1); TaskAdapter.ORIGINAL_INSTANCE_ID.setIn(values, result.id()); - db.update(TaskDatabaseHelper.Tables.TASKS, values, TaskContract.Tasks.ORIGINAL_INSTANCE_SYNC_ID + "=? and " - + TaskContract.Tasks.ORIGINAL_INSTANCE_ID + " is null", new String[] { result.valueOf(TaskAdapter.SYNC_ID) }); + db.update( + TaskDatabaseHelper.Tables.TASKS, values, TaskContract.Tasks.ORIGINAL_INSTANCE_SYNC_ID + "=? and " + + TaskContract.Tasks.ORIGINAL_INSTANCE_ID + " is null", + new String[]{result.valueOf(TaskAdapter.SYNC_ID)}); } return result; } - @Override - public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { updateFields(db, task, isSyncAdapter); TaskAdapter result = mDelegate.update(db, task, isSyncAdapter); - if (isSyncAdapter && result.isRecurring() && result.isUpdated(TaskAdapter.SYNC_ID)) - { - // task is recurring, update ORIGINAL_INSTANCE_SYNC_ID of all exceptions that may already exists + if (isSyncAdapter && result.isRecurring() && result.isUpdated(TaskAdapter.SYNC_ID)) { + // task is recurring, update ORIGINAL_INSTANCE_SYNC_ID of all exceptions that + // may already + // exists ContentValues values = new ContentValues(1); TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID.setIn(values, result.valueOf(TaskAdapter.SYNC_ID)); - db.update(TaskDatabaseHelper.Tables.TASKS, values, TaskContract.Tasks.ORIGINAL_INSTANCE_ID + "=" + result.id(), null); + db.update(TaskDatabaseHelper.Tables.TASKS, values, + TaskContract.Tasks.ORIGINAL_INSTANCE_ID + "=" + result.id(), null); } return result; } - @Override - public void delete(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) { mDelegate.delete(db, entityAdapter, isSyncAdapter); } - - private void updateFields(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { - if (!isSyncAdapter) - { + private void updateFields(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { + if (!isSyncAdapter) { task.set(TaskAdapter._DIRTY, true); task.set(TaskAdapter.LAST_MODIFIED, DateTime.now()); // set proper STATUS if task has been completed - if (task.valueOf(TaskAdapter.COMPLETED) != null && !task.isUpdated(TaskAdapter.STATUS)) - { + if (task.valueOf(TaskAdapter.COMPLETED) != null && !task.isUpdated(TaskAdapter.STATUS)) { task.set(TaskAdapter.STATUS, TaskContract.Tasks.STATUS_COMPLETED); } } - if (task.isUpdated(TaskAdapter.PRIORITY)) - { + if (task.isUpdated(TaskAdapter.PRIORITY)) { Integer priority = task.valueOf(TaskAdapter.PRIORITY); - if (priority != null && priority == 0) - { - // replace priority 0 by null, it's the default and we need that for proper sorting + if (priority != null && priority == 0) { + // replace priority 0 by null, it's the default and we need that for proper + // sorting task.set(TaskAdapter.PRIORITY, null); } } // Find corresponding ORIGINAL_INSTANCE_ID - if (task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID)) - { - String[] syncId = { task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID) }; - try (Cursor cursor = db.query(TaskDatabaseHelper.Tables.TASKS, TASK_ID_PROJECTION, SYNC_ID_SELECTION, syncId, null, null, null)) - { - if (cursor.moveToNext()) - { + if (task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID)) { + String[] syncId = {task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID)}; + try (Cursor cursor = db.query(TaskDatabaseHelper.Tables.TASKS, TASK_ID_PROJECTION, SYNC_ID_SELECTION, + syncId, null, null, null)) { + if (cursor.moveToNext()) { Long originalId = cursor.getLong(0); task.set(TaskAdapter.ORIGINAL_INSTANCE_ID, originalId); } } - } - else if (task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_ID)) // Find corresponding ORIGINAL_INSTANCE_SYNC_ID + } else if (task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_ID)) // Find corresponding ORIGINAL_INSTANCE_SYNC_ID { - String[] id = { Long.toString(task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID)) }; - try (Cursor cursor = db.query(TaskDatabaseHelper.Tables.TASKS, TASK_SYNC_ID_PROJECTION, TASK_ID_SELECTION, id, null, null, null)) - { - if (cursor.moveToNext()) - { + String[] id = {Long.toString(task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID))}; + try (Cursor cursor = db.query(TaskDatabaseHelper.Tables.TASKS, TASK_SYNC_ID_PROJECTION, TASK_ID_SELECTION, + id, null, null, null)) { + if (cursor.moveToNext()) { String originalSyncId = cursor.getString(0); task.set(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID, originalSyncId); } } } - // check that PERCENT_COMPLETE is an Integer between 0 and 100 if supplied also update status and completed accordingly - if (task.isUpdated(TaskAdapter.PERCENT_COMPLETE)) - { + // check that PERCENT_COMPLETE is an Integer between 0 and 100 if supplied also + // update status + // and completed accordingly + if (task.isUpdated(TaskAdapter.PERCENT_COMPLETE)) { Integer percent = task.valueOf(TaskAdapter.PERCENT_COMPLETE); - if (!isSyncAdapter && percent != null && percent == 100) - { - if (!task.isUpdated(TaskAdapter.STATUS)) - { + if (!isSyncAdapter && percent != null && percent == 100) { + if (!task.isUpdated(TaskAdapter.STATUS)) { task.set(TaskAdapter.STATUS, TaskContract.Tasks.STATUS_COMPLETED); } - if (!task.isUpdated(TaskAdapter.COMPLETED)) - { + if (!task.isUpdated(TaskAdapter.COMPLETED)) { task.set(TaskAdapter.COMPLETED, new DateTime(System.currentTimeMillis())); } - } - else if (!isSyncAdapter && percent != null) - { - if (!task.isUpdated(TaskAdapter.COMPLETED)) - { + } else if (!isSyncAdapter && percent != null) { + if (!task.isUpdated(TaskAdapter.COMPLETED)) { task.set(TaskAdapter.COMPLETED, null); } } } // validate STATUS and set IS_NEW and IS_CLOSED accordingly - if (task.isUpdated(TaskAdapter.STATUS) || task.id() < 0 /* this is true when the task is new */) - { + if (task.isUpdated(TaskAdapter.STATUS) || task.id() < 0 /* this is true when the task is new */) { Integer status = task.valueOf(TaskAdapter.STATUS); - if (status == null) - { + if (status == null) { status = TaskContract.Tasks.STATUS_DEFAULT; task.set(TaskAdapter.STATUS, status); } task.set(TaskAdapter.IS_NEW, status == TaskContract.Tasks.STATUS_NEEDS_ACTION); - task.set(TaskAdapter.IS_CLOSED, status == TaskContract.Tasks.STATUS_COMPLETED || status == TaskContract.Tasks.STATUS_CANCELLED); + task.set(TaskAdapter.IS_CLOSED, + status == TaskContract.Tasks.STATUS_COMPLETED || status == TaskContract.Tasks.STATUS_CANCELLED); /* - * Update PERCENT_COMPLETE and COMPLETED (if not given). Sync adapters should know what they're doing, so don't update anything if caller is a sync + * Update PERCENT_COMPLETE and COMPLETED (if not given). Sync adapters should + * know what they're doing, so don't update anything if caller is a sync * adapter. */ - if (status == TaskContract.Tasks.STATUS_COMPLETED && !isSyncAdapter) - { + if (status == TaskContract.Tasks.STATUS_COMPLETED && !isSyncAdapter) { task.set(TaskAdapter.PERCENT_COMPLETE, 100); - if (!task.isUpdated(TaskAdapter.COMPLETED) || task.valueOf(TaskAdapter.COMPLETED) == null) - { + if (!task.isUpdated(TaskAdapter.COMPLETED) || task.valueOf(TaskAdapter.COMPLETED) == null) { task.set(TaskAdapter.COMPLETED, new DateTime(System.currentTimeMillis())); } - } - else if (!isSyncAdapter) - { + } else if (!isSyncAdapter) { task.set(TaskAdapter.COMPLETED, null); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Instantiating.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Instantiating.java index 1891ff381bc14e7265a5f1baa29f593cae860a8b..33d6dd67919b7c8abd5de3ee5c354cfd9f34b8ac 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Instantiating.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Instantiating.java @@ -16,10 +16,12 @@ package org.dmfs.provider.tasks.processors.tasks; +import static org.dmfs.provider.tasks.model.TaskAdapter.IS_CLOSED; + import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - +import java.util.Locale; import org.dmfs.jems.function.elementary.DiffMap; import org.dmfs.jems.iterable.composite.Diff; import org.dmfs.jems.iterable.decorators.Mapped; @@ -41,170 +43,142 @@ import org.dmfs.provider.tasks.utils.Range; import org.dmfs.provider.tasks.utils.RowIterator; import org.dmfs.tasks.contract.TaskContract; -import java.util.Locale; - -import static org.dmfs.provider.tasks.model.TaskAdapter.IS_CLOSED; - - /** * A processor that creates or updates the instance values of a task. * * @author Marten Gajda */ -public final class Instantiating implements EntityProcessor -{ - /** - * Projection we use to read the overrides of a task - */ - private final static String[] OVERRIDE_PROJECTION = { - TaskContract.Tasks._ID, - TaskContract.Tasks.DTSTART, - TaskContract.Tasks.DUE, - TaskContract.Tasks.DURATION, - TaskContract.Tasks.TZ, - TaskContract.Tasks.IS_ALLDAY, - TaskContract.Tasks.IS_CLOSED, - TaskContract.Tasks.ORIGINAL_INSTANCE_TIME, - TaskContract.Tasks.ORIGINAL_INSTANCE_ALLDAY }; +public final class Instantiating implements EntityProcessor { + /** Projection we use to read the overrides of a task */ + private static final String[] OVERRIDE_PROJECTION = {TaskContract.Tasks._ID, TaskContract.Tasks.DTSTART, + TaskContract.Tasks.DUE, TaskContract.Tasks.DURATION, TaskContract.Tasks.TZ, TaskContract.Tasks.IS_ALLDAY, + TaskContract.Tasks.IS_CLOSED, TaskContract.Tasks.ORIGINAL_INSTANCE_TIME, + TaskContract.Tasks.ORIGINAL_INSTANCE_ALLDAY}; /** - * This is a field adapter for a pseudo column to indicate that the instances may need an update, even if no relevant value has changed. This is useful to - * force an update of the sorting values when the local timezone has been changed. + * This is a field adapter for a pseudo column to indicate that the instances + * may need an update, even if no relevant value has changed. This is useful to + * force an update of the sorting values when the local timezone has been + * changed. + * *

* TODO: get rid of it */ - private final static BooleanFieldAdapter UPDATE_REQUESTED = new BooleanFieldAdapter( + private static final BooleanFieldAdapter UPDATE_REQUESTED = new BooleanFieldAdapter( "org.dmfs.tasks.TaskInstanceProcessor.UPDATE_REQUESTED"); // for now we only expand the next upcoming instance - private final static int UPCOMING_INSTANCE_COUNT_LIMIT = 1; - + private static final int UPCOMING_INSTANCE_COUNT_LIMIT = 1; /** - * Add a pseudo column to the given {@link ContentValues} to request an instances update, even if no time value has changed. + * Add a pseudo column to the given {@link ContentValues} to request an + * instances update, even if no time value has changed. * * @param values - * The {@link ContentValues} to add the pseudo column to. + * The {@link ContentValues} to add the pseudo column to. */ - public static void addUpdateRequest(ContentValues values) - { + public static void addUpdateRequest(ContentValues values) { UPDATE_REQUESTED.setIn(values, true); } - private final EntityProcessor mDelegate; - - public Instantiating(EntityProcessor delegate) - { + public Instantiating(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { TaskAdapter result = mDelegate.insert(db, task, isSyncAdapter); - if (task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null) - { + if (task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null) { // an override was created, insert a single task updateOverrideInstance(db, result, result.id()); - } - else - { - // update the recurring instances, there may already be overrides, so we use the update method + } else { + // update the recurring instances, there may already be overrides, so we use the + // update method updateMasterInstances(db, result, result.id()); } return result; } - @Override - public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { // TODO: get rid if this mechanism boolean updateRequested = task.isUpdated(UPDATE_REQUESTED) ? task.valueOf(UPDATE_REQUESTED) : false; task.unset(UPDATE_REQUESTED); TaskAdapter result = mDelegate.update(db, task, isSyncAdapter); - if (!result.isUpdated(TaskAdapter.DTSTART) && !result.isUpdated(TaskAdapter.DUE) && !result.isUpdated(TaskAdapter.DURATION) - && !result.isUpdated(TaskAdapter.STATUS) && !result.isUpdated(TaskAdapter.RDATE) && !result.isUpdated(TaskAdapter.RRULE) && !result.isUpdated( - TaskAdapter.EXDATE) && !result.isUpdated(IS_CLOSED) && !updateRequested) - { - // date values didn't change and update not requested -> no need to update the instances table + if (!result.isUpdated(TaskAdapter.DTSTART) && !result.isUpdated(TaskAdapter.DUE) + && !result.isUpdated(TaskAdapter.DURATION) && !result.isUpdated(TaskAdapter.STATUS) + && !result.isUpdated(TaskAdapter.RDATE) && !result.isUpdated(TaskAdapter.RRULE) + && !result.isUpdated(TaskAdapter.EXDATE) && !result.isUpdated(IS_CLOSED) && !updateRequested) { + // date values didn't change and update not requested -> no need to update the + // instances table return result; } - if (task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) == null) - { + if (task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) == null) { updateMasterInstances(db, result, result.id()); - } - else - { + } else { updateOverrideInstance(db, result, result.id()); } return result; } - @Override - public void delete(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) - { - // Note: there is a database trigger which cleans the instances table automatically when a task is deleted + public void delete(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) { + // Note: there is a database trigger which cleans the instances table + // automatically when a task + // is deleted mDelegate.delete(db, entityAdapter, isSyncAdapter); } - /** * Update the instance of an override. + * *

* TODO: take instance overrides into account * * @param db - * an {@link SQLiteDatabase}. + * an {@link SQLiteDatabase}. * @param taskAdapter - * the {@link TaskAdapter} of the task to insert. + * the {@link TaskAdapter} of the task to insert. * @param id - * the row id of the new task. + * the row id of the new task. */ - private void updateOverrideInstance(SQLiteDatabase db, TaskAdapter taskAdapter, long id) - { + private void updateOverrideInstance(SQLiteDatabase db, TaskAdapter taskAdapter, long id) { long origId = taskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID); int count = 0; - if (!taskAdapter.isUpdated(IS_CLOSED)) - { - // task status was not updated, we can take the shortcut and only update any existing instance values - for (Single values : new InstanceValuesIterable(id, taskAdapter)) - { - if (count++ > 1) - { - throw new RuntimeException("more than one instance returned for task instance which was supposed to have exactly one"); + if (!taskAdapter.isUpdated(IS_CLOSED)) { + // task status was not updated, we can take the shortcut and only update any + // existing instance + // values + for (Single values : new InstanceValuesIterable(id, taskAdapter)) { + if (count++ > 1) { + throw new RuntimeException( + "more than one instance returned for task instance which was supposed to have exactly one"); } ContentValues contentValues = values.value(); - // we don't know the current distance, but it for sure hasn't changed either, so just make sure we don't change it + // we don't know the current distance, but it for sure hasn't changed either, so + // just make + // sure we don't change it contentValues.remove(TaskContract.Instances.DISTANCE_FROM_CURRENT); // TASK_ID hasn't changed either contentValues.remove(TaskContract.Instances.TASK_ID); - db.update(TaskDatabaseHelper.Tables.INSTANCES, - contentValues, - String.format(Locale.ENGLISH, "%s = %d", TaskContract.Instances.TASK_ID, id), - null); + db.update(TaskDatabaseHelper.Tables.INSTANCES, contentValues, + String.format(Locale.ENGLISH, "%s = %d", TaskContract.Instances.TASK_ID, id), null); } - if (count == 0) - { + if (count == 0) { throw new RuntimeException("no instance returned for task which was supposed to have exactly one"); } - } - else - { + } else { // task status was updated, this might affect other instances, update them all // ensure the distance from current is set properly for all sibling instances try (Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, null, - String.format(Locale.ENGLISH, "(%s = %d)", TaskContract.Tasks._ID, origId), null, null, null, null)) - { - if (c.moveToFirst()) - { + String.format(Locale.ENGLISH, "(%s = %d)", TaskContract.Tasks._ID, origId), null, null, null, + null)) { + if (c.moveToFirst()) { TaskAdapter ta = new CursorContentValuesTaskAdapter(c, new ContentValues()); updateMasterInstances(db, ta, ta.id()); } @@ -212,51 +186,39 @@ public final class Instantiating implements EntityProcessor } } - /** * Updates the instances of an existing task * * @param db - * An {@link SQLiteDatabase}. + * An {@link SQLiteDatabase}. * @param taskAdapter - * the {@link TaskAdapter} of the task to update + * the {@link TaskAdapter} of the task to update * @param id - * the row id of the new task + * the row id of the new task */ - private void updateMasterInstances(SQLiteDatabase db, TaskAdapter taskAdapter, long id) - { - try (Cursor existingInstances = db.query( - TaskDatabaseHelper.Tables.INSTANCE_VIEW, - new String[] { - TaskContract.Instances._ID, - TaskContract.InstanceColumns.INSTANCE_ORIGINAL_TIME, + private void updateMasterInstances(SQLiteDatabase db, TaskAdapter taskAdapter, long id) { + try (Cursor existingInstances = db.query(TaskDatabaseHelper.Tables.INSTANCE_VIEW, + new String[]{TaskContract.Instances._ID, TaskContract.InstanceColumns.INSTANCE_ORIGINAL_TIME, TaskContract.InstanceColumns.INSTANCE_START, - TaskContract.InstanceColumns.INSTANCE_START_SORTING, - TaskContract.InstanceColumns.INSTANCE_DUE, + TaskContract.InstanceColumns.INSTANCE_START_SORTING, TaskContract.InstanceColumns.INSTANCE_DUE, TaskContract.InstanceColumns.INSTANCE_DUE_SORTING, - TaskContract.InstanceColumns.INSTANCE_DURATION, - TaskContract.InstanceColumns.TASK_ID, - TaskContract.InstanceColumns.DISTANCE_FROM_CURRENT, - TaskContract.Instances.IS_CLOSED }, - String.format(Locale.ENGLISH, "%s = ? or %s = ?", TaskContract.Instances.TASK_ID, TaskContract.Instances.ORIGINAL_INSTANCE_ID), - new String[] { Long.toString(id), Long.toString(id) }, - null, - null, + TaskContract.InstanceColumns.INSTANCE_DURATION, TaskContract.InstanceColumns.TASK_ID, + TaskContract.InstanceColumns.DISTANCE_FROM_CURRENT, TaskContract.Instances.IS_CLOSED}, + String.format(Locale.ENGLISH, "%s = ? or %s = ?", TaskContract.Instances.TASK_ID, + TaskContract.Instances.ORIGINAL_INSTANCE_ID), + new String[]{Long.toString(id), Long.toString(id)}, null, null, TaskContract.Instances.INSTANCE_ORIGINAL_TIME); - Cursor overrides = db.query( - TaskDatabaseHelper.Tables.TASKS, - OVERRIDE_PROJECTION, - String.format("%s = ? AND %s != 1", TaskContract.Tasks.ORIGINAL_INSTANCE_ID, TaskContract.Tasks._DELETED), - new String[] { Long.toString(id) }, - null, - null, - TaskContract.Tasks.ORIGINAL_INSTANCE_TIME);) - { + Cursor overrides = db.query(TaskDatabaseHelper.Tables.TASKS, OVERRIDE_PROJECTION, + String.format("%s = ? AND %s != 1", TaskContract.Tasks.ORIGINAL_INSTANCE_ID, + TaskContract.Tasks._DELETED), + new String[]{Long.toString(id)}, null, null, TaskContract.Tasks.ORIGINAL_INSTANCE_TIME);) { /* - * The goal of the code below is to update existing instances in place (as opposed to delete and recreate all instances). We do this for two reasons: - * 1) efficiency, in most cases existing instances don't change, deleting and recreating them would be overly expensive - * 2) stable row ids, deleting and recreating instances would change their id and void any existing URIs to them + * The goal of the code below is to update existing instances in place (as + * opposed to delete and recreate all instances). We do this for two reasons: 1) + * efficiency, in most cases existing instances don't change, deleting and + * recreating them would be overly expensive 2) stable row ids, deleting and + * recreating instances would change their id and void any existing URIs to them */ final int idIdx = existingInstances.getColumnIndex(TaskContract.Instances._ID); final int startIdx = existingInstances.getColumnIndex(TaskContract.Instances.INSTANCE_ORIGINAL_TIME); @@ -265,61 +227,57 @@ public final class Instantiating implements EntityProcessor final int distanceIdx = existingInstances.getColumnIndex(TaskContract.Instances.DISTANCE_FROM_CURRENT); // get an Iterator of all expected instances - // for very long or even infinite series we need to stop iterating at some point. - - Iterable, Optional>> diff = new Diff<>( - new Mapped<>(Single::value, new Limited<>(10000 /* hard limit for infinite rules*/, - new Mapped<>( - new DiffMap<>( - (original, override) -> override, // we have both, a regular instance and an override -> take the override - original -> original, - override -> override // we only have an override :-o, not really valid but tolerated - ), - new Diff<>( - new InstanceValuesIterable(id, taskAdapter), - new Mapped<>( - cursor -> - new OverrideValuesFunction() - .value(new CursorContentValuesTaskAdapter(cursor, new ContentValues())), - () -> new RowIterator(overrides)), - (left, right) -> { - Long leftLong = left.value().getAsLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME); - Long rightLong = right.value().getAsLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME); - // null is always smaller - if (leftLong == null) - { - return rightLong == null ? 0 : -1; - } - if (rightLong == null) - { - return 1; - } - - long ldiff = leftLong - rightLong; - return ldiff < 0 ? -1 : (ldiff > 0 ? 1 : 0); - })))), - new Range(existingInstances.getCount()), - (newInstanceValues, cursorRow) -> - { + // for very long or even infinite series we need to stop iterating at some + // point. + + Iterable, Optional>> diff = new Diff<>(new Mapped<>(Single::value, + new Limited<>(10000 /* hard limit for infinite rules */, + new Mapped<>(new DiffMap<>((original, override) -> override, // we have both, a regular + // instance and an override + // -> + // take the override + original -> original, override -> override // we only have an override :-o, not + // really valid but + // tolerated + ), new Diff<>(new InstanceValuesIterable(id, taskAdapter), + new Mapped<>( + cursor -> new OverrideValuesFunction().value( + new CursorContentValuesTaskAdapter(cursor, new ContentValues())), + () -> new RowIterator(overrides)), + (left, right) -> { + Long leftLong = left.value() + .getAsLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME); + Long rightLong = right.value() + .getAsLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME); + // null is always smaller + if (leftLong == null) { + return rightLong == null ? 0 : -1; + } + if (rightLong == null) { + return 1; + } + + long ldiff = leftLong - rightLong; + return ldiff < 0 ? -1 : (ldiff > 0 ? 1 : 0); + })))), + new Range(existingInstances.getCount()), (newInstanceValues, cursorRow) -> { existingInstances.moveToPosition(cursorRow); - long ldiff = new Backed<>(new NullSafe<>(newInstanceValues.getAsLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME)), 0L).value() + long ldiff = new Backed<>(new NullSafe<>( + newInstanceValues.getAsLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME)), 0L).value() - existingInstances.getLong(startIdx); return ldiff < 0 ? -1 : (ldiff > 0 ? 1 : 0); }); int distance = -1; // sync the instances table with the new instances - for (Pair, Optional> next : diff) - { - if (distance >= UPCOMING_INSTANCE_COUNT_LIMIT - 1) - { + for (Pair, Optional> next : diff) { + if (distance >= UPCOMING_INSTANCE_COUNT_LIMIT - 1) { // we already expanded enough instances - if (!next.right().isPresent()) - { + if (!next.right().isPresent()) { // if no further instances exist, stop here Long original = next.left().value().getAsLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME); - if (original != null && existingInstances.moveToLast() && existingInstances.getLong(startIdx) < original) - { + if (original != null && existingInstances.moveToLast() + && existingInstances.getLong(startIdx) < original) { break; } @@ -329,66 +287,51 @@ public final class Instantiating implements EntityProcessor next = new RightSidedPair<>(next.right()); } - if (!next.left().isPresent()) - { + if (!next.left().isPresent()) { // there is no new instance for this old one, remove it existingInstances.moveToPosition(next.right().value()); - db.delete(TaskDatabaseHelper.Tables.INSTANCES, - String.format(Locale.ENGLISH, "%s = %d", TaskContract.Instances._ID, existingInstances.getLong(idIdx)), null); - } - else if (!next.right().isPresent()) - { + db.delete(TaskDatabaseHelper.Tables.INSTANCES, String.format(Locale.ENGLISH, "%s = %d", + TaskContract.Instances._ID, existingInstances.getLong(idIdx)), null); + } else if (!next.right().isPresent()) { // there is no old instance for this new one, add it ContentValues values = next.left().value(); - if (distance >= 0 || values.getAsLong(TaskContract.Instances.DISTANCE_FROM_CURRENT) >= 0) - { + if (distance >= 0 || values.getAsLong(TaskContract.Instances.DISTANCE_FROM_CURRENT) >= 0) { distance += 1; } values.put(TaskContract.Instances.DISTANCE_FROM_CURRENT, distance); db.insert(TaskDatabaseHelper.Tables.INSTANCES, "", values); - } - else // both sides are present + } else // both sides are present { // update this instance existingInstances.moveToPosition(next.right().value()); ContentValues values = next.left().value(); - if (distance >= 0 || values.getAsLong(TaskContract.Instances.DISTANCE_FROM_CURRENT) >= 0) - { + if (distance >= 0 || values.getAsLong(TaskContract.Instances.DISTANCE_FROM_CURRENT) >= 0) { // the distance needs to be updated distance += 1; values.put(TaskContract.Instances.DISTANCE_FROM_CURRENT, distance); } ContentValues updates = updatedOnly(values, existingInstances); - if (updates.size() > 0) - { - db.update(TaskDatabaseHelper.Tables.INSTANCES, - updates, - String.format(Locale.ENGLISH, "%s = %d", TaskContract.Instances._ID, existingInstances.getLong(idIdx)), - null); + if (updates.size() > 0) { + db.update(TaskDatabaseHelper.Tables.INSTANCES, updates, String.format(Locale.ENGLISH, "%s = %d", + TaskContract.Instances._ID, existingInstances.getLong(idIdx)), null); } } } } } - - private static ContentValues updatedOnly(ContentValues newValues, Cursor oldValues) - { + private static ContentValues updatedOnly(ContentValues newValues, Cursor oldValues) { ContentValues result = new ContentValues(newValues); - for (String key : newValues.keySet()) - { + for (String key : newValues.keySet()) { int columnIdx = oldValues.getColumnIndex(key); - if (columnIdx < 0) - { + if (columnIdx < 0) { throw new RuntimeException("Missing column " + key + " in Cursor "); } - if (oldValues.isNull(columnIdx) && newValues.get(key) == null) - { + if (oldValues.isNull(columnIdx) && newValues.get(key) == null) { result.remove(key); - } - else if (!oldValues.isNull(columnIdx) && newValues.get(key) != null && oldValues.getLong(columnIdx) == newValues.getAsLong(key)) - { + } else if (!oldValues.isNull(columnIdx) && newValues.get(key) != null + && oldValues.getLong(columnIdx) == newValues.getAsLong(key)) { result.remove(key); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Moving.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Moving.java index ea9d9cb1d8b755848d8a86a29876924a8af49cd7..84345959adf2980764db62ad04e62513ef3e740b 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Moving.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Moving.java @@ -19,52 +19,44 @@ package org.dmfs.provider.tasks.processors.tasks; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.CursorContentValuesTaskAdapter; import org.dmfs.provider.tasks.model.TaskAdapter; import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.tasks.contract.TaskContract; - /** - * This processor makes sure that changing the list a task belongs is properly handled by sync adapters. This is achieved by emulating an atomic copy & delete - * operation. - *

- * TODO: at present we only move recurrence exceptions based on the original row id. We should consider to move exceptions based on the original SYNC_ID as well - * to support moving exception sets of tasks without known master instance. + * This processor makes sure that changing the list a task belongs is properly + * handled by sync adapters. This is achieved by emulating an atomic copy & + * delete operation. + * + *

+ * TODO: at present we only move recurrence exceptions based on the original row + * id. We should consider to move exceptions based on the original SYNC_ID as + * well to support moving exception sets of tasks without known master instance. * * @author Marten Gajda */ -public final class Moving implements EntityProcessor -{ +public final class Moving implements EntityProcessor { private final EntityProcessor mDelegate; - - public Moving(EntityProcessor delegate) - { + public Moving(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { return mDelegate.insert(db, task, isSyncAdapter); } - @Override - public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { - if (isSyncAdapter) - { + public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { + if (isSyncAdapter) { // sync-adapters have to implement the move logic themselves return mDelegate.update(db, task, isSyncAdapter); } - if (!task.isUpdated(TaskAdapter.LIST_ID)) - { + if (!task.isUpdated(TaskAdapter.LIST_ID)) { // list has not been changed return mDelegate.update(db, task, isSyncAdapter); } @@ -72,8 +64,7 @@ public final class Moving implements EntityProcessor long oldList = task.oldValueOf(TaskAdapter.LIST_ID); long newList = task.valueOf(TaskAdapter.LIST_ID); - if (oldList == newList) - { + if (oldList == newList) { // list has not been changed return mDelegate.update(db, task, isSyncAdapter); } @@ -81,53 +72,47 @@ public final class Moving implements EntityProcessor Long newMasterId; Long deletedMasterId = null; - if (task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null || task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID) != null) - { + if (task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null + || task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID) != null) { // this is an exception, move the master first newMasterId = task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID); - if (newMasterId != null) - { + if (newMasterId != null) { // find the master task - Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, null, TaskContract.Tasks._ID + "=" + newMasterId, null, null, null, null); - try - { - if (c.moveToFirst()) - { + Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, null, TaskContract.Tasks._ID + "=" + newMasterId, + null, null, null, null); + try { + if (c.moveToFirst()) { // move the master task - deletedMasterId = moveTask(db, new CursorContentValuesTaskAdapter(c, new ContentValues(16)), oldList, newList, null, true); + deletedMasterId = moveTask(db, new CursorContentValuesTaskAdapter(c, new ContentValues(16)), + oldList, newList, null, true); } - } - finally - { + } finally { c.close(); } } - // now move this exception, make sure we link the deleted exception to the deleted master + // now move this exception, make sure we link the deleted exception to the + // deleted master moveTask(db, task, oldList, newList, deletedMasterId, false); - } - else - { + } else { newMasterId = task.id(); // move the task to the new list deletedMasterId = moveTask(db, task, oldList, newList, null, false); } - if (task.isRecurring() || task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null) - { - // This task is recurring and may have exceptions or it's an exception itself. Move all (other) exceptions to the new list. - Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, null, TaskContract.Tasks.ORIGINAL_INSTANCE_ID + "=" + newMasterId + " and " - + TaskContract.Tasks._ID + "!=" + task.id(), null, null, null, null); - try - { - while (c.moveToNext()) - { - moveTask(db, new CursorContentValuesTaskAdapter(c, new ContentValues(16)), oldList, newList, deletedMasterId, true); + if (task.isRecurring() || task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_ID) != null) { + // This task is recurring and may have exceptions or it's an exception itself. + // Move all + // (other) exceptions to the new list. + Cursor c = db.query(TaskDatabaseHelper.Tables.TASKS, null, TaskContract.Tasks.ORIGINAL_INSTANCE_ID + "=" + + newMasterId + " and " + TaskContract.Tasks._ID + "!=" + task.id(), null, null, null, null); + try { + while (c.moveToNext()) { + moveTask(db, new CursorContentValuesTaskAdapter(c, new ContentValues(16)), oldList, newList, + deletedMasterId, true); } - } - finally - { + } finally { c.close(); } } @@ -135,31 +120,33 @@ public final class Moving implements EntityProcessor return mDelegate.update(db, task, isSyncAdapter); } - @Override - public void delete(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { mDelegate.delete(db, task, isSyncAdapter); } - - private Long moveTask(SQLiteDatabase db, TaskAdapter task, long oldList, long newList, Long deletedOriginalId, boolean commitTask) - { + private Long moveTask(SQLiteDatabase db, TaskAdapter task, long oldList, long newList, Long deletedOriginalId, + boolean commitTask) { /* - * The task has been moved to a different list. Sync adapters are not expected to support this (especially since the new list may belong to a completely - * different account or even account-type), so we emulate a copy & delete operation. + * The task has been moved to a different list. Sync adapters are not expected + * to support this (especially since the new list may belong to a completely + * different account or even account-type), so we emulate a copy & delete + * operation. * - * All sync adapter fields of the task are cleared, so it looks like a new task. In addition we create a new deleted task in the old list having the old - * sync adapter field values. This means that the _ID field of the "deleted" task will not equal the _ID field f the original task. Sync adapters should - * handle that correctly. + * All sync adapter fields of the task are cleared, so it looks like a new task. + * In addition we create a new deleted task in the old list having the old sync + * adapter field values. This means that the _ID field of the "deleted" task + * will not equal the _ID field f the original task. Sync adapters should handle + * that correctly. */ Long result = null; - // create a deleted task for the old one, unless the task has not been synced yet (which is always true for tasks in the local account) + // create a deleted task for the old one, unless the task has not been synced + // yet (which is + // always true for tasks in the local account) if (task.valueOf(TaskAdapter.SYNC_ID) != null || task.valueOf(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID) != null - || task.valueOf(TaskAdapter.SYNC_VERSION) != null) - { + || task.valueOf(TaskAdapter.SYNC_VERSION) != null) { TaskAdapter deletedTask = task.duplicate(); deletedTask.set(TaskAdapter.LIST_ID, oldList); deletedTask.set(TaskAdapter.ORIGINAL_INSTANCE_ID, deletedOriginalId); @@ -194,12 +181,10 @@ public final class Moving implements EntityProcessor task.set(TaskAdapter.SYNC_ID, null); task.set(TaskAdapter.SYNC_VERSION, null); task.set(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID, null); - if (commitTask) - { + if (commitTask) { task.commit(db); } return result; } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Originating.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Originating.java index 15e82b40c9922cd270ad9007247f024a1cb84a2e..ca00b880464e4a9d5a7f268ba4edc925970b4615 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Originating.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Originating.java @@ -18,60 +18,50 @@ package org.dmfs.provider.tasks.processors.tasks; import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; - +import java.util.Locale; import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.TaskAdapter; import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.tasks.contract.TaskContract; -import java.util.Locale; - - /** - * An {@link EntityProcessor} which updates the {@link TaskContract.Tasks#ORIGINAL_INSTANCE_ID} of any overrides when a master is inserted which has the - * matching {@link TaskContract.Tasks#ORIGINAL_INSTANCE_SYNC_ID}. + * An {@link EntityProcessor} which updates the + * {@link TaskContract.Tasks#ORIGINAL_INSTANCE_ID} of any overrides when a + * master is inserted which has the matching + * {@link TaskContract.Tasks#ORIGINAL_INSTANCE_SYNC_ID}. * * @author Marten Gajda */ -public final class Originating implements EntityProcessor -{ +public final class Originating implements EntityProcessor { private final EntityProcessor mDelegate; - - public Originating(EntityProcessor delegate) - { + public Originating(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { TaskAdapter result = mDelegate.insert(db, task, isSyncAdapter); String syncId = result.valueOf(TaskAdapter.SYNC_ID); - if (syncId != null) - { + if (syncId != null) { // A master task with a syncId has been inserted. // Update original ID of any existing overrides. ContentValues values = new ContentValues(1); values.put(TaskContract.Tasks.ORIGINAL_INSTANCE_ID, result.id()); - db.update(TaskDatabaseHelper.Tables.TASKS, values, String.format(Locale.ENGLISH, "%s = ?", TaskContract.Tasks.ORIGINAL_INSTANCE_SYNC_ID), - new String[] { syncId }); + db.update(TaskDatabaseHelper.Tables.TASKS, values, + String.format(Locale.ENGLISH, "%s = ?", TaskContract.Tasks.ORIGINAL_INSTANCE_SYNC_ID), + new String[]{syncId}); } return result; } - @Override - public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { return mDelegate.update(db, task, isSyncAdapter); } - @Override - public void delete(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { mDelegate.delete(db, task, isSyncAdapter); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Relating.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Relating.java index d64177950b53b9703d06e60abf38b45970c0627d..891e25ce8e4fc65ec3c735b97473f9ce1a1d01f8 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Relating.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Relating.java @@ -19,81 +19,76 @@ package org.dmfs.provider.tasks.processors.tasks; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.TaskAdapter; import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.tasks.contract.TaskContract; - /** * A processor that updates relations for new tasks. + * *

- * In general there is no guarantee that a related task is already in the database when a task is - * inserted. In such a case we can not set the {@link TaskContract.Property.Relation#RELATED_ID} value. This processor updates the {@link - * TaskContract.Property.Relation#RELATED_ID} when a task is inserted. + * In general there is no guarantee that a related task is already in the + * database when a task is inserted. In such a case we can not set the + * {@link TaskContract.Property.Relation#RELATED_ID} value. This processor + * updates the {@link TaskContract.Property.Relation#RELATED_ID} when a task is + * inserted. + * *

- * It also updates {@link TaskContract.Property.Relation#RELATED_UID} when a tasks - * is synced the first time and a UID has been set. + * It also updates {@link TaskContract.Property.Relation#RELATED_UID} when a + * tasks is synced the first time and a UID has been set. + * *

* * @author Marten Gajda */ -public final class Relating implements EntityProcessor -{ +public final class Relating implements EntityProcessor { private final EntityProcessor mDelegate; - - public Relating(EntityProcessor delegate) - { + public Relating(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { TaskAdapter result = mDelegate.insert(db, task, isSyncAdapter); - // A new task has been inserted by the sync adapter. Update all relations that point to this task. + // A new task has been inserted by the sync adapter. Update all relations that + // point to this + // task. - if (!isSyncAdapter) - { + if (!isSyncAdapter) { // the task was created on the device, so it doesn't have a UID return result; } String uid = result.valueOf(TaskAdapter._UID); - if (uid != null) - { + if (uid != null) { ContentValues v = new ContentValues(1); v.put(TaskContract.Property.Relation.RELATED_ID, result.id()); - int updates = db.update(TaskDatabaseHelper.Tables.PROPERTIES, v, - TaskContract.Property.Relation.MIMETYPE + "= ? AND " + TaskContract.Property.Relation.RELATED_UID + "=?", new String[] { - TaskContract.Property.Relation.CONTENT_ITEM_TYPE, uid }); + int updates = db.update( + TaskDatabaseHelper.Tables.PROPERTIES, v, TaskContract.Property.Relation.MIMETYPE + "= ? AND " + + TaskContract.Property.Relation.RELATED_UID + "=?", + new String[]{TaskContract.Property.Relation.CONTENT_ITEM_TYPE, uid}); - if (updates > 0) - { - // there were other relations pointing towards this task, update PARENT_IDs if necessary + if (updates > 0) { + // there were other relations pointing towards this task, update PARENT_IDs if + // necessary ContentValues parentIdValues = new ContentValues(1); parentIdValues.put(TaskContract.Tasks.PARENT_ID, result.id()); - // iterate over all tasks which refer to this as their parent and update their PARENT_ID - try (Cursor c = db.query( - TaskDatabaseHelper.Tables.PROPERTIES, new String[] { TaskContract.Property.Relation.TASK_ID }, - String.format("%s = ? and %s = ? and %s = ?", - TaskContract.Property.Relation.MIMETYPE, - TaskContract.Property.Relation.RELATED_ID, - TaskContract.Property.Relation.RELATED_TYPE), - new String[] { - TaskContract.Property.Relation.CONTENT_ITEM_TYPE, - String.valueOf(result.id()), - String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT) }, - null, null, null)) - { - while (c.moveToNext()) - { - db.update(TaskDatabaseHelper.Tables.TASKS, parentIdValues, TaskContract.Tasks._ID + " = ?", new String[] { c.getString(0) }); + // iterate over all tasks which refer to this as their parent and update their + // PARENT_ID + try (Cursor c = db.query(TaskDatabaseHelper.Tables.PROPERTIES, + new String[]{TaskContract.Property.Relation.TASK_ID}, + String.format("%s = ? and %s = ? and %s = ?", TaskContract.Property.Relation.MIMETYPE, + TaskContract.Property.Relation.RELATED_ID, TaskContract.Property.Relation.RELATED_TYPE), + new String[]{TaskContract.Property.Relation.CONTENT_ITEM_TYPE, String.valueOf(result.id()), + String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT)}, + null, null, null)) { + while (c.moveToNext()) { + db.update(TaskDatabaseHelper.Tables.TASKS, parentIdValues, TaskContract.Tasks._ID + " = ?", + new String[]{c.getString(0)}); } } // TODO, way also may have to do this for all the siblings of these tasks. @@ -102,49 +97,45 @@ public final class Relating implements EntityProcessor return result; } - @Override - public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { TaskAdapter result = mDelegate.update(db, task, isSyncAdapter); - // A task has been updated and may have received a UID by the sync adapter. Update all by-id references to this task. - // in this case we don't need to update any PARENT_ID because it should already be set. + // A task has been updated and may have received a UID by the sync adapter. + // Update all by-id + // references to this task. + // in this case we don't need to update any PARENT_ID because it should already + // be set. - if (!isSyncAdapter) - { + if (!isSyncAdapter) { // only sync adapters may assign a UID return result; } String uid = result.valueOf(TaskAdapter._UID); - if (uid != null) - { + if (uid != null) { ContentValues v = new ContentValues(1); v.put(TaskContract.Property.Relation.RELATED_UID, uid); db.update(TaskDatabaseHelper.Tables.PROPERTIES, v, - TaskContract.Property.Relation.MIMETYPE + "= ? AND " + TaskContract.Property.Relation.RELATED_ID + "=?", new String[] { - TaskContract.Property.Relation.CONTENT_ITEM_TYPE, Long.toString(result.id()) }); + TaskContract.Property.Relation.MIMETYPE + "= ? AND " + TaskContract.Property.Relation.RELATED_ID + + "=?", + new String[]{TaskContract.Property.Relation.CONTENT_ITEM_TYPE, Long.toString(result.id())}); } return result; } - @Override - public void delete(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { mDelegate.delete(db, task, isSyncAdapter); - if (!isSyncAdapter) - { + if (!isSyncAdapter) { // remove once the deletion is final, which is when the sync adapter removes it return; } - db.delete(TaskDatabaseHelper.Tables.PROPERTIES, TaskContract.Property.Relation.MIMETYPE + "= ? AND " + TaskContract.Property.Relation.RELATED_ID + "=?", - new String[] { - TaskContract.Property.Relation.CONTENT_ITEM_TYPE, - Long.toString(task.id()) }); + db.delete(TaskDatabaseHelper.Tables.PROPERTIES, + TaskContract.Property.Relation.MIMETYPE + "= ? AND " + TaskContract.Property.Relation.RELATED_ID + "=?", + new String[]{TaskContract.Property.Relation.CONTENT_ITEM_TYPE, Long.toString(task.id())}); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Reparenting.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Reparenting.java index a08f9b7ab44cc7df67f8b47c727375d69540d928..a5fb68d293370955490c5ba32d71dfa84e1df96d 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Reparenting.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Reparenting.java @@ -18,94 +18,71 @@ package org.dmfs.provider.tasks.processors.tasks; import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.TaskAdapter; import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.tasks.contract.TaskContract; - /** - * An {@link EntityProcessor} which updates a task's parent-child relations when its {@link TaskContract.Tasks#PARENT_ID} is updated. + * An {@link EntityProcessor} which updates a task's parent-child relations when + * its {@link TaskContract.Tasks#PARENT_ID} is updated. * * @author Marten Gajda */ -public final class Reparenting implements EntityProcessor -{ +public final class Reparenting implements EntityProcessor { private final EntityProcessor mDelegate; - - public Reparenting(EntityProcessor delegate) - { + public Reparenting(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public TaskAdapter insert(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) - { + public TaskAdapter insert(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) { TaskAdapter result = mDelegate.insert(db, entityAdapter, isSyncAdapter); - if (entityAdapter.isUpdated(TaskAdapter.PARENT_ID)) - { + if (entityAdapter.isUpdated(TaskAdapter.PARENT_ID)) { linkParent(db, result); } return result; } - @Override - public TaskAdapter update(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) - { - if (entityAdapter.isUpdated(TaskAdapter.PARENT_ID)) - { + public TaskAdapter update(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) { + if (entityAdapter.isUpdated(TaskAdapter.PARENT_ID)) { unlinkParent(db, entityAdapter); TaskAdapter result = mDelegate.update(db, entityAdapter, isSyncAdapter); linkParent(db, entityAdapter); return result; - } - else - { + } else { return mDelegate.update(db, entityAdapter, isSyncAdapter); } } - @Override - public void delete(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) { unlinkParent(db, entityAdapter); mDelegate.delete(db, entityAdapter, isSyncAdapter); } - - private void unlinkParent(SQLiteDatabase db, TaskAdapter taskAdapter) - { - if (taskAdapter.oldValueOf(TaskAdapter.PARENT_ID) != null) - { + private void unlinkParent(SQLiteDatabase db, TaskAdapter taskAdapter) { + if (taskAdapter.oldValueOf(TaskAdapter.PARENT_ID) != null) { // delete any parent, child or sibling relation with this task db.delete(TaskDatabaseHelper.Tables.PROPERTIES, String.format("%s = ? AND (%s = ? and %s in (?, ?) or %s = ? and %s in (?, ?))", - TaskContract.Property.Relation.MIMETYPE, - TaskContract.Property.Relation.TASK_ID, - TaskContract.Property.Relation.RELATED_TYPE, - TaskContract.Property.Relation.RELATED_ID, + TaskContract.Property.Relation.MIMETYPE, TaskContract.Property.Relation.TASK_ID, + TaskContract.Property.Relation.RELATED_TYPE, TaskContract.Property.Relation.RELATED_ID, TaskContract.Property.Relation.RELATED_TYPE), - new String[] { - TaskContract.Property.Relation.CONTENT_ITEM_TYPE, + new String[]{TaskContract.Property.Relation.CONTENT_ITEM_TYPE, String.valueOf(taskAdapter.valueOf(TaskAdapter._ID)), String.valueOf(TaskContract.Property.Relation.RELTYPE_SIBLING), String.valueOf(TaskContract.Property.Relation.RELTYPE_PARENT), String.valueOf(taskAdapter.valueOf(TaskAdapter._ID)), String.valueOf(TaskContract.Property.Relation.RELTYPE_SIBLING), - String.valueOf(TaskContract.Property.Relation.RELTYPE_CHILD) }); + String.valueOf(TaskContract.Property.Relation.RELTYPE_CHILD)}); } } - - private void linkParent(SQLiteDatabase db, TaskAdapter taskAdapter) - { - if (taskAdapter.valueOf(TaskAdapter.PARENT_ID) != null) - { + private void linkParent(SQLiteDatabase db, TaskAdapter taskAdapter) { + if (taskAdapter.valueOf(TaskAdapter.PARENT_ID) != null) { ContentValues values = new ContentValues(); values.put(TaskContract.Property.Relation.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE); values.put(TaskContract.Property.Relation.TASK_ID, taskAdapter.id()); @@ -115,5 +92,4 @@ public final class Reparenting implements EntityProcessor db.insert(TaskDatabaseHelper.Tables.PROPERTIES, "", values); } } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Searchable.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Searchable.java index 5b62b8e50ef66eb8faa837bea2c3966815fe6352..2575032de66d7d55c30ff99608a84a5d53461728 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Searchable.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Searchable.java @@ -17,50 +17,40 @@ package org.dmfs.provider.tasks.processors.tasks; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.FTSDatabaseHelper; import org.dmfs.provider.tasks.model.TaskAdapter; import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.provider.tasks.utils.Profiled; - /** - * An {@link EntityProcessor} to update the fast text search table when inserting or updating a task. + * An {@link EntityProcessor} to update the fast text search table when + * inserting or updating a task. * * @author Marten Gajda */ -public final class Searchable implements EntityProcessor -{ +public final class Searchable implements EntityProcessor { private final EntityProcessor mDelegate; - - public Searchable(EntityProcessor delegate) - { + public Searchable(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { TaskAdapter result = mDelegate.insert(db, task, isSyncAdapter); new Profiled("InsertFTS").run(() -> FTSDatabaseHelper.updateTaskFTSEntries(db, task)); return result; } - @Override - public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { TaskAdapter result = mDelegate.update(db, task, isSyncAdapter); new Profiled("UpdateFTS").run(() -> FTSDatabaseHelper.updateTaskFTSEntries(db, task)); return result; } - @Override - public void delete(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) { new Profiled("DeleteFTS").run(() -> mDelegate.delete(db, entityAdapter, isSyncAdapter)); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/TaskCommitProcessor.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/TaskCommitProcessor.java index 677dd61db52e0c44e3c24f10a0c3aa9de1025d81..43f2d319582ef9da6a71c005ca24f3d1515bd2dd 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/TaskCommitProcessor.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/TaskCommitProcessor.java @@ -17,48 +17,39 @@ package org.dmfs.provider.tasks.processors.tasks; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.TaskAdapter; import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.tasks.contract.TaskContract; - /** * A processor that performs the actual operations on tasks. * * @author Marten Gajda */ -public final class TaskCommitProcessor implements EntityProcessor -{ +public final class TaskCommitProcessor implements EntityProcessor { @Override - public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { task.commit(db); return task; } - @Override - public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { task.commit(db); return task; } - @Override - public void delete(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { String accountType = task.valueOf(TaskAdapter.ACCOUNT_TYPE); - if (isSyncAdapter || TaskContract.LOCAL_ACCOUNT_TYPE.equals(accountType)) - { - // this is a local task or it's removed by a sync adapter, in either case we delete it right away + if (isSyncAdapter || TaskContract.LOCAL_ACCOUNT_TYPE.equals(accountType)) { + // this is a local task or it's removed by a sync adapter, in either case we + // delete it right + // away db.delete(TaskDatabaseHelper.Tables.TASKS, TaskContract.TaskColumns._ID + "=" + task.id(), null); - } - else - { + } else { // just set the deleted flag otherwise task.set(TaskAdapter._DELETED, true); task.commit(db); diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Validating.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Validating.java index a28a97ea5a6d24184197b1d6f1d518e47b475595..fa0b81d7a2276bc0283d88e6b72998e916910038 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Validating.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/Validating.java @@ -18,222 +18,186 @@ package org.dmfs.provider.tasks.processors.tasks; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; - import org.dmfs.provider.tasks.TaskDatabaseHelper; import org.dmfs.provider.tasks.model.TaskAdapter; import org.dmfs.provider.tasks.processors.EntityProcessor; import org.dmfs.rfc5545.Duration; import org.dmfs.tasks.contract.TaskContract; - /** * A processor that validates the values of a task. * * @author Marten Gajda */ -public final class Validating implements EntityProcessor -{ - private static final String[] TASKLIST_ID_PROJECTION = { TaskContract.TaskLists._ID }; +public final class Validating implements EntityProcessor { + private static final String[] TASKLIST_ID_PROJECTION = {TaskContract.TaskLists._ID}; private static final String TASKLISTS_ID_SELECTION = TaskContract.TaskLists._ID + "="; private final EntityProcessor mDelegate; - - public Validating(EntityProcessor delegate) - { + public Validating(EntityProcessor delegate) { mDelegate = delegate; } - @Override - public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter insert(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { verifyCommon(task, isSyncAdapter); // LIST_ID must be present and refer to an existing TaskList row id Long listId = task.valueOf(TaskAdapter.LIST_ID); - if (listId == null) - { + if (listId == null) { throw new IllegalArgumentException("LIST_ID is required on INSERT"); } // TODO: get rid of this query and use a cache instead // TODO: ensure that the list is writable unless the caller is a sync adapter - Cursor cursor = db.query(TaskDatabaseHelper.Tables.LISTS, TASKLIST_ID_PROJECTION, TASKLISTS_ID_SELECTION + listId, null, null, null, null); - try - { - if (cursor == null || cursor.getCount() != 1) - { + Cursor cursor = db.query(TaskDatabaseHelper.Tables.LISTS, TASKLIST_ID_PROJECTION, + TASKLISTS_ID_SELECTION + listId, null, null, null, null); + try { + if (cursor == null || cursor.getCount() != 1) { throw new IllegalArgumentException("LIST_ID must refer to an existing TaskList"); } - } - finally - { - if (cursor != null) - { + } finally { + if (cursor != null) { cursor.close(); } } return mDelegate.insert(db, task, isSyncAdapter); } - @Override - public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) - { + public TaskAdapter update(SQLiteDatabase db, TaskAdapter task, boolean isSyncAdapter) { verifyCommon(task, isSyncAdapter); - // only sync adapters can modify original sync id and original instance id of an existing task - if (!isSyncAdapter && (task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_ID) || task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID))) - { - throw new IllegalArgumentException("ORIGINAL_INSTANCE_SYNC_ID and ORIGINAL_INSTANCE_ID can be modified by sync adapters only"); + // only sync adapters can modify original sync id and original instance id of an + // existing task + if (!isSyncAdapter && (task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_ID) + || task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID))) { + throw new IllegalArgumentException( + "ORIGINAL_INSTANCE_SYNC_ID and ORIGINAL_INSTANCE_ID can be modified by sync adapters only"); } // only sync adapters are allowed to change the UID of existing tasks - if (!isSyncAdapter && task.isUpdated(TaskAdapter._UID)) - { + if (!isSyncAdapter && task.isUpdated(TaskAdapter._UID)) { throw new IllegalArgumentException("modification of _UID is not allowed to non-sync adapters"); } return mDelegate.update(db, task, isSyncAdapter); } - @Override - public void delete(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) - { + public void delete(SQLiteDatabase db, TaskAdapter entityAdapter, boolean isSyncAdapter) { mDelegate.delete(db, entityAdapter, isSyncAdapter); } - /** * Performs tests that are common to insert an update operations. * * @param task - * The {@link TaskAdapter} to verify. + * The {@link TaskAdapter} to verify. * @param isSyncAdapter - * true if the caller is a sync adapter, false otherwise. + * true if the caller is a sync adapter, false + * otherwise. */ - private void verifyCommon(TaskAdapter task, boolean isSyncAdapter) - { + private void verifyCommon(TaskAdapter task, boolean isSyncAdapter) { // row id can not be changed or set manually - if (task.isUpdated(TaskAdapter._ID)) - { + if (task.isUpdated(TaskAdapter._ID)) { throw new IllegalArgumentException("_ID can not be set manually"); } - if (task.isUpdated(TaskAdapter.VERSION)) - { + if (task.isUpdated(TaskAdapter.VERSION)) { throw new IllegalArgumentException("VERSION can not be set manually"); } // account name can not be set on a tasks - if (task.isUpdated(TaskAdapter.ACCOUNT_NAME)) - { + if (task.isUpdated(TaskAdapter.ACCOUNT_NAME)) { throw new IllegalArgumentException("ACCOUNT_NAME can not be set on a tasks"); } // account type can not be set on a tasks - if (task.isUpdated(TaskAdapter.ACCOUNT_TYPE)) - { + if (task.isUpdated(TaskAdapter.ACCOUNT_TYPE)) { throw new IllegalArgumentException("ACCOUNT_TYPE can not be set on a tasks"); } // list color is read only for tasks - if (task.isUpdated(TaskAdapter.LIST_COLOR)) - { + if (task.isUpdated(TaskAdapter.LIST_COLOR)) { throw new IllegalArgumentException("LIST_COLOR can not be set on a tasks"); } // no one can undelete a task! - if (task.isUpdated(TaskAdapter._DELETED)) - { + if (task.isUpdated(TaskAdapter._DELETED)) { throw new IllegalArgumentException("modification of _DELETE is not allowed"); } // only sync adapters are allowed to remove the dirty flag - if (!isSyncAdapter && task.isUpdated(TaskAdapter._DIRTY)) - { + if (!isSyncAdapter && task.isUpdated(TaskAdapter._DIRTY)) { throw new IllegalArgumentException("modification of _DIRTY is not allowed"); } // only sync adapters are allowed to set creation time - if (!isSyncAdapter && task.isUpdated(TaskAdapter.CREATED)) - { + if (!isSyncAdapter && task.isUpdated(TaskAdapter.CREATED)) { throw new IllegalArgumentException("modification of CREATED is not allowed"); } // IS_NEW is set automatically - if (task.isUpdated(TaskAdapter.IS_NEW)) - { + if (task.isUpdated(TaskAdapter.IS_NEW)) { throw new IllegalArgumentException("modification of IS_NEW is not allowed"); } // IS_CLOSED is set automatically - if (task.isUpdated(TaskAdapter.IS_CLOSED)) - { + if (task.isUpdated(TaskAdapter.IS_CLOSED)) { throw new IllegalArgumentException("modification of IS_CLOSED is not allowed"); } // HAS_PROPERTIES is set automatically - if (task.isUpdated(TaskAdapter.HAS_PROPERTIES)) - { + if (task.isUpdated(TaskAdapter.HAS_PROPERTIES)) { throw new IllegalArgumentException("modification of HAS_PROPERTIES is not allowed"); } // HAS_ALARMS is set automatically - if (task.isUpdated(TaskAdapter.HAS_ALARMS)) - { + if (task.isUpdated(TaskAdapter.HAS_ALARMS)) { throw new IllegalArgumentException("modification of HAS_ALARMS is not allowed"); } // only sync adapters are allowed to set modification time - if (!isSyncAdapter && task.isUpdated(TaskAdapter.LAST_MODIFIED)) - { + if (!isSyncAdapter && task.isUpdated(TaskAdapter.LAST_MODIFIED)) { throw new IllegalArgumentException("modification of MODIFICATION_TIME is not allowed"); } - if (task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID) && task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_ID)) - { - throw new IllegalArgumentException("ORIGINAL_INSTANCE_SYNC_ID and ORIGINAL_INSTANCE_ID must not be specified at the same time"); + if (task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_SYNC_ID) && task.isUpdated(TaskAdapter.ORIGINAL_INSTANCE_ID)) { + throw new IllegalArgumentException( + "ORIGINAL_INSTANCE_SYNC_ID and ORIGINAL_INSTANCE_ID must not be specified at the same time"); } // check that CLASSIFICATION is an Integer between 0 and 2 if given - if (task.isUpdated(TaskAdapter.CLASSIFICATION)) - { + if (task.isUpdated(TaskAdapter.CLASSIFICATION)) { Integer classification = task.valueOf(TaskAdapter.CLASSIFICATION); - if (classification != null && (classification < 0 || classification > 2)) - { + if (classification != null && (classification < 0 || classification > 2)) { throw new IllegalArgumentException("CLASSIFICATION must be an integer between 0 and 2"); } } // check that PRIORITY is an Integer between 0 and 9 if given - if (task.isUpdated(TaskAdapter.PRIORITY)) - { + if (task.isUpdated(TaskAdapter.PRIORITY)) { Integer priority = task.valueOf(TaskAdapter.PRIORITY); - if (priority != null && (priority < 0 || priority > 9)) - { + if (priority != null && (priority < 0 || priority > 9)) { throw new IllegalArgumentException("PRIORITY must be an integer between 0 and 9"); } } // check that PERCENT_COMPLETE is an Integer between 0 and 100 - if (task.isUpdated(TaskAdapter.PERCENT_COMPLETE)) - { + if (task.isUpdated(TaskAdapter.PERCENT_COMPLETE)) { Integer percent = task.valueOf(TaskAdapter.PERCENT_COMPLETE); - if (percent != null && (percent < 0 || percent > 100)) - { + if (percent != null && (percent < 0 || percent > 100)) { throw new IllegalArgumentException("PERCENT_COMPLETE must be null or an integer between 0 and 100"); } } // validate STATUS - if (task.isUpdated(TaskAdapter.STATUS)) - { + if (task.isUpdated(TaskAdapter.STATUS)) { Integer status = task.valueOf(TaskAdapter.STATUS); - if (status != null && (status < TaskContract.Tasks.STATUS_NEEDS_ACTION || status > TaskContract.Tasks.STATUS_CANCELLED)) - { + if (status != null && (status < TaskContract.Tasks.STATUS_NEEDS_ACTION + || status > TaskContract.Tasks.STATUS_CANCELLED)) { throw new IllegalArgumentException("invalid STATUS: " + status); } } @@ -243,36 +207,28 @@ public final class Validating implements EntityProcessor Long due = task.valueOf(TaskAdapter.DUE_RAW); Duration duration = task.valueOf(TaskAdapter.DURATION); - if (dtStart != null) - { - if (due != null && duration != null) - { + if (dtStart != null) { + if (due != null && duration != null) { throw new IllegalArgumentException("Only one of DUE or DURATION must be supplied."); - } - else if (due != null) - { - if (due < dtStart) - { + } else if (due != null) { + if (due < dtStart) { throw new IllegalArgumentException("DUE must not be < DTSTART"); } - } - else if (duration != null) - { - if (duration.getSign() == -1) - { + } else if (duration != null) { + if (duration.getSign() == -1) { throw new IllegalArgumentException("DURATION must not be negative"); } } - } - else if (duration != null) - { + } else if (duration != null) { throw new IllegalArgumentException("DURATION must not be supplied without DTSTART"); } - // if one of DTSTART or DUE is given, TZ must not be null unless it's an all-day task - if ((dtStart != null || due != null) && !task.valueOf(TaskAdapter.IS_ALLDAY) && task.valueOf(TaskAdapter.TIMEZONE_RAW) == null) - { - throw new IllegalArgumentException("TIMEZONE must be supplied if one of DTSTART or DUE is not null and not all-day"); + // if one of DTSTART or DUE is given, TZ must not be null unless it's an all-day + // task + if ((dtStart != null || due != null) && !task.valueOf(TaskAdapter.IS_ALLDAY) + && task.valueOf(TaskAdapter.TIMEZONE_RAW) == null) { + throw new IllegalArgumentException( + "TIMEZONE must be supplied if one of DTSTART or DUE is not null and not all-day"); } } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Dated.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Dated.java index c9e606c0f4b5513b6b59b2b770dfee9429d31895..f2e33a00ed999066eae3707ba55b35c4112a0bf4 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Dated.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Dated.java @@ -17,35 +17,30 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; import android.content.ContentValues; - +import java.util.TimeZone; import org.dmfs.jems.optional.Optional; import org.dmfs.jems.single.Single; import org.dmfs.jems.single.decorators.DelegatingSingle; import org.dmfs.provider.tasks.utils.Zipped; import org.dmfs.rfc5545.DateTime; -import java.util.TimeZone; - - /** * A {@link Single} of date and time {@link ContentValues} of an instance. * * @author Marten Gajda */ -public final class Dated extends DelegatingSingle -{ +public final class Dated extends DelegatingSingle { - public Dated(Optional dateTime, String timeStampColumn, String sortingColumn, Single delegate) - { - super(new Zipped<>( - dateTime, - delegate, - (dateTime1, values) -> - { - // add timestamp and sorting - values.put(timeStampColumn, dateTime1.getTimestamp()); - values.put(sortingColumn, dateTime1.isAllDay() ? dateTime1.getInstance() : dateTime1.shiftTimeZone(TimeZone.getDefault()).getInstance()); - return values; - })); + public Dated(Optional dateTime, String timeStampColumn, String sortingColumn, + Single delegate) { + super(new Zipped<>(dateTime, delegate, (dateTime1, values) -> { + // add timestamp and sorting + values.put(timeStampColumn, dateTime1.getTimestamp()); + values.put(sortingColumn, + dateTime1.isAllDay() + ? dateTime1.getInstance() + : dateTime1.shiftTimeZone(TimeZone.getDefault()).getInstance()); + return values; + })); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Distant.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Distant.java index fafc5ca6e2b41d4ea92e6661aa76abc74f8e3998..c888b4a506dfd52f37c4b73654858a1733df9b9c 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Distant.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Distant.java @@ -17,24 +17,20 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; import android.content.ContentValues; - import org.dmfs.jems.single.Single; import org.dmfs.jems.single.decorators.DelegatingSingle; import org.dmfs.tasks.contract.TaskContract; - /** - * A {@link Single} of the instance distance {@link ContentValues} of an instance. + * A {@link Single} of the instance distance {@link ContentValues} of an + * instance. * * @author Marten Gajda */ -public final class Distant extends DelegatingSingle -{ +public final class Distant extends DelegatingSingle { - public Distant(int distance, Single delegate) - { - super(() -> - { + public Distant(int distance, Single delegate) { + super(() -> { ContentValues values = delegate.value(); values.put(TaskContract.Instances.DISTANCE_FROM_CURRENT, distance); return values; diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DueDated.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DueDated.java index d39005f607a123c3fc8af32e645c0090c9a0e12b..503321992ca5b6dba0059576ab50bb99be09820c 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DueDated.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DueDated.java @@ -17,23 +17,20 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; import android.content.ContentValues; - import org.dmfs.jems.optional.Optional; import org.dmfs.jems.single.Single; import org.dmfs.jems.single.decorators.DelegatingSingle; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; - /** * A decorator to a {@link Single} of {@link ContentValues} adding due data. * * @author Marten Gajda */ -public final class DueDated extends DelegatingSingle -{ - public DueDated(Optional due, Single delegate) - { - super(new Dated(due, TaskContract.Instances.INSTANCE_DUE, TaskContract.Instances.INSTANCE_DUE_SORTING, delegate)); +public final class DueDated extends DelegatingSingle { + public DueDated(Optional due, Single delegate) { + super(new Dated(due, TaskContract.Instances.INSTANCE_DUE, TaskContract.Instances.INSTANCE_DUE_SORTING, + delegate)); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Enduring.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Enduring.java index 0552a877444211aa1e242e1711622809a9862645..c1c6f7c93b18275fb25567bfb7115b9d273e20a9 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Enduring.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Enduring.java @@ -17,43 +17,36 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; import android.content.ContentValues; - import org.dmfs.jems.optional.composite.Zipped; import org.dmfs.jems.optional.elementary.NullSafe; import org.dmfs.jems.single.Single; import org.dmfs.jems.single.combined.Backed; import org.dmfs.tasks.contract.TaskContract; - /** - * A decorator for {@link Single}s of Instance {@link ContentValues} which populates the {@link TaskContract.Instances#INSTANCE_DURATION} field based on the - * already populated {@link TaskContract.Instances#INSTANCE_START} and {@link TaskContract.Instances#INSTANCE_DUE} fields. + * A decorator for {@link Single}s of Instance {@link ContentValues} which + * populates the {@link TaskContract.Instances#INSTANCE_DURATION} field based on + * the already populated {@link TaskContract.Instances#INSTANCE_START} and + * {@link TaskContract.Instances#INSTANCE_DUE} fields. * * @author Marten Gajda */ -public final class Enduring implements Single -{ +public final class Enduring implements Single { private final Single mDelegate; - - public Enduring(Single delegate) - { + public Enduring(Single delegate) { mDelegate = delegate; } - @Override - public ContentValues value() - { + public ContentValues value() { ContentValues values = mDelegate.value(); - // just store the difference between due and start, if both are present, otherwise store null + // just store the difference between due and start, if both are present, + // otherwise store null values.put(TaskContract.Instances.INSTANCE_DURATION, - new Backed( - new Zipped<>( - new NullSafe<>(values.getAsLong(TaskContract.Instances.INSTANCE_START)), - new NullSafe<>(values.getAsLong(TaskContract.Instances.INSTANCE_DUE)), - (start, due) -> due - start), - () -> null).value()); + new Backed(new Zipped<>(new NullSafe<>(values.getAsLong(TaskContract.Instances.INSTANCE_START)), + new NullSafe<>(values.getAsLong(TaskContract.Instances.INSTANCE_DUE)), + (start, due) -> due - start), () -> null).value()); return values; } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Overridden.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Overridden.java index 793ffa1e6f9fd65d87ef3a859bc5ac171f8b2f67..f2a6913c7653f5be90c4f0a63a0d96cf26c287bd 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Overridden.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/Overridden.java @@ -17,7 +17,6 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; import android.content.ContentValues; - import org.dmfs.jems.optional.Optional; import org.dmfs.jems.optional.decorators.Mapped; import org.dmfs.jems.optional.elementary.Present; @@ -26,37 +25,31 @@ import org.dmfs.jems.single.Single; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; - /** - * A decorator for {@link Single}s of Instance {@link ContentValues} which populates the {@link TaskContract.Instances#INSTANCE_ORIGINAL_TIME} field based on - * the given {@link Optional} original start. + * A decorator for {@link Single}s of Instance {@link ContentValues} which + * populates the {@link TaskContract.Instances#INSTANCE_ORIGINAL_TIME} field + * based on the given {@link Optional} original start. * * @author Marten Gajda */ -public final class Overridden implements Single -{ +public final class Overridden implements Single { private final Optional mOriginalTime; private final Single mDelegate; - - public Overridden(DateTime originalTime, ContentValues delegate) - { + public Overridden(DateTime originalTime, ContentValues delegate) { this(new Present<>(originalTime), () -> delegate); } - - public Overridden(Optional originalTime, Single delegate) - { + public Overridden(Optional originalTime, Single delegate) { mOriginalTime = originalTime; mDelegate = delegate; } - @Override - public ContentValues value() - { + public ContentValues value() { ContentValues values = mDelegate.value(); - new ForEach<>(new Mapped<>(DateTime::getTimestamp, mOriginalTime)).process(time -> values.put(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, time)); + new ForEach<>(new Mapped<>(DateTime::getTimestamp, mOriginalTime)) + .process(time -> values.put(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, time)); return values; } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/StartDated.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/StartDated.java index 5ecb320571207c3b6890a7b40d673eb0c3ea9bef..672a1176ef64c55f09ef828d14ff0dcd728ef8ee 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/StartDated.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/StartDated.java @@ -17,23 +17,20 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; import android.content.ContentValues; - import org.dmfs.jems.optional.Optional; import org.dmfs.jems.single.Single; import org.dmfs.jems.single.decorators.DelegatingSingle; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; - /** * A decorator to a {@link Single} of {@link ContentValues} adding start data. * * @author Marten Gajda */ -public final class StartDated extends DelegatingSingle -{ - public StartDated(Optional start, Single delegate) - { - super(new Dated(start, TaskContract.Instances.INSTANCE_START, TaskContract.Instances.INSTANCE_START_SORTING, delegate)); +public final class StartDated extends DelegatingSingle { + public StartDated(Optional start, Single delegate) { + super(new Dated(start, TaskContract.Instances.INSTANCE_START, TaskContract.Instances.INSTANCE_START_SORTING, + delegate)); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/TaskRelated.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/TaskRelated.java index 65be8e90fc5b6a306d9ca8ceafa8a1b670f5bf2b..09e869f95e5681019d6fcf0f9b6c1593db58baf2 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/TaskRelated.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/TaskRelated.java @@ -17,39 +17,31 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; import android.content.ContentValues; - import org.dmfs.jems.single.Single; import org.dmfs.provider.tasks.model.TaskAdapter; import org.dmfs.tasks.contract.TaskContract; - /** - * A decorator to {@link Single}s of {@link ContentValues} adding a {@link TaskContract.Instances#TASK_ID} to the data. + * A decorator to {@link Single}s of {@link ContentValues} adding a + * {@link TaskContract.Instances#TASK_ID} to the data. * * @author Marten Gajda */ -public final class TaskRelated implements Single -{ +public final class TaskRelated implements Single { private final long mTaskId; private final Single mDelegate; - - public TaskRelated(TaskAdapter taskAdapter, Single delegate) - { + public TaskRelated(TaskAdapter taskAdapter, Single delegate) { this(taskAdapter.id(), delegate); } - - public TaskRelated(long taskId, Single delegate) - { + public TaskRelated(long taskId, Single delegate) { mTaskId = taskId; mDelegate = delegate; } - @Override - public ContentValues value() - { + public ContentValues value() { ContentValues values = mDelegate.value(); values.put(TaskContract.Instances.TASK_ID, mTaskId); return values; diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/VanillaInstanceData.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/VanillaInstanceData.java index b46d3cc2401cc5d3646732d0a24dab9035c0a145..86919f49bf6218c869cf8b24ddc94e9c33720e3a 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/VanillaInstanceData.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/processors/tasks/instancedata/VanillaInstanceData.java @@ -17,22 +17,21 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; import android.content.ContentValues; - import org.dmfs.jems.single.Single; import org.dmfs.tasks.contract.TaskContract; - /** - * A {@link Single} of instance data {@link ContentValues}. It initializes most columns with {@code null} values, except for {@link - * TaskContract.Instances#TASK_ID} which is left out and {@link TaskContract.Instances#DISTANCE_FROM_CURRENT} which is initialized with {@code 0} as well. + * A {@link Single} of instance data {@link ContentValues}. It initializes most + * columns with {@code + * null} values, except for {@link TaskContract.Instances#TASK_ID} which is left + * out and {@link TaskContract.Instances#DISTANCE_FROM_CURRENT} which is + * initialized with {@code 0} as well. * * @author Marten Gajda */ -public final class VanillaInstanceData implements Single -{ +public final class VanillaInstanceData implements Single { @Override - public ContentValues value() - { + public ContentValues value() { ContentValues values = new ContentValues(10); values.putNull(TaskContract.Instances.INSTANCE_START); values.putNull(TaskContract.Instances.INSTANCE_START_SORTING); diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/ContainsValues.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/ContainsValues.java index 3f37b2ec5caed16b5cf02b35ab1ee8accddba3ee..2f3c0a5419d3884c20ecc42332e22b9e42e136f5 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/ContainsValues.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/ContainsValues.java @@ -18,51 +18,38 @@ package org.dmfs.provider.tasks.utils; import android.content.ContentValues; import android.database.Cursor; - -import org.dmfs.jems.predicate.Predicate; - import java.util.Arrays; - +import org.dmfs.jems.predicate.Predicate; /** - * A {@link Predicate} which determines whether all values of a ContentValues object are present in a {@link Cursor}. + * A {@link Predicate} which determines whether all values of a ContentValues + * object are present in a {@link Cursor}. * * @author Marten Gajda */ -public final class ContainsValues implements Predicate -{ +public final class ContainsValues implements Predicate { private final ContentValues mValues; - - public ContainsValues(ContentValues values) - { + public ContainsValues(ContentValues values) { mValues = values; } - @Override - public boolean satisfiedBy(Cursor testedInstance) - { - for (String key : mValues.keySet()) - { + public boolean satisfiedBy(Cursor testedInstance) { + for (String key : mValues.keySet()) { int columnIdx = testedInstance.getColumnIndex(key); - if (columnIdx < 0) - { + if (columnIdx < 0) { return false; } - if (testedInstance.getType(columnIdx) == Cursor.FIELD_TYPE_BLOB) - { - if (!Arrays.equals(mValues.getAsByteArray(key), testedInstance.getBlob(columnIdx))) - { + if (testedInstance.getType(columnIdx) == Cursor.FIELD_TYPE_BLOB) { + if (!Arrays.equals(mValues.getAsByteArray(key), testedInstance.getBlob(columnIdx))) { return false; } - } - else - { + } else { String stringValue = mValues.getAsString(key); - if (stringValue != null && !stringValue.equals(testedInstance.getString(columnIdx)) || stringValue == null && !testedInstance.isNull(columnIdx)) - { + if (stringValue != null && !stringValue.equals(testedInstance.getString(columnIdx)) + || stringValue == null && !testedInstance.isNull(columnIdx)) { return false; } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/InstanceValuesIterable.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/InstanceValuesIterable.java index 5ee653d96722c6d5e15d06be96e33eb924dca1cb..c1e78bead0367602ae232874ca085f8b77e319a2 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/InstanceValuesIterable.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/InstanceValuesIterable.java @@ -17,7 +17,7 @@ package org.dmfs.provider.tasks.utils; import android.content.ContentValues; - +import java.util.Iterator; import org.dmfs.iterators.SingletonIterator; import org.dmfs.jems.iterable.elementary.Seq; import org.dmfs.jems.iterator.decorators.Mapped; @@ -38,83 +38,70 @@ import org.dmfs.provider.tasks.processors.tasks.instancedata.VanillaInstanceData import org.dmfs.rfc5545.DateTime; import org.dmfs.rfc5545.Duration; -import java.util.Iterator; - - /** - * An {@link Iterable} of {@link Single} {@link ContentValues} of the instances of a task. + * An {@link Iterable} of {@link Single} {@link ContentValues} of the instances + * of a task. * * @author Marten Gajda */ // TODO: replace Single with Generator -public final class InstanceValuesIterable implements Iterable> -{ +public final class InstanceValuesIterable implements Iterable> { private final long mId; private final TaskAdapter mTaskAdapter; - - public InstanceValuesIterable(long id, TaskAdapter taskAdapter) - { + public InstanceValuesIterable(long id, TaskAdapter taskAdapter) { mId = id; mTaskAdapter = taskAdapter; } - @Override - public Iterator> iterator() - { + public Iterator> iterator() { Optional start = new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.DTSTART)); // effective due is either the actual due, start + duration or absent - Optional effectiveDue = new FirstPresent<>( - new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.DUE)), + Optional effectiveDue = new FirstPresent<>(new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.DUE)), new Zipped<>(start, new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.DURATION)), DateTime::addDuration)); - Single baseData = new Distant(mTaskAdapter.valueOf(TaskAdapter.IS_CLOSED) ? -1 : 0, - new Enduring(new DueDated(effectiveDue, new StartDated(start, new TaskRelated(mId, new VanillaInstanceData()))))); + Single baseData = new Distant(mTaskAdapter.valueOf(TaskAdapter.IS_CLOSED) ? -1 : 0, new Enduring( + new DueDated(effectiveDue, new StartDated(start, new TaskRelated(mId, new VanillaInstanceData()))))); - if (!mTaskAdapter.isRecurring()) - { + if (!mTaskAdapter.isRecurring()) { return new SingletonIterator<>( - // apply the Overridden decorator only if this task has an ORIGINAL_INSTANCE_TIME + // apply the Overridden decorator only if this task has an + // ORIGINAL_INSTANCE_TIME new org.dmfs.provider.tasks.utils.Zipped<>( - new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_TIME)), - baseData, + new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_TIME)), baseData, (DateTime time, ContentValues data) -> new Overridden(time, data).value())); } - if (start.isPresent()) - { + if (start.isPresent()) { Optional effectiveDuration = new FirstPresent<>( - new Seq<>( - new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.DURATION)), - new Zipped<>(start, effectiveDue, - (dtStart, due) -> new Duration(1, 0, (int) ((due.getTimestamp() - dtStart.getTimestamp()) / 1000))))); - - return new Mapped<>(dateTime -> new Distant(mTaskAdapter.valueOf(TaskAdapter.IS_CLOSED) ? -1 : 0, - new Overridden(new Present<>(dateTime), - new Enduring( - new DueDated(new Zipped<>(new Present<>(dateTime), effectiveDuration, this::addDuration), + new Seq<>(new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.DURATION)), + new Zipped<>(start, effectiveDue, (dtStart, due) -> new Duration(1, 0, + (int) ((due.getTimestamp() - dtStart.getTimestamp()) / 1000))))); + + return new Mapped<>( + dateTime -> new Distant(mTaskAdapter.valueOf(TaskAdapter.IS_CLOSED) ? -1 : 0, + new Overridden(new Present<>(dateTime), + new Enduring(new DueDated( + new Zipped<>(new Present<>(dateTime), effectiveDuration, this::addDuration), new StartDated(new Present<>(dateTime), new TaskRelated(mId, new VanillaInstanceData())))))), new TaskInstanceIterable(mTaskAdapter).iterator()); } // special treatment for recurring tasks without a DTSTART: - return new Mapped<>(dateTime -> new Distant(mTaskAdapter.valueOf(TaskAdapter.IS_CLOSED) ? -1 : 0, - new Overridden(new Present<>(dateTime), - new DueDated(new Present<>(dateTime), new TaskRelated(mId, new VanillaInstanceData())))), + return new Mapped<>( + dateTime -> new Distant(mTaskAdapter.valueOf(TaskAdapter.IS_CLOSED) ? -1 : 0, + new Overridden(new Present<>(dateTime), + new DueDated(new Present<>(dateTime), + new TaskRelated(mId, new VanillaInstanceData())))), new TaskInstanceIterable(mTaskAdapter).iterator()); - } - - private DateTime addDuration(DateTime dt, Duration dur) - { - if (dt.isAllDay() && dur.getSecondsOfDay() != 0) - { + private DateTime addDuration(DateTime dt, Duration dur) { + if (dt.isAllDay() && dur.getSecondsOfDay() != 0) { dur = new Duration(1, dur.getWeeks() * 7 + dur.getDays() + dur.getSecondsOfDay() / (3600 * 24), 0); } return dt.addDuration(dur); } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Limited.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Limited.java index 43833a1a3b2d2612bd9541ce9282dc0da4e222cf..3c5cb895495869648b7cf8aa8fd0449e3d3e1e54 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Limited.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Limited.java @@ -18,9 +18,9 @@ package org.dmfs.provider.tasks.utils; import java.util.Iterator; - /** * An {@link Iterable} which limits the number of elements. + * *

* TODO: move to jems * @@ -28,22 +28,17 @@ import java.util.Iterator; * @deprecated */ @Deprecated -public final class Limited implements Iterable -{ +public final class Limited implements Iterable { private final int mCount; private final Iterable mDelegate; - - public Limited(int count, Iterable delegate) - { + public Limited(int count, Iterable delegate) { mCount = count; mDelegate = delegate; } - @Override - public Iterator iterator() - { + public Iterator iterator() { return new LimitedIterator<>(mCount, mDelegate.iterator()); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/LimitedIterator.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/LimitedIterator.java index 88bba90ded9284f73b4eadd4df2ab467576e7a3e..49c38122e2e08177607f609029566aab53bad48d 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/LimitedIterator.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/LimitedIterator.java @@ -16,45 +16,34 @@ package org.dmfs.provider.tasks.utils; -import org.dmfs.iterators.AbstractBaseIterator; - import java.util.Iterator; import java.util.NoSuchElementException; - +import org.dmfs.iterators.AbstractBaseIterator; /** - * An {@link Iterator} which limits the number elements. - * TODO: move to jems + * An {@link Iterator} which limits the number elements. TODO: move to jems * * @author Marten Gajda * @deprecated */ @Deprecated -public final class LimitedIterator extends AbstractBaseIterator -{ +public final class LimitedIterator extends AbstractBaseIterator { private int mCount; private final Iterator mDelegate; - - public LimitedIterator(int count, Iterator delegate) - { + public LimitedIterator(int count, Iterator delegate) { mCount = count; mDelegate = delegate; } - @Override - public boolean hasNext() - { + public boolean hasNext() { return mCount > 0 && mDelegate.hasNext(); } - @Override - public T next() - { - if (!hasNext()) - { + public T next() { + if (!hasNext()) { throw new NoSuchElementException("No more elements to iterate"); } mCount--; diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/OverrideValuesFunction.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/OverrideValuesFunction.java index b8984b6f2b721dff8cdfa6ae91ae90caf04378dd..654b4c6493157a6f57b5152bb8238db120743aa1 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/OverrideValuesFunction.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/OverrideValuesFunction.java @@ -17,7 +17,6 @@ package org.dmfs.provider.tasks.utils; import android.content.ContentValues; - import org.dmfs.jems.function.Function; import org.dmfs.jems.optional.Optional; import org.dmfs.jems.optional.adapters.FirstPresent; @@ -34,31 +33,29 @@ import org.dmfs.provider.tasks.processors.tasks.instancedata.TaskRelated; import org.dmfs.provider.tasks.processors.tasks.instancedata.VanillaInstanceData; import org.dmfs.rfc5545.DateTime; - /** - * An {@link Iterable} of {@link Single} {@link ContentValues} of the overrides of a task. + * An {@link Iterable} of {@link Single} {@link ContentValues} of the overrides + * of a task. * * @author Marten Gajda */ -public final class OverrideValuesFunction implements Function> -{ +public final class OverrideValuesFunction implements Function> { @Override - public Single value(TaskAdapter taskAdapter) - { + public Single value(TaskAdapter taskAdapter) { Optional start = new NullSafe<>(taskAdapter.valueOf(TaskAdapter.DTSTART)); // effective due is either the actual due, start + duration or absent - Optional effectiveDue = new FirstPresent<>( - new NullSafe<>(taskAdapter.valueOf(TaskAdapter.DUE)), + Optional effectiveDue = new FirstPresent<>(new NullSafe<>(taskAdapter.valueOf(TaskAdapter.DUE)), new Zipped<>(start, new NullSafe<>(taskAdapter.valueOf(TaskAdapter.DURATION)), DateTime::addDuration)); Single baseData = new Distant(taskAdapter.valueOf(TaskAdapter.IS_CLOSED) ? -1 : 0, - new Enduring(new DueDated(effectiveDue, new StartDated(start, new TaskRelated(taskAdapter, new VanillaInstanceData()))))); + new Enduring(new DueDated(effectiveDue, + new StartDated(start, new TaskRelated(taskAdapter, new VanillaInstanceData()))))); - // apply the Overridden decorator only if this task has an ORIGINAL_INSTANCE_TIME + // apply the Overridden decorator only if this task has an + // ORIGINAL_INSTANCE_TIME return new org.dmfs.provider.tasks.utils.Zipped<>( - new NullSafe<>(taskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_TIME)), - baseData, + new NullSafe<>(taskAdapter.valueOf(TaskAdapter.ORIGINAL_INSTANCE_TIME)), baseData, (DateTime time, ContentValues data) -> new Overridden(time, data).value()); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Profiled.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Profiled.java index a30f3fc6385d10f76d0f794d6d8282a8f71c203c..99ae259a55eed29df620b9314fb1ec877f8ad773 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Profiled.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Profiled.java @@ -17,64 +17,48 @@ package org.dmfs.provider.tasks.utils; import android.util.Log; - +import java.util.Locale; import org.dmfs.jems.fragile.Fragile; import org.dmfs.jems.single.Single; -import java.util.Locale; - - /** * A simple class to measure the execution time of a given piece of code. * * @author Marten Gajda */ -public final class Profiled -{ +public final class Profiled { private final String mSubject; - - public Profiled(String subject) - { + public Profiled(String subject) { mSubject = subject; } - - public void run(Runnable runnable) - { + public void run(Runnable runnable) { long start = System.currentTimeMillis(); runnable.run(); - Log.d("Profiled", String.format(Locale.ENGLISH, "Time spent in %s: %d milliseconds", mSubject, System.currentTimeMillis() - start)); + Log.d("Profiled", String.format(Locale.ENGLISH, "Time spent in %s: %d milliseconds", mSubject, + System.currentTimeMillis() - start)); } - - public V run(Single runnable) - { + public V run(Single runnable) { long start = System.currentTimeMillis(); - try - { + try { return runnable.value(); - } - finally - { - Log.d("Profiled", String.format(Locale.ENGLISH, "Time spent in %s: %d milliseconds", mSubject, System.currentTimeMillis() - start)); + } finally { + Log.d("Profiled", String.format(Locale.ENGLISH, "Time spent in %s: %d milliseconds", mSubject, + System.currentTimeMillis() - start)); } } - - public V run(Fragile runnable) throws E - { + public V run(Fragile runnable) throws E { long start = System.currentTimeMillis(); - try - { + try { return runnable.value(); - } - finally - { - Log.d("Profiled", String.format(Locale.ENGLISH, "Time spent in %s: %d milliseconds", mSubject, System.currentTimeMillis() - start)); + } finally { + Log.d("Profiled", String.format(Locale.ENGLISH, "Time spent in %s: %d milliseconds", mSubject, + System.currentTimeMillis() - start)); } } - } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Range.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Range.java index 731e4243ffbbc9c311abc02c6fd420541e85249f..fe9ca75ee99c488370ab43f6704722d7fcee2f19 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Range.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Range.java @@ -16,41 +16,33 @@ package org.dmfs.provider.tasks.utils; -import org.dmfs.jems.iterator.generators.IntSequenceGenerator; - import java.util.Iterator; - +import org.dmfs.jems.iterator.generators.IntSequenceGenerator; /** * An {@link Iterable} which iterates a range of numbers. + * *

* TODO: implement in jems * * @author Marten Gajda */ @Deprecated -public final class Range implements Iterable -{ +public final class Range implements Iterable { private final int mStart; private final int mEnd; - - public Range(int end) - { + public Range(int end) { this(0, end); } - - public Range(int start, int end) - { + public Range(int start, int end) { mStart = start; mEnd = end; } - @Override - public Iterator iterator() - { + public Iterator iterator() { return new LimitedIterator<>(mEnd - mStart, new IntSequenceGenerator(mStart)); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/ResourceArray.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/ResourceArray.java index e5b5fab144a3d3a8708168cd1289bb7305b68d01..8d0974e7f514531be5f08caa1c821fe743bc7caf 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/ResourceArray.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/ResourceArray.java @@ -17,33 +17,25 @@ package org.dmfs.provider.tasks.utils; import android.content.Context; - -import org.dmfs.iterators.elementary.Seq; - import java.util.Iterator; - +import org.dmfs.iterators.elementary.Seq; /** * An {@link Iterable} of a string array resource. * * @author Marten Gajda */ -public final class ResourceArray implements Iterable -{ +public final class ResourceArray implements Iterable { private final Context mContext; private final int mResource; - - public ResourceArray(Context context, int resource) - { + public ResourceArray(Context context, int resource) { mContext = context; mResource = resource; } - @Override - public Iterator iterator() - { + public Iterator iterator() { return new Seq<>(mContext.getResources().getStringArray(mResource)); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/RowIterator.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/RowIterator.java index e49ac383564207968e962d7e18e1335dc131ff2e..5bb20185e1ace7e0fbaf5f30d19eb8fc31d9c655 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/RowIterator.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/RowIterator.java @@ -17,38 +17,27 @@ package org.dmfs.provider.tasks.utils; import android.database.Cursor; - -import org.dmfs.iterators.AbstractBaseIterator; - import java.util.NoSuchElementException; - +import org.dmfs.iterators.AbstractBaseIterator; /** * @author Marten Gajda */ -public final class RowIterator extends AbstractBaseIterator -{ +public final class RowIterator extends AbstractBaseIterator { private final Cursor mCursor; - - public RowIterator(Cursor cursor) - { + public RowIterator(Cursor cursor) { mCursor = cursor; } - @Override - public boolean hasNext() - { + public boolean hasNext() { return mCursor.getCount() > 0 && !mCursor.isClosed() && !mCursor.isLast(); } - @Override - public Cursor next() - { - if (!hasNext()) - { + public Cursor next() { + if (!hasNext()) { throw new NoSuchElementException("No other rows to iterate."); } mCursor.moveToNext(); diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TableColumns.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TableColumns.java index d96ac735dd2db9c93c08be77cf369501f6e4c378..16ca69e5fc2960cdfe316f8680f5cf15303e173b 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TableColumns.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TableColumns.java @@ -19,39 +19,31 @@ package org.dmfs.provider.tasks.utils; import android.database.Cursor; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; - -import org.dmfs.jems.function.Function; - import java.util.LinkedList; import java.util.List; - +import org.dmfs.jems.function.Function; /** - * A {@link Function} which returns all column names of a specific table on a given database. + * A {@link Function} which returns all column names of a specific table on a + * given database. * * @author Marten Gajda */ -public final class TableColumns implements Function> -{ +public final class TableColumns implements Function> { private final String mTableName; - - public TableColumns(String tableName) - { + public TableColumns(String tableName) { mTableName = tableName; } - @Override - public Iterable value(SQLiteDatabase db) - { - try (Cursor cursor = db.rawQuery(String.format("PRAGMA table_info(%s)", DatabaseUtils.sqlEscapeString(mTableName)), null)) - { + public Iterable value(SQLiteDatabase db) { + try (Cursor cursor = db + .rawQuery(String.format("PRAGMA table_info(%s)", DatabaseUtils.sqlEscapeString(mTableName)), null)) { int nameIdx = cursor.getColumnIndexOrThrow("name"); List result = new LinkedList<>(); - while (cursor.moveToNext()) - { + while (cursor.moveToNext()) { result.add(cursor.getString(nameIdx)); } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TaskInstanceIterable.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TaskInstanceIterable.java index b3620b395383f4b8a2b4b175d711f1a1b90f6fed..9f1cd9782af338402a541000dd2ca17a6dfc4e2f 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TaskInstanceIterable.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TaskInstanceIterable.java @@ -16,6 +16,8 @@ package org.dmfs.provider.tasks.utils; +import java.util.Iterator; +import java.util.TimeZone; import org.dmfs.jems.optional.elementary.NullSafe; import org.dmfs.jems.single.combined.Backed; import org.dmfs.provider.tasks.model.TaskAdapter; @@ -25,48 +27,38 @@ import org.dmfs.rfc5545.recurrenceset.RecurrenceList; import org.dmfs.rfc5545.recurrenceset.RecurrenceRuleAdapter; import org.dmfs.rfc5545.recurrenceset.RecurrenceSet; -import java.util.Iterator; -import java.util.TimeZone; - - /** * An {@link Iterable} of all the instances of a task. * * @author Marten Gajda */ -public final class TaskInstanceIterable implements Iterable -{ +public final class TaskInstanceIterable implements Iterable { private final TaskAdapter mTaskAdapter; - - public TaskInstanceIterable(TaskAdapter taskAdapter) - { + public TaskInstanceIterable(TaskAdapter taskAdapter) { mTaskAdapter = taskAdapter; } - @Override - public Iterator iterator() - { - DateTime dtstart = new Backed(new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.DTSTART)), () -> mTaskAdapter.valueOf(TaskAdapter.DUE)).value(); + public Iterator iterator() { + DateTime dtstart = new Backed(new NullSafe<>(mTaskAdapter.valueOf(TaskAdapter.DTSTART)), + () -> mTaskAdapter.valueOf(TaskAdapter.DUE)).value(); RecurrenceSet set = new RecurrenceSet(); RecurrenceRule rule = mTaskAdapter.valueOf(TaskAdapter.RRULE); - if (rule != null) - { - if (rule.getUntil() != null && dtstart.isFloating() != rule.getUntil().isFloating()) - { - // rule UNTIL date mismatches start. This is merely a workaround for existing users. In future we should make sure + if (rule != null) { + if (rule.getUntil() != null && dtstart.isFloating() != rule.getUntil().isFloating()) { + // rule UNTIL date mismatches start. This is merely a workaround for existing + // users. In + // future we should make sure // such tasks don't exist - if (dtstart.isFloating()) - { + if (dtstart.isFloating()) { // make until floating too by making it floating in the current time zone rule.setUntil(rule.getUntil().shiftTimeZone(TimeZone.getDefault()).swapTimeZone(null)); - } - else - { + } else { // anchor UNTIL in the current time zone - rule.setUntil(new DateTime(null, rule.getUntil().getTimestamp()).swapTimeZone(TimeZone.getDefault())); + rule.setUntil( + new DateTime(null, rule.getUntil().getTimestamp()).swapTimeZone(TimeZone.getDefault())); } } set.addInstances(new RecurrenceRuleAdapter(rule)); diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TaskInstanceIterator.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TaskInstanceIterator.java index 5b74cfb63ca3dc2fe4fdac98454b8d2600ef5d9e..7ebbf64ccfbf251d8a1229c6a8d34eb534ecdc4d 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TaskInstanceIterator.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/TaskInstanceIterator.java @@ -16,6 +16,9 @@ package org.dmfs.provider.tasks.utils; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.TimeZone; import org.dmfs.iterators.AbstractBaseIterator; import org.dmfs.jems.optional.decorators.Mapped; import org.dmfs.jems.optional.elementary.NullSafe; @@ -24,52 +27,39 @@ import org.dmfs.rfc5545.DateTime; import org.dmfs.rfc5545.recurrenceset.RecurrenceSet; import org.dmfs.rfc5545.recurrenceset.RecurrenceSetIterator; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.TimeZone; - - /** - * An {@link Iterator} of instances as returned by a {@link RecurrenceSetIterator}. + * An {@link Iterator} of instances as returned by a + * {@link RecurrenceSetIterator}. + * *

* TODO: this should go to lib-recur * * @author Marten Gajda */ -public final class TaskInstanceIterator extends AbstractBaseIterator -{ +public final class TaskInstanceIterator extends AbstractBaseIterator { private final DateTime mStart; private final RecurrenceSetIterator mSetIterator; private final String mTimezone; - - TaskInstanceIterator(DateTime start, RecurrenceSet set) - { + TaskInstanceIterator(DateTime start, RecurrenceSet set) { this(start, set.iterator(start.getTimeZone(), start.getTimestamp()), new Backed<>(new Mapped<>(TimeZone::getID, new NullSafe<>(start.getTimeZone())), () -> null).value()); } - - TaskInstanceIterator(DateTime start, RecurrenceSetIterator setIterator, String timezone) - { + TaskInstanceIterator(DateTime start, RecurrenceSetIterator setIterator, String timezone) { mStart = start; mSetIterator = setIterator; mTimezone = timezone; } - @Override - public boolean hasNext() - { + public boolean hasNext() { return mSetIterator.hasNext(); } - @Override - public DateTime next() - { - if (!hasNext()) - { + public DateTime next() { + if (!hasNext()) { throw new NoSuchElementException("No more elements to iterate"); } DateTime result = new DateTime(mStart.getTimeZone(), mSetIterator.next()); diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Timestamps.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Timestamps.java index 84f0949dee116df7c9e5a092a445523130e1fef1..9507a73186c5af26ceab14898250d6950435eb21 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Timestamps.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Timestamps.java @@ -19,35 +19,28 @@ package org.dmfs.provider.tasks.utils; import org.dmfs.jems.single.Single; import org.dmfs.rfc5545.DateTime; - /** - * A {@link Single} of an array of timestamp values of a given {@link Iterable} of {@link DateTime}s. + * A {@link Single} of an array of timestamp values of a given {@link Iterable} + * of {@link DateTime}s. * * @author Marten Gajda */ -public final class Timestamps implements Single -{ +public final class Timestamps implements Single { private final Iterable mDateTimes; - - public Timestamps(Iterable dateTimes) - { + public Timestamps(Iterable dateTimes) { mDateTimes = dateTimes; } - @Override - public long[] value() - { + public long[] value() { int count = 0; - for (DateTime ignored : mDateTimes) - { + for (DateTime ignored : mDateTimes) { count += 1; } long[] timeStamps = new long[count]; int i = 0; - for (DateTime dt : mDateTimes) - { + for (DateTime dt : mDateTimes) { timeStamps[i++] = dt.getTimestamp(); } return timeStamps; diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/With.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/With.java index 7ae6b448157b417c9946fea15053e7e113b42919..8d4582776f97825e056b117dacefbfb840d178ec 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/With.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/With.java @@ -21,43 +21,33 @@ import org.dmfs.jems.optional.adapters.SinglePresent; import org.dmfs.jems.procedure.Procedure; import org.dmfs.jems.single.Single; - /** * Experiemental Procedure which calls another procedure with a given value. + * *

* TODO move to jems if this works out well * * @author Marten Gajda */ @Deprecated -public final class With implements Procedure> -{ +public final class With implements Procedure> { private final Optional mValue; - - public With(T value) - { + public With(T value) { this(() -> value); } - - public With(Single value) - { + public With(Single value) { this(new SinglePresent<>(value)); } - - public With(Optional value) - { + public With(Optional value) { mValue = value; } - @Override - public void process(Procedure delegate) - { - if (mValue.isPresent()) - { + public void process(Procedure delegate) { + if (mValue.isPresent()) { delegate.process(mValue.value()); } } diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Zipped.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Zipped.java index 80df3f7fe2dc73290515400ba392080c9f3713ef..b218c5e27f1cab3ea70ef60f983126392e9076f0 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Zipped.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/utils/Zipped.java @@ -23,21 +23,21 @@ import org.dmfs.jems.single.Single; import org.dmfs.jems.single.combined.Backed; import org.dmfs.jems.single.decorators.DelegatingSingle; - /** - * Experimental {@link Single} which applies a {@link BiFunction} based on the presence of an {@link Optional}. + * Experimental {@link Single} which applies a {@link BiFunction} based on the + * presence of an {@link Optional}. + * *

* TODO: maybe a more appropriate name? + * *

* TODO: move to jems * * @author Marten Gajda */ @Deprecated -public final class Zipped extends DelegatingSingle -{ - public Zipped(Optional optionalValue, Single delegate, BiFunction function) - { +public final class Zipped extends DelegatingSingle { + public Zipped(Optional optionalValue, Single delegate, BiFunction function) { super(new Backed(new Mapped<>(from -> function.value(from, delegate.value()), optionalValue), delegate)); } } diff --git a/opentasks-provider/src/main/res/drawable/ic_24_opentasks.xml b/opentasks-provider/src/main/res/drawable/ic_24_opentasks.xml index a5420b49ab2a9193906ec4a3df8f282f561518fe..ba721c68124b5b403d673f4ed5d6ac302452793a 100644 --- a/opentasks-provider/src/main/res/drawable/ic_24_opentasks.xml +++ b/opentasks-provider/src/main/res/drawable/ic_24_opentasks.xml @@ -1,4 +1,6 @@ - + android:viewportWidth="960.00006" android:width="24dp" + xmlns:android="http://schemas.android.com/apk/res/android"> + diff --git a/opentasks-provider/src/main/res/values-de/strings.xml b/opentasks-provider/src/main/res/values-de/strings.xml index 45491a4209858fbfc0559bb0d25ede17c9ecacde..c3b5dd443f8f0a391599eddcb3392f9f75550a3e 100644 --- a/opentasks-provider/src/main/res/values-de/strings.xml +++ b/opentasks-provider/src/main/res/values-de/strings.xml @@ -4,12 +4,13 @@ Aufgaben - + Aufgaben lesen Aufgaben lesen Aufgaben schreiben - Aufgaben und Aufgabenlisten erstellen, bearbeiten und löschen + Aufgaben und Aufgabenlisten erstellen, bearbeiten + und löschen Aufgaben lesen und verwalten diff --git a/opentasks-provider/src/main/res/values-fr/strings.xml b/opentasks-provider/src/main/res/values-fr/strings.xml index 31736fc1efc068649e38e26a16ac31abce6c34d0..451d4c450fd8bfd39dabd4657ecde29fc8f4b496 100644 --- a/opentasks-provider/src/main/res/values-fr/strings.xml +++ b/opentasks-provider/src/main/res/values-fr/strings.xml @@ -7,9 +7,12 @@ Lire tâches - Autoriser une application à lire les tâches de la listes de tâches + Autoriser une application à lire les tâches de la + listes de tâches Écrire tâches - Autoriser une application à écrire des tâches dans la listes de tâches - Autoriser une application à écrire des tâches dans la listes de tâches + Autoriser une application à écrire des tâches dans + la listes de tâches + Autoriser une application à écrire des tâches dans + la listes de tâches diff --git a/opentasks-provider/src/main/res/values-hu/strings.xml b/opentasks-provider/src/main/res/values-hu/strings.xml index ae9ea8156841002c37767d1a08559fca2ddbe7b2..a77fde0bea1b4ab3bcf8fb363748c29edcf53ea0 100644 --- a/opentasks-provider/src/main/res/values-hu/strings.xml +++ b/opentasks-provider/src/main/res/values-hu/strings.xml @@ -9,7 +9,9 @@ feladatok olvasása Feladatok és feladatlisták olvasása feladatok írása - Feladatok és feladatlisták létrehozása, módosítása és törlése - Feladatok és feladatlisták létrehozása, módosítása és törlése + Feladatok és feladatlisták létrehozása, módosítása + és törlése + Feladatok és feladatlisták létrehozása, módosítása + és törlése diff --git a/opentasks-provider/src/main/res/values-it/strings.xml b/opentasks-provider/src/main/res/values-it/strings.xml index b34fa667303442a545d7ba6b4b92d8c7dd558285..e62ab2b8853fa3df73b21ed2e2b920f63018b751 100644 --- a/opentasks-provider/src/main/res/values-it/strings.xml +++ b/opentasks-provider/src/main/res/values-it/strings.xml @@ -9,7 +9,8 @@ lettura attività lettura attività ed elenchi di attività scrittura attività - creazione, modifica e eliminazione di attività ed elenchi di attività + creazione, modifica e eliminazione di attività ed + elenchi di attività accesso e modifica delle attività diff --git a/opentasks-provider/src/main/res/values-nl/strings.xml b/opentasks-provider/src/main/res/values-nl/strings.xml index 3d37b3c809bfa9dec6be4d0f538f9b8333b014ab..41a536214476d72d7b088a9c1f00cbfc83cdda4f 100644 --- a/opentasks-provider/src/main/res/values-nl/strings.xml +++ b/opentasks-provider/src/main/res/values-nl/strings.xml @@ -7,9 +7,12 @@ leestaken - Staat een app toe om taken in je takenlijst te lezen + Staat een app toe om taken in je takenlijst te + lezen schrijftaken - Staat een app toe om taken in je takenlijst aan te maken - Staat een app tpe om taken in je takenlijst aan te maken + Staat een app toe om taken in je takenlijst aan te + maken + Staat een app tpe om taken in je takenlijst aan te + maken diff --git a/opentasks-provider/src/main/res/values-pl/strings.xml b/opentasks-provider/src/main/res/values-pl/strings.xml index b2973e2138cfe1942fadd068a40489ea1527b4d8..1da4560cc30c2234fff7239a778df992385fe2ce 100644 --- a/opentasks-provider/src/main/res/values-pl/strings.xml +++ b/opentasks-provider/src/main/res/values-pl/strings.xml @@ -7,9 +7,12 @@ Czytaj zadania - Pozwala aplikacji na czytanie zadań z Twojej listy zadań + Pozwala aplikacji na czytanie zadań z Twojej listy + zadań Zapisuj zadania - Pozwala aplikacji na zapisywanie zadań na Twojej liście zadań - Pozwala aplikacji na zapisywanie zadań na Twojej liście zadań + Pozwala aplikacji na zapisywanie zadań na Twojej + liście zadań + Pozwala aplikacji na zapisywanie zadań na Twojej + liście zadań diff --git a/opentasks-provider/src/main/res/values-pt-rBR/strings.xml b/opentasks-provider/src/main/res/values-pt-rBR/strings.xml index bdb8414b886d47e2d5415852f2f1aa5488a28bf5..a57720187bdd06082d327d0f7360c99547e79c4f 100644 --- a/opentasks-provider/src/main/res/values-pt-rBR/strings.xml +++ b/opentasks-provider/src/main/res/values-pt-rBR/strings.xml @@ -7,9 +7,12 @@ ler tarefas - Permite que um aplicativo leia as tarefas na sua lista de tarefas + Permite que um aplicativo leia as tarefas na sua + lista de tarefas escrever tarefas - Permite que um aplicativo escreva tarefas na sua lista de tarefas - Permite que um aplicativo escreva tarefas na sua lista de tarefas + Permite que um aplicativo escreva tarefas na sua + lista de tarefas + Permite que um aplicativo escreva tarefas na sua + lista de tarefas - \ No newline at end of file + diff --git a/opentasks-provider/src/main/res/values-pt-rPT/strings.xml b/opentasks-provider/src/main/res/values-pt-rPT/strings.xml index 39ae46f8bb2a3967f578b7cdafdf77e2c6d574f6..7f765c6965814549ff16167ede22b718fd1c3e76 100644 --- a/opentasks-provider/src/main/res/values-pt-rPT/strings.xml +++ b/opentasks-provider/src/main/res/values-pt-rPT/strings.xml @@ -9,7 +9,9 @@ ler tarefas Ler tarefas e listas de tarefas escrever tarefas - Criar, modificar e eliminar tarefas e listas de tarefas - Criar, modificar e eliminar tarefas e listas de tarefas + Criar, modificar e eliminar tarefas e listas de + tarefas + Criar, modificar e eliminar tarefas e listas de + tarefas diff --git a/opentasks-provider/src/main/res/values-ru/strings.xml b/opentasks-provider/src/main/res/values-ru/strings.xml index 7f02ec90c6f346b5ea885c6bcd8d335de340695b..264cb308ca4230a2490700e2dc407b93727854ae 100644 --- a/opentasks-provider/src/main/res/values-ru/strings.xml +++ b/opentasks-provider/src/main/res/values-ru/strings.xml @@ -9,9 +9,12 @@ чтение задач - Разрешить приложению читать задачи из Ваших списков задач + Разрешить приложению читать задачи из Ваших списков + задач запись задач - Разрешить приложению сохранять задачи в Ваших списках задач - Разрешить приложению сохранять задачи в Ваших списках задач + Разрешить приложению сохранять задачи в Ваших + списках задач + Разрешить приложению сохранять задачи в Ваших + списках задач diff --git a/opentasks-provider/src/main/res/values-sr/strings.xml b/opentasks-provider/src/main/res/values-sr/strings.xml index f5e96a51b706ea7dbb3c037e9ec85b45148171c2..3c4f371cad7cf5d101ddf349cfecc165228e0cd4 100644 --- a/opentasks-provider/src/main/res/values-sr/strings.xml +++ b/opentasks-provider/src/main/res/values-sr/strings.xml @@ -7,9 +7,12 @@ читање задатака - Дозвољава апликацији да чита задатке са ваше листе задатака + Дозвољава апликацији да чита задатке са ваше листе + задатака упис задатака - Дозвољава апликацији да уноси задатке у вашу листу задатака - Дозвољава апликацији да уноси задатке у вашу листу задатака + Дозвољава апликацији да уноси задатке у вашу листу + задатака + Дозвољава апликацији да уноси задатке у вашу листу + задатака diff --git a/opentasks-provider/src/main/res/values-uk/strings.xml b/opentasks-provider/src/main/res/values-uk/strings.xml index d011b97400b82c41b808898d1d6ca59923d68968..fb7e208edcce3105a0bd6983b5515c8cdfb0faaa 100644 --- a/opentasks-provider/src/main/res/values-uk/strings.xml +++ b/opentasks-provider/src/main/res/values-uk/strings.xml @@ -7,9 +7,12 @@ читання завдань - Дозволити додатку читати ваші завдання з ваших переліків завдань + Дозволити додатку читати ваші завдання з ваших + переліків завдань запис завдань - Дозволити додатку зберігати завдання до ваших переліків завдань - Дозволити додатку зберігати завдання до ваших переліків завдань + Дозволити додатку зберігати завдання до ваших + переліків завдань + Дозволити додатку зберігати завдання до ваших + переліків завдань diff --git a/opentasks-provider/src/main/res/values/opentasks_defaults.xml b/opentasks-provider/src/main/res/values/opentasks_defaults.xml index 5135fc4f5f8556013ddcf899b1511fc40a0d341a..c441a9db89594ea629160dfab79f068a0d321fe1 100644 --- a/opentasks-provider/src/main/res/values/opentasks_defaults.xml +++ b/opentasks-provider/src/main/res/values/opentasks_defaults.xml @@ -2,7 +2,6 @@ - foundation.e.tasks + foundation.e.tasks - \ No newline at end of file + diff --git a/opentasks-provider/src/main/res/values/opentasks_provider_changed_receivers.xml b/opentasks-provider/src/main/res/values/opentasks_provider_changed_receivers.xml index 344b230b4b41777a765c4ffd0aba9c67e8f4e2f7..97e74c5766d144c75cd3ced0560e4ac5df01b1a6 100644 --- a/opentasks-provider/src/main/res/values/opentasks_provider_changed_receivers.xml +++ b/opentasks-provider/src/main/res/values/opentasks_provider_changed_receivers.xml @@ -3,4 +3,4 @@ org.andstatus.todoagenda - \ No newline at end of file + diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/model/adapters/DateTimeIterableFieldAdapterTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/model/adapters/DateTimeIterableFieldAdapterTest.java index 29ff80910d1d4edb693829c109d260755b10f3df..2651d5fdb26c49a2d7aa81573bf83f3af8c7b87a 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/model/adapters/DateTimeIterableFieldAdapterTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/model/adapters/DateTimeIterableFieldAdapterTest.java @@ -16,8 +16,12 @@ package org.dmfs.provider.tasks.model.adapters; -import android.content.ContentValues; +import static org.dmfs.jems.hamcrest.matchers.IterableMatcher.iteratesTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import android.content.ContentValues; import org.dmfs.iterables.EmptyIterable; import org.dmfs.iterables.elementary.Seq; import org.dmfs.provider.tasks.model.TaskAdapter; @@ -27,49 +31,35 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.jems.hamcrest.matchers.IterableMatcher.iteratesTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class DateTimeIterableFieldAdapterTest -{ +public class DateTimeIterableFieldAdapterTest { @Test - public void testFieldName() - { + public void testFieldName() { assertThat(new DateTimeIterableFieldAdapter<>("x", "y").fieldName(), is("x")); } - @Test - public void testGetFromCVAllDay1() - { + public void testGetFromCVAllDay1() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); values.put("x", "20180109"); assertThat(adapter.getFrom(values), iteratesTo(DateTime.parse("20180109"))); } - @Test - public void testGetFromCVAllDay2() - { + public void testGetFromCVAllDay2() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); values.put("x", "20180109,20180110"); assertThat(adapter.getFrom(values), iteratesTo(DateTime.parse("20180109"), DateTime.parse("20180110"))); } - @Test - public void testGetFromCVFloating1() - { + public void testGetFromCVFloating1() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); values.put("x", "20180109T140000"); @@ -77,21 +67,18 @@ public class DateTimeIterableFieldAdapterTest assertThat(adapter.getFrom(values), iteratesTo(DateTime.parse("20180109T140000"))); } - @Test - public void testGetFromCVFloating2() - { + public void testGetFromCVFloating2() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); values.put("x", "20180109T140000,20180110T140000"); values.putNull("y"); - assertThat(adapter.getFrom(values), iteratesTo(DateTime.parse("20180109T140000"), DateTime.parse("20180110T140000"))); + assertThat(adapter.getFrom(values), + iteratesTo(DateTime.parse("20180109T140000"), DateTime.parse("20180110T140000"))); } - @Test - public void testGetFromCVAbsolute1() - { + public void testGetFromCVAbsolute1() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); values.put("x", "20180109T140000Z"); @@ -99,125 +86,107 @@ public class DateTimeIterableFieldAdapterTest assertThat(adapter.getFrom(values), iteratesTo(DateTime.parse("Europe/Berlin", "20180109T150000"))); } - @Test - public void testGetFromCVAbsolute2() - { + public void testGetFromCVAbsolute2() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); values.put("x", "20180109T140000Z,20180110T140000Z"); values.put("y", "Europe/Berlin"); - assertThat(adapter.getFrom(values), iteratesTo(DateTime.parse("Europe/Berlin", "20180109T150000"), DateTime.parse("Europe/Berlin", "20180110T150000"))); + assertThat(adapter.getFrom(values), iteratesTo(DateTime.parse("Europe/Berlin", "20180109T150000"), + DateTime.parse("Europe/Berlin", "20180110T150000"))); } - @Test - public void testSetInNull() - { + public void testSetInNull() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); adapter.setIn(values, null); assertThat(values.getAsString("x"), nullValue()); } - @Test - public void testSetInEmpty() - { + public void testSetInEmpty() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); adapter.setIn(values, EmptyIterable.instance()); assertThat(values.getAsString("x"), nullValue()); } - @Test - public void testSetInSingleAllDay() - { + public void testSetInSingleAllDay() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); adapter.setIn(values, new Seq<>(DateTime.parse("20180109"))); assertThat(values.getAsString("x"), is("20180109")); } - @Test - public void testSetInSingleFloating() - { + public void testSetInSingleFloating() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); adapter.setIn(values, new Seq<>(DateTime.parse("20180109T150000"))); assertThat(values.getAsString("x"), is("20180109T150000")); } - @Test - public void testSetInSingleAbsolute() - { + public void testSetInSingleAbsolute() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); adapter.setIn(values, new Seq<>(DateTime.parse("Europe/Berlin", "20180109T150000"))); assertThat(values.getAsString("x"), is("20180109T140000Z")); } - @Test - public void testSetInDoubleAllDay() - { + public void testSetInDoubleAllDay() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); adapter.setIn(values, new Seq<>(DateTime.parse("20180109"), DateTime.parse("20180110"))); assertThat(values.getAsString("x"), is("20180109,20180110")); } - @Test - public void testSetInDoubleFloating() - { + public void testSetInDoubleFloating() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); adapter.setIn(values, new Seq<>(DateTime.parse("20180109T150000"), DateTime.parse("20180110T150000"))); assertThat(values.getAsString("x"), is("20180109T150000,20180110T150000")); } - @Test - public void testSetInDoubleAbsolute() - { + public void testSetInDoubleAbsolute() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); - adapter.setIn(values, new Seq<>(DateTime.parse("Europe/Berlin", "20180109T150000"), DateTime.parse("Europe/Berlin", "20180110T150000"))); + adapter.setIn(values, new Seq<>(DateTime.parse("Europe/Berlin", "20180109T150000"), + DateTime.parse("Europe/Berlin", "20180110T150000"))); assertThat(values.getAsString("x"), is("20180109T140000Z,20180110T140000Z")); } - @Test - public void testSetInMultiAllDay() - { + public void testSetInMultiAllDay() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); - adapter.setIn(values, new Seq<>(DateTime.parse("20180109"), DateTime.parse("20180110"), DateTime.parse("20180111"))); + adapter.setIn(values, + new Seq<>(DateTime.parse("20180109"), DateTime.parse("20180110"), DateTime.parse("20180111"))); assertThat(values.getAsString("x"), is("20180109,20180110,20180111")); } - @Test - public void testSetInMultiFloating() - { + public void testSetInMultiFloating() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); - adapter.setIn(values, new Seq<>(DateTime.parse("20180109T150000"), DateTime.parse("20180110T150000"), DateTime.parse("20180111T150000"))); + adapter.setIn(values, new Seq<>(DateTime.parse("20180109T150000"), DateTime.parse("20180110T150000"), + DateTime.parse("20180111T150000"))); assertThat(values.getAsString("x"), is("20180109T150000,20180110T150000,20180111T150000")); } - @Test - public void testSetInMultiAbsolute() - { + public void testSetInMultiAbsolute() { ContentValues values = new ContentValues(); FieldAdapter, ?> adapter = new DateTimeIterableFieldAdapter("x", "y"); - adapter.setIn(values, new Seq<>(DateTime.parse("Europe/Berlin", "20180109T150000"), DateTime.parse("Europe/Berlin", "20180110T150000"), - DateTime.parse("Europe/Berlin", "20180111T150000"))); + adapter.setIn(values, + new Seq<>(DateTime.parse("Europe/Berlin", "20180109T150000"), + DateTime.parse("Europe/Berlin", "20180110T150000"), + DateTime.parse("Europe/Berlin", "20180111T150000"))); assertThat(values.getAsString("x"), is("20180109T140000Z,20180110T140000Z,20180111T140000Z")); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DatedTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DatedTest.java index 43bb5b955fdb9945134c70478dfe6380bfddb395..f653f71c3f29288e4c33d5c85e3c391c0e40063b 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DatedTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DatedTest.java @@ -16,9 +16,11 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; -import android.content.ContentValues; -import android.util.Log; +import static org.dmfs.jems.optional.elementary.Absent.absent; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import android.content.ContentValues; import org.dmfs.jems.optional.elementary.Present; import org.dmfs.provider.tasks.utils.ContentValuesWithLong; import org.dmfs.rfc5545.DateTime; @@ -27,39 +29,28 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.jems.optional.elementary.Absent.absent; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class DatedTest -{ +public class DatedTest { @Test - public void testAbsent() - { + public void testAbsent() { ContentValues instanceData = new Dated(absent(), "ts", "sorting", ContentValues::new).value(); // this shouldn't really add any values and go by the "defaults" assertThat(instanceData.size(), is(0)); } - @Test - public void testPresent() - { + public void testPresent() { DateTime start = DateTime.parse("Europe/Berlin", "20171208T125500"); - ContentValues instanceData = new Dated(new Present<>(start), - "ts", - "sorting", ContentValues::new).value(); + ContentValues instanceData = new Dated(new Present<>(start), "ts", "sorting", ContentValues::new).value(); assertThat(instanceData, new ContentValuesWithLong("ts", start.getTimestamp())); - assertThat(instanceData, new ContentValuesWithLong("sorting", start.getInstance())); + assertThat(instanceData, new ContentValuesWithLong("sorting", start.getInstance())); assertThat(instanceData.size(), is(2)); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DistantTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DistantTest.java index c8be962ddd8b2da50e5d92d2c01ac651d347972e..9fe6a980bd546e8fd248ad6472a93f32761c9eb5 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DistantTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DistantTest.java @@ -16,31 +16,27 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; -import android.content.ContentValues; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import android.content.ContentValues; import org.dmfs.tasks.contract.TaskContract; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class DistantTest -{ +public class DistantTest { @Test - public void test() - { + public void test() { ContentValues instanceData = new Distant(100, ContentValues::new).value(); assertThat(instanceData.get(TaskContract.Instances.DISTANCE_FROM_CURRENT), is(100)); assertThat(instanceData.size(), is(1)); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DueDatedTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DueDatedTest.java index 25840e9a2f59ede662b4c4ed1445958eb3ee1496..d71ae5b91120242f061da39aa3aaad158f83b2c0 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DueDatedTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/DueDatedTest.java @@ -16,8 +16,13 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; -import android.content.ContentValues; +import static org.dmfs.jems.optional.elementary.Absent.absent; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import android.content.ContentValues; +import java.util.TimeZone; import org.dmfs.jems.optional.elementary.Present; import org.dmfs.provider.tasks.utils.ContentValuesWithLong; import org.dmfs.rfc5545.DateTime; @@ -27,58 +32,46 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import java.util.TimeZone; - -import static org.dmfs.jems.optional.elementary.Absent.absent; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class DueDatedTest -{ +public class DueDatedTest { @Test - public void testNone() - { + public void testNone() { ContentValues instanceData = new DueDated(absent(), ContentValues::new).value(); assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DUE, nullValue(Long.class))); - assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DUE_SORTING, nullValue(Long.class))); - // this doesn't actually add anything, the ContentValues are expected to contain null values. + assertThat(instanceData, + new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DUE_SORTING, nullValue(Long.class))); + // this doesn't actually add anything, the ContentValues are expected to contain + // null values. assertThat(instanceData.size(), is(0)); } - @Test - public void testStartEurope() - { + public void testStartEurope() { DateTime start = DateTime.parse("Europe/Berlin", "20171208T125500"); ContentValues instanceData = new DueDated(new Present<>(start), ContentValues::new).value(); assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DUE, start.getTimestamp())); - assertThat(instanceData, - new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DUE_SORTING, start.shiftTimeZone(TimeZone.getDefault()).getInstance())); + assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DUE_SORTING, + start.shiftTimeZone(TimeZone.getDefault()).getInstance())); assertThat(instanceData.size(), is(2)); } - @Test - public void testStartAmerica() - { + public void testStartAmerica() { DateTime start = DateTime.parse("America/New_York", "20171208T125500"); ContentValues instanceData = new DueDated(new Present<>(start), ContentValues::new).value(); assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DUE, start.getTimestamp())); - assertThat(instanceData, - new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DUE_SORTING, start.shiftTimeZone(TimeZone.getDefault()).getInstance())); + assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DUE_SORTING, + start.shiftTimeZone(TimeZone.getDefault()).getInstance())); assertThat(instanceData.size(), is(2)); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/EnduringTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/EnduringTest.java index 4fbd8f52e3b4fc87aa59aeb5d9807aaa262487cb..b6edb590f301d188628ad698a4af9e7219a43d48 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/EnduringTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/EnduringTest.java @@ -16,8 +16,12 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; -import android.content.ContentValues; +import static org.dmfs.jems.hamcrest.matchers.SingleMatcher.hasValue; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import android.content.ContentValues; import org.dmfs.provider.tasks.utils.ContentValuesWithLong; import org.dmfs.tasks.contract.TaskContract; import org.junit.Test; @@ -25,30 +29,21 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.jems.hamcrest.matchers.SingleMatcher.hasValue; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class EnduringTest -{ +public class EnduringTest { @Test - public void testNoValue() - { - assertThat(new Enduring(ContentValues::new), hasValue(new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DURATION, nullValue(Long.class)))); + public void testNoValue() { + assertThat(new Enduring(ContentValues::new), + hasValue(new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DURATION, nullValue(Long.class)))); assertThat(new Enduring(ContentValues::new).value().size(), is(1)); } - @Test - public void testStartValue() - { + public void testStartValue() { ContentValues values = new ContentValues(1); values.put(TaskContract.Instances.INSTANCE_START, 10); assertThat(new Enduring(() -> new ContentValues(values)), @@ -56,10 +51,8 @@ public class EnduringTest assertThat(new Enduring(() -> new ContentValues(values)).value().size(), is(2)); } - @Test - public void testDueValue() - { + public void testDueValue() { ContentValues values = new ContentValues(1); values.put(TaskContract.Instances.INSTANCE_DUE, 10); assertThat(new Enduring(() -> new ContentValues(values)), @@ -67,14 +60,13 @@ public class EnduringTest assertThat(new Enduring(() -> new ContentValues(values)).value().size(), is(2)); } - @Test - public void testStartDueValue() - { + public void testStartDueValue() { ContentValues values = new ContentValues(2); values.put(TaskContract.Instances.INSTANCE_START, 1); values.put(TaskContract.Instances.INSTANCE_DUE, 10); - assertThat(new Enduring(() -> new ContentValues(values)), hasValue(new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DURATION, 9))); + assertThat(new Enduring(() -> new ContentValues(values)), + hasValue(new ContentValuesWithLong(TaskContract.Instances.INSTANCE_DURATION, 9))); assertThat(new Enduring(() -> new ContentValues(values)).value().size(), is(3)); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/OverriddenTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/OverriddenTest.java index e56d8a416292ab1dbaf0669f496c072d79680554..52aea106f1cfcea21a6895be04e737401447705c 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/OverriddenTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/OverriddenTest.java @@ -16,8 +16,12 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; -import android.content.ContentValues; +import static org.dmfs.optional.Absent.absent; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import android.content.ContentValues; import org.dmfs.jems.optional.elementary.Present; import org.dmfs.provider.tasks.utils.ContentValuesWithLong; import org.dmfs.rfc5545.DateTime; @@ -27,84 +31,71 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.optional.Absent.absent; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class OverriddenTest -{ +public class OverriddenTest { @Test - public void testAbsent() - { + public void testAbsent() { ContentValues instanceData = new Overridden(absent(), ContentValues::new).value(); - assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, nullValue(Long.class))); + assertThat(instanceData, + new ContentValuesWithLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, nullValue(Long.class))); assertThat(instanceData.size(), is(0)); } - @Test - public void testAbsentWithStart() - { + public void testAbsentWithStart() { ContentValues values = new ContentValues(); values.put(TaskContract.Instances.INSTANCE_START, 10); ContentValues instanceData = new Overridden(absent(), () -> new ContentValues(values)).value(); - assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, nullValue(Long.class))); + assertThat(instanceData, + new ContentValuesWithLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, nullValue(Long.class))); assertThat(instanceData.size(), is(1)); } - @Test - public void testAbsentWithDue() - { + public void testAbsentWithDue() { ContentValues values = new ContentValues(); values.put(TaskContract.Instances.INSTANCE_DUE, 20); ContentValues instanceData = new Overridden(absent(), () -> new ContentValues(values)).value(); - assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, nullValue(Long.class))); + assertThat(instanceData, + new ContentValuesWithLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, nullValue(Long.class))); assertThat(instanceData.size(), is(1)); } - @Test - public void testAbsentWithStartAndDue() - { + public void testAbsentWithStartAndDue() { ContentValues values = new ContentValues(); values.put(TaskContract.Instances.INSTANCE_START, 10); values.put(TaskContract.Instances.INSTANCE_DUE, 20); ContentValues instanceData = new Overridden(absent(), () -> new ContentValues(values)).value(); - assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, nullValue(Long.class))); + assertThat(instanceData, + new ContentValuesWithLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, nullValue(Long.class))); assertThat(instanceData.size(), is(2)); } - @Test - public void testPresent() - { + public void testPresent() { ContentValues instanceData = new Overridden(new Present<>(new DateTime(40)), ContentValues::new).value(); assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, 40)); assertThat(instanceData.size(), is(1)); } - @Test - public void testPresentWithStartAndDue() - { + public void testPresentWithStartAndDue() { ContentValues values = new ContentValues(); values.put(TaskContract.Instances.INSTANCE_START, 10); values.put(TaskContract.Instances.INSTANCE_DUE, 20); - ContentValues instanceData = new Overridden(new Present<>(new DateTime(40)), () -> new ContentValues(values)).value(); + ContentValues instanceData = new Overridden(new Present<>(new DateTime(40)), () -> new ContentValues(values)) + .value(); assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, 40)); assertThat(instanceData.size(), is(3)); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/StartDatedTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/StartDatedTest.java index 85676d1897c92193c2c2cccc756a2562c7cfe4d4..03abfbdbe1fc3601a125cc60b5ece415933dff85 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/StartDatedTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/StartDatedTest.java @@ -16,8 +16,13 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; -import android.content.ContentValues; +import static org.dmfs.optional.Absent.absent; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import android.content.ContentValues; +import java.util.TimeZone; import org.dmfs.jems.optional.elementary.Present; import org.dmfs.provider.tasks.utils.ContentValuesWithLong; import org.dmfs.rfc5545.DateTime; @@ -27,58 +32,49 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import java.util.TimeZone; - -import static org.dmfs.optional.Absent.absent; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class StartDatedTest -{ +public class StartDatedTest { @Test - public void testNone() - { + public void testNone() { ContentValues instanceData = new StartDated(absent(), ContentValues::new).value(); - assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START, nullValue(Long.class))); - assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START_SORTING, nullValue(Long.class))); - // this doesn't actually add anything, the ContentValues are expected to contain null values. + assertThat(instanceData, + new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START, nullValue(Long.class))); + assertThat(instanceData, + new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START_SORTING, nullValue(Long.class))); + // this doesn't actually add anything, the ContentValues are expected to contain + // null values. assertThat(instanceData.size(), is(0)); } - @Test - public void testStartEurope() - { + public void testStartEurope() { DateTime start = DateTime.parse("Europe/Berlin", "20171208T125500"); ContentValues instanceData = new StartDated(new Present<>(start), ContentValues::new).value(); - assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START, start.getTimestamp())); assertThat(instanceData, - new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START_SORTING, start.shiftTimeZone(TimeZone.getDefault()).getInstance())); + new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START, start.getTimestamp())); + assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START_SORTING, + start.shiftTimeZone(TimeZone.getDefault()).getInstance())); assertThat(instanceData.size(), is(2)); } - @Test - public void testStartAmerica() - { + public void testStartAmerica() { DateTime start = DateTime.parse("America/New_York", "20171208T125500"); ContentValues instanceData = new StartDated(new Present<>(start), ContentValues::new).value(); - assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START, start.getTimestamp())); assertThat(instanceData, - new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START_SORTING, start.shiftTimeZone(TimeZone.getDefault()).getInstance())); + new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START, start.getTimestamp())); + assertThat(instanceData, new ContentValuesWithLong(TaskContract.Instances.INSTANCE_START_SORTING, + start.shiftTimeZone(TimeZone.getDefault()).getInstance())); assertThat(instanceData.size(), is(2)); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/TaskRelatedTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/TaskRelatedTest.java index 760ca346d81f16d91cae79df44d1e165dbf00957..a07708b12626352a3be90a3b27577df4693aac8c 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/TaskRelatedTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/TaskRelatedTest.java @@ -16,8 +16,10 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; -import android.content.ContentValues; +import static org.dmfs.jems.hamcrest.matchers.SingleMatcher.hasValue; +import static org.junit.Assert.assertThat; +import android.content.ContentValues; import org.dmfs.provider.tasks.utils.ContentValuesWithLong; import org.dmfs.tasks.contract.TaskContract; import org.junit.Test; @@ -25,20 +27,15 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.jems.hamcrest.matchers.SingleMatcher.hasValue; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class TaskRelatedTest -{ +public class TaskRelatedTest { @Test - public void testValue() - { - assertThat(new TaskRelated(123, ContentValues::new), hasValue(new ContentValuesWithLong(TaskContract.Instances.TASK_ID, 123))); + public void testValue() { + assertThat(new TaskRelated(123, ContentValues::new), + hasValue(new ContentValuesWithLong(TaskContract.Instances.TASK_ID, 123))); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/VanillaInstanceDataTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/VanillaInstanceDataTest.java index f78f8bff82c4d2988c5933608c021753a81db6fd..a21350b4f39723f62f407faf3277a902643ae7d7 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/VanillaInstanceDataTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/processors/tasks/instancedata/VanillaInstanceDataTest.java @@ -16,29 +16,25 @@ package org.dmfs.provider.tasks.processors.tasks.instancedata; -import android.content.ContentValues; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import android.content.ContentValues; import org.dmfs.tasks.contract.TaskContract; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class VanillaInstanceDataTest -{ +public class VanillaInstanceDataTest { @Test - public void testValue() - { + public void testValue() { ContentValues values = new VanillaInstanceData().value(); assertThat(values.get(TaskContract.Instances.INSTANCE_START), nullValue()); assertThat(values.get(TaskContract.Instances.INSTANCE_START_SORTING), nullValue()); @@ -49,5 +45,4 @@ public class VanillaInstanceDataTest assertThat(values.get(TaskContract.Instances.INSTANCE_ORIGINAL_TIME), nullValue()); assertThat(values.size(), is(7)); } - -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ContainsValuesTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ContainsValuesTest.java index 750f4778d8576abda796fe352c5def2009163ea3..545cb44a245bc15a7b0cc3c5fcaa24fd14795bd1 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ContainsValuesTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ContainsValuesTest.java @@ -16,46 +16,42 @@ package org.dmfs.provider.tasks.utils; +import static org.dmfs.jems.hamcrest.matchers.predicate.PredicateMatcher.satisfiedBy; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; + import android.content.ContentValues; import android.database.MatrixCursor; - import org.dmfs.iterables.elementary.Seq; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.jems.hamcrest.matchers.predicate.PredicateMatcher.satisfiedBy; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class ContainsValuesTest -{ +public class ContainsValuesTest { @Test - public void test() - { + public void test() { ContentValues values = new ContentValues(); values.put("a", 123); values.put("b", "stringValue"); - values.put("c", new byte[] { 3, 2, 1 }); + values.put("c", new byte[]{3, 2, 1}); values.putNull("d"); - MatrixCursor cursor = new MatrixCursor(new String[] { "c", "b", "a", "d", "f" }); - cursor.addRow(new Seq<>(new byte[] { 3, 2, 1 }, "stringValue", 123, null, "xyz")); - cursor.addRow(new Seq<>(new byte[] { 3, 2, 1 }, "stringValue", "123", null, "xyz")); - cursor.addRow(new Seq<>(new byte[] { 3, 2 }, "stringValue", 123, null, "xyz")); - cursor.addRow(new Seq<>(new byte[] { 3, 2, 1 }, "stringValueX", 123, null, "xyz")); - cursor.addRow(new Seq<>(new byte[] { 3, 2, 1 }, "stringValue", 1234, null, "xyz")); - cursor.addRow(new Seq<>(new byte[] { 3, 2, 1 }, "stringValue", 123, "123", "xyz")); + MatrixCursor cursor = new MatrixCursor(new String[]{"c", "b", "a", "d", "f"}); + cursor.addRow(new Seq<>(new byte[]{3, 2, 1}, "stringValue", 123, null, "xyz")); + cursor.addRow(new Seq<>(new byte[]{3, 2, 1}, "stringValue", "123", null, "xyz")); + cursor.addRow(new Seq<>(new byte[]{3, 2}, "stringValue", 123, null, "xyz")); + cursor.addRow(new Seq<>(new byte[]{3, 2, 1}, "stringValueX", 123, null, "xyz")); + cursor.addRow(new Seq<>(new byte[]{3, 2, 1}, "stringValue", 1234, null, "xyz")); + cursor.addRow(new Seq<>(new byte[]{3, 2, 1}, "stringValue", 123, "123", "xyz")); cursor.addRow(new Seq<>(321, "stringValueX", "1234", "123", "xyz")); - cursor.addRow(new Seq<>(new byte[] { 3, 2, 1, 0 }, "stringValueX", 1234, "123", "xyz")); + cursor.addRow(new Seq<>(new byte[]{3, 2, 1, 0}, "stringValueX", 1234, "123", "xyz")); cursor.moveToFirst(); assertThat(new ContainsValues(values), is(satisfiedBy(cursor))); @@ -75,20 +71,18 @@ public class ContainsValuesTest assertThat(new ContainsValues(values), is(not(satisfiedBy(cursor)))); } - @Test - public void testMissingColumns() - { + public void testMissingColumns() { ContentValues values = new ContentValues(); values.put("a", 123); values.put("b", "stringValue"); - values.put("c", new byte[] { 3, 2, 1 }); + values.put("c", new byte[]{3, 2, 1}); values.putNull("d"); - MatrixCursor cursor = new MatrixCursor(new String[] { "c", "b" }); - cursor.addRow(new Seq<>(new byte[] { 3, 2, 1 }, "stringValue")); + MatrixCursor cursor = new MatrixCursor(new String[]{"c", "b"}); + cursor.addRow(new Seq<>(new byte[]{3, 2, 1}, "stringValue")); cursor.moveToFirst(); assertThat(new ContainsValues(values), is(not(satisfiedBy(cursor)))); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ContentValuesWithLong.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ContentValuesWithLong.java index 6dafc00b220ffeead636358403c5cef425d7eada..76d11917e955ddd124bf040839c46fdfaf15ced8 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ContentValuesWithLong.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ContentValuesWithLong.java @@ -16,42 +16,37 @@ package org.dmfs.provider.tasks.utils; -import android.content.ContentValues; +import static org.hamcrest.Matchers.is; +import android.content.ContentValues; import org.hamcrest.FeatureMatcher; import org.hamcrest.Matcher; -import static org.hamcrest.Matchers.is; - - /** - * A {@link Matcher} to test if {@link ContentValues} contain a specific Long value. + * A {@link Matcher} to test if {@link ContentValues} contain a specific Long + * value. + * *

- * TODO: can we convert that into a more generic {@link ContentValues} matcher? It might be useful in other places. + * TODO: can we convert that into a more generic {@link ContentValues} matcher? + * It might be useful in other places. + * *

* TODO: also consider moving this to "Test-Bolts" */ -public final class ContentValuesWithLong extends FeatureMatcher -{ +public final class ContentValuesWithLong extends FeatureMatcher { private final String mKey; - - public ContentValuesWithLong(String valueKey, long value) - { + public ContentValuesWithLong(String valueKey, long value) { this(valueKey, is(value)); } - - public ContentValuesWithLong(String valueKey, Matcher matcher) - { + public ContentValuesWithLong(String valueKey, Matcher matcher) { super(matcher, "Long value " + valueKey, "Long value " + valueKey); mKey = valueKey; } - @Override - protected Long featureValueOf(ContentValues actual) - { + protected Long featureValueOf(ContentValues actual) { return actual.getAsLong(mKey); } } diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/TaskInstanceIterableTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/TaskInstanceIterableTest.java index 81eff9c6f157ebab3ba29ddc043a60b4b6c74df4..9ce549fe2f9809082606d683a0394c2c24862315 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/TaskInstanceIterableTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/TaskInstanceIterableTest.java @@ -16,8 +16,10 @@ package org.dmfs.provider.tasks.utils; -import android.content.ContentValues; +import static org.dmfs.jems.hamcrest.matchers.IterableMatcher.iteratesTo; +import static org.junit.Assert.assertThat; +import android.content.ContentValues; import org.dmfs.iterables.elementary.Seq; import org.dmfs.provider.tasks.model.ContentValuesTaskAdapter; import org.dmfs.provider.tasks.model.TaskAdapter; @@ -28,161 +30,94 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.jems.hamcrest.matchers.IterableMatcher.iteratesTo; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class TaskInstanceIterableTest -{ +public class TaskInstanceIterableTest { @Test - public void testAbsolute() throws Exception - { + public void testAbsolute() throws Exception { TaskAdapter taskAdapter = new ContentValuesTaskAdapter(new ContentValues()); taskAdapter.set(TaskAdapter.DTSTART, DateTime.parse("Europe/Berlin", "20170606T121314")); taskAdapter.set(TaskAdapter.RRULE, new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=10")); - assertThat(new TaskInstanceIterable(taskAdapter), - iteratesTo( - DateTime.parse("Europe/Berlin", "20170606T121314"), - DateTime.parse("Europe/Berlin", "20170608T121314"), - DateTime.parse("Europe/Berlin", "20170610T121314"), - DateTime.parse("Europe/Berlin", "20170612T121314"), - DateTime.parse("Europe/Berlin", "20170614T121314"), - DateTime.parse("Europe/Berlin", "20170616T121314"), - DateTime.parse("Europe/Berlin", "20170618T121314"), - DateTime.parse("Europe/Berlin", "20170620T121314"), - DateTime.parse("Europe/Berlin", "20170622T121314"), - DateTime.parse("Europe/Berlin", "20170624T121314") - )); + assertThat(new TaskInstanceIterable(taskAdapter), iteratesTo(DateTime.parse("Europe/Berlin", "20170606T121314"), + DateTime.parse("Europe/Berlin", "20170608T121314"), DateTime.parse("Europe/Berlin", "20170610T121314"), + DateTime.parse("Europe/Berlin", "20170612T121314"), DateTime.parse("Europe/Berlin", "20170614T121314"), + DateTime.parse("Europe/Berlin", "20170616T121314"), DateTime.parse("Europe/Berlin", "20170618T121314"), + DateTime.parse("Europe/Berlin", "20170620T121314"), DateTime.parse("Europe/Berlin", "20170622T121314"), + DateTime.parse("Europe/Berlin", "20170624T121314"))); } - @Test - public void testAllDay() throws Exception - { + public void testAllDay() throws Exception { TaskAdapter taskAdapter = new ContentValuesTaskAdapter(new ContentValues()); taskAdapter.set(TaskAdapter.DTSTART, DateTime.parse("20170606")); taskAdapter.set(TaskAdapter.RRULE, new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=10")); assertThat(new TaskInstanceIterable(taskAdapter), - iteratesTo( - DateTime.parse("20170606"), - DateTime.parse("20170608"), - DateTime.parse("20170610"), - DateTime.parse("20170612"), - DateTime.parse("20170614"), - DateTime.parse("20170616"), - DateTime.parse("20170618"), - DateTime.parse("20170620"), - DateTime.parse("20170622"), - DateTime.parse("20170624") - )); + iteratesTo(DateTime.parse("20170606"), DateTime.parse("20170608"), DateTime.parse("20170610"), + DateTime.parse("20170612"), DateTime.parse("20170614"), DateTime.parse("20170616"), + DateTime.parse("20170618"), DateTime.parse("20170620"), DateTime.parse("20170622"), + DateTime.parse("20170624"))); } - @Test - public void testFloating() throws Exception - { + public void testFloating() throws Exception { TaskAdapter taskAdapter = new ContentValuesTaskAdapter(new ContentValues()); taskAdapter.set(TaskAdapter.DTSTART, DateTime.parse("20170606T121314")); taskAdapter.set(TaskAdapter.RRULE, new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=10")); assertThat(new TaskInstanceIterable(taskAdapter), - iteratesTo( - DateTime.parse("20170606T121314"), - DateTime.parse("20170608T121314"), - DateTime.parse("20170610T121314"), - DateTime.parse("20170612T121314"), - DateTime.parse("20170614T121314"), - DateTime.parse("20170616T121314"), - DateTime.parse("20170618T121314"), - DateTime.parse("20170620T121314"), - DateTime.parse("20170622T121314"), - DateTime.parse("20170624T121314") - )); + iteratesTo(DateTime.parse("20170606T121314"), DateTime.parse("20170608T121314"), + DateTime.parse("20170610T121314"), DateTime.parse("20170612T121314"), + DateTime.parse("20170614T121314"), DateTime.parse("20170616T121314"), + DateTime.parse("20170618T121314"), DateTime.parse("20170620T121314"), + DateTime.parse("20170622T121314"), DateTime.parse("20170624T121314"))); } - @Test - public void testRDate() throws Exception - { + public void testRDate() throws Exception { TaskAdapter taskAdapter = new ContentValuesTaskAdapter(new ContentValues()); taskAdapter.set(TaskAdapter.DTSTART, DateTime.parse("Europe/Berlin", "20170606T121314")); - taskAdapter.set(TaskAdapter.RDATE, new Seq<>( - DateTime.parse("Europe/Berlin", "20170606T121314"), - DateTime.parse("Europe/Berlin", "20170608T121314"), - DateTime.parse("Europe/Berlin", "20170610T121314"), - DateTime.parse("Europe/Berlin", "20170612T121314"), - DateTime.parse("Europe/Berlin", "20170614T121314"), - DateTime.parse("Europe/Berlin", "20170616T121314"), - DateTime.parse("Europe/Berlin", "20170618T121314"), - DateTime.parse("Europe/Berlin", "20170620T121314"), - DateTime.parse("Europe/Berlin", "20170622T121314"), - DateTime.parse("Europe/Berlin", "20170624T121314") - )); - - assertThat(new TaskInstanceIterable(taskAdapter), - iteratesTo( - DateTime.parse("Europe/Berlin", "20170606T121314"), - DateTime.parse("Europe/Berlin", "20170608T121314"), - DateTime.parse("Europe/Berlin", "20170610T121314"), - DateTime.parse("Europe/Berlin", "20170612T121314"), - DateTime.parse("Europe/Berlin", "20170614T121314"), - DateTime.parse("Europe/Berlin", "20170616T121314"), - DateTime.parse("Europe/Berlin", "20170618T121314"), - DateTime.parse("Europe/Berlin", "20170620T121314"), - DateTime.parse("Europe/Berlin", "20170622T121314"), - DateTime.parse("Europe/Berlin", "20170624T121314") - )); + taskAdapter.set(TaskAdapter.RDATE, new Seq<>(DateTime.parse("Europe/Berlin", "20170606T121314"), + DateTime.parse("Europe/Berlin", "20170608T121314"), DateTime.parse("Europe/Berlin", "20170610T121314"), + DateTime.parse("Europe/Berlin", "20170612T121314"), DateTime.parse("Europe/Berlin", "20170614T121314"), + DateTime.parse("Europe/Berlin", "20170616T121314"), DateTime.parse("Europe/Berlin", "20170618T121314"), + DateTime.parse("Europe/Berlin", "20170620T121314"), DateTime.parse("Europe/Berlin", "20170622T121314"), + DateTime.parse("Europe/Berlin", "20170624T121314"))); + + assertThat(new TaskInstanceIterable(taskAdapter), iteratesTo(DateTime.parse("Europe/Berlin", "20170606T121314"), + DateTime.parse("Europe/Berlin", "20170608T121314"), DateTime.parse("Europe/Berlin", "20170610T121314"), + DateTime.parse("Europe/Berlin", "20170612T121314"), DateTime.parse("Europe/Berlin", "20170614T121314"), + DateTime.parse("Europe/Berlin", "20170616T121314"), DateTime.parse("Europe/Berlin", "20170618T121314"), + DateTime.parse("Europe/Berlin", "20170620T121314"), DateTime.parse("Europe/Berlin", "20170622T121314"), + DateTime.parse("Europe/Berlin", "20170624T121314"))); } - @Test - public void testRDateAndRRule() throws Exception - { + public void testRDateAndRRule() throws Exception { TaskAdapter taskAdapter = new ContentValuesTaskAdapter(new ContentValues()); taskAdapter.set(TaskAdapter.DTSTART, DateTime.parse("Europe/Berlin", "20170606T121314")); taskAdapter.set(TaskAdapter.RRULE, new RecurrenceRule("FREQ=DAILY;INTERVAL=2;COUNT=10")); - taskAdapter.set(TaskAdapter.RDATE, new Seq<>( - DateTime.parse("Europe/Berlin", "20170606T121313"), - DateTime.parse("Europe/Berlin", "20170608T121313"), - DateTime.parse("Europe/Berlin", "20170610T121313"), - DateTime.parse("Europe/Berlin", "20170612T121313"), - DateTime.parse("Europe/Berlin", "20170614T121313"), - DateTime.parse("Europe/Berlin", "20170616T121313"), - DateTime.parse("Europe/Berlin", "20170618T121313"), - DateTime.parse("Europe/Berlin", "20170620T121313"), - DateTime.parse("Europe/Berlin", "20170622T121313"), - DateTime.parse("Europe/Berlin", "20170624T121313") - )); - - assertThat(new TaskInstanceIterable(taskAdapter), - iteratesTo( - DateTime.parse("Europe/Berlin", "20170606T121313"), - DateTime.parse("Europe/Berlin", "20170606T121314"), - DateTime.parse("Europe/Berlin", "20170608T121313"), - DateTime.parse("Europe/Berlin", "20170608T121314"), - DateTime.parse("Europe/Berlin", "20170610T121313"), - DateTime.parse("Europe/Berlin", "20170610T121314"), - DateTime.parse("Europe/Berlin", "20170612T121313"), - DateTime.parse("Europe/Berlin", "20170612T121314"), - DateTime.parse("Europe/Berlin", "20170614T121313"), - DateTime.parse("Europe/Berlin", "20170614T121314"), - DateTime.parse("Europe/Berlin", "20170616T121313"), - DateTime.parse("Europe/Berlin", "20170616T121314"), - DateTime.parse("Europe/Berlin", "20170618T121313"), - DateTime.parse("Europe/Berlin", "20170618T121314"), - DateTime.parse("Europe/Berlin", "20170620T121313"), - DateTime.parse("Europe/Berlin", "20170620T121314"), - DateTime.parse("Europe/Berlin", "20170622T121313"), - DateTime.parse("Europe/Berlin", "20170622T121314"), - DateTime.parse("Europe/Berlin", "20170624T121313"), - DateTime.parse("Europe/Berlin", "20170624T121314") - )); + taskAdapter.set(TaskAdapter.RDATE, new Seq<>(DateTime.parse("Europe/Berlin", "20170606T121313"), + DateTime.parse("Europe/Berlin", "20170608T121313"), DateTime.parse("Europe/Berlin", "20170610T121313"), + DateTime.parse("Europe/Berlin", "20170612T121313"), DateTime.parse("Europe/Berlin", "20170614T121313"), + DateTime.parse("Europe/Berlin", "20170616T121313"), DateTime.parse("Europe/Berlin", "20170618T121313"), + DateTime.parse("Europe/Berlin", "20170620T121313"), DateTime.parse("Europe/Berlin", "20170622T121313"), + DateTime.parse("Europe/Berlin", "20170624T121313"))); + + assertThat(new TaskInstanceIterable(taskAdapter), iteratesTo(DateTime.parse("Europe/Berlin", "20170606T121313"), + DateTime.parse("Europe/Berlin", "20170606T121314"), DateTime.parse("Europe/Berlin", "20170608T121313"), + DateTime.parse("Europe/Berlin", "20170608T121314"), DateTime.parse("Europe/Berlin", "20170610T121313"), + DateTime.parse("Europe/Berlin", "20170610T121314"), DateTime.parse("Europe/Berlin", "20170612T121313"), + DateTime.parse("Europe/Berlin", "20170612T121314"), DateTime.parse("Europe/Berlin", "20170614T121313"), + DateTime.parse("Europe/Berlin", "20170614T121314"), DateTime.parse("Europe/Berlin", "20170616T121313"), + DateTime.parse("Europe/Berlin", "20170616T121314"), DateTime.parse("Europe/Berlin", "20170618T121313"), + DateTime.parse("Europe/Berlin", "20170618T121314"), DateTime.parse("Europe/Berlin", "20170620T121313"), + DateTime.parse("Europe/Berlin", "20170620T121314"), DateTime.parse("Europe/Berlin", "20170622T121313"), + DateTime.parse("Europe/Berlin", "20170622T121314"), DateTime.parse("Europe/Berlin", "20170624T121313"), + DateTime.parse("Europe/Berlin", "20170624T121314"))); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/TaskInstanceIteratorTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/TaskInstanceIteratorTest.java index 552f43de4c936a6b2e7e6f4f69b65f57ac30ab7b..cfe0746eb212b24f1d847f1ec6acd344a086cf4f 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/TaskInstanceIteratorTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/TaskInstanceIteratorTest.java @@ -16,6 +16,10 @@ package org.dmfs.provider.tasks.utils; +import static org.dmfs.jems.hamcrest.matchers.iterator.IteratorMatcher.iteratorOf; +import static org.junit.Assert.assertThat; + +import java.util.TimeZone; import org.dmfs.rfc5545.DateTime; import org.dmfs.rfc5545.recur.InvalidRecurrenceRuleException; import org.dmfs.rfc5545.recur.RecurrenceRule; @@ -23,99 +27,55 @@ import org.dmfs.rfc5545.recurrenceset.RecurrenceRuleAdapter; import org.dmfs.rfc5545.recurrenceset.RecurrenceSet; import org.junit.Test; -import java.util.TimeZone; - -import static org.dmfs.jems.hamcrest.matchers.iterator.IteratorMatcher.iteratorOf; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ -public class TaskInstanceIteratorTest -{ - private final static String TIMEZONE = "Europe/Berlin"; - +public class TaskInstanceIteratorTest { + private static final String TIMEZONE = "Europe/Berlin"; @Test - public void testAbsolute() throws InvalidRecurrenceRuleException - { + public void testAbsolute() throws InvalidRecurrenceRuleException { RecurrenceSet recurrenceSet = new RecurrenceSet(); recurrenceSet.addInstances(new RecurrenceRuleAdapter(new RecurrenceRule("FREQ=DAILY;COUNT=3"))); DateTime start = DateTime.parse(TIMEZONE, "20210201T120000"); assertThat( - () -> new TaskInstanceIterator(start, recurrenceSet.iterator(TimeZone.getTimeZone(TIMEZONE), start.getTimestamp()), TIMEZONE), - iteratorOf( - DateTime.parse(TIMEZONE, "20210201T120000"), - DateTime.parse(TIMEZONE, "20210202T120000"), - DateTime.parse(TIMEZONE, "20210203T120000") - ) - ); - - assertThat( - () -> new TaskInstanceIterator(start, recurrenceSet), - iteratorOf( - DateTime.parse(TIMEZONE, "20210201T120000"), - DateTime.parse(TIMEZONE, "20210202T120000"), - DateTime.parse(TIMEZONE, "20210203T120000") - ) - ); + () -> new TaskInstanceIterator(start, + recurrenceSet.iterator(TimeZone.getTimeZone(TIMEZONE), start.getTimestamp()), TIMEZONE), + iteratorOf(DateTime.parse(TIMEZONE, "20210201T120000"), DateTime.parse(TIMEZONE, "20210202T120000"), + DateTime.parse(TIMEZONE, "20210203T120000"))); + + assertThat(() -> new TaskInstanceIterator(start, recurrenceSet), + iteratorOf(DateTime.parse(TIMEZONE, "20210201T120000"), DateTime.parse(TIMEZONE, "20210202T120000"), + DateTime.parse(TIMEZONE, "20210203T120000"))); } - @Test - public void testFloating() throws InvalidRecurrenceRuleException - { + public void testFloating() throws InvalidRecurrenceRuleException { RecurrenceSet recurrenceSet = new RecurrenceSet(); recurrenceSet.addInstances(new RecurrenceRuleAdapter(new RecurrenceRule("FREQ=DAILY;COUNT=3"))); DateTime start = DateTime.parse("20210201T120000"); - assertThat( - () -> new TaskInstanceIterator(start, recurrenceSet.iterator(null, start.getTimestamp()), null), - iteratorOf( - DateTime.parse("20210201T120000"), - DateTime.parse("20210202T120000"), - DateTime.parse("20210203T120000") - ) - ); + assertThat(() -> new TaskInstanceIterator(start, recurrenceSet.iterator(null, start.getTimestamp()), null), + iteratorOf(DateTime.parse("20210201T120000"), DateTime.parse("20210202T120000"), + DateTime.parse("20210203T120000"))); - assertThat( - () -> new TaskInstanceIterator(start, recurrenceSet), - iteratorOf( - DateTime.parse("20210201T120000"), - DateTime.parse("20210202T120000"), - DateTime.parse("20210203T120000") - ) - ); + assertThat(() -> new TaskInstanceIterator(start, recurrenceSet), iteratorOf(DateTime.parse("20210201T120000"), + DateTime.parse("20210202T120000"), DateTime.parse("20210203T120000"))); } - @Test - public void testAllDay() throws InvalidRecurrenceRuleException - { + public void testAllDay() throws InvalidRecurrenceRuleException { RecurrenceSet recurrenceSet = new RecurrenceSet(); recurrenceSet.addInstances(new RecurrenceRuleAdapter(new RecurrenceRule("FREQ=DAILY;COUNT=3"))); DateTime start = DateTime.parse("20210201"); - assertThat( - () -> new TaskInstanceIterator(start, recurrenceSet.iterator(null, start.getTimestamp()), null), - iteratorOf( - DateTime.parse("20210201"), - DateTime.parse("20210202"), - DateTime.parse("20210203") - ) - ); + assertThat(() -> new TaskInstanceIterator(start, recurrenceSet.iterator(null, start.getTimestamp()), null), + iteratorOf(DateTime.parse("20210201"), DateTime.parse("20210202"), DateTime.parse("20210203"))); - assertThat( - () -> new TaskInstanceIterator(start, recurrenceSet), - iteratorOf( - DateTime.parse("20210201"), - DateTime.parse("20210202"), - DateTime.parse("20210203") - ) - ); + assertThat(() -> new TaskInstanceIterator(start, recurrenceSet), + iteratorOf(DateTime.parse("20210201"), DateTime.parse("20210202"), DateTime.parse("20210203"))); } -} \ No newline at end of file +} diff --git a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ZippedTest.java b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ZippedTest.java index f81928c07dd2be9315e49ec4b2ca0e97eaf9dd7e..a14f1deb814863807040378c2bf61315a4bf5478 100644 --- a/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ZippedTest.java +++ b/opentasks-provider/src/test/java/org/dmfs/provider/tasks/utils/ZippedTest.java @@ -16,11 +16,6 @@ package org.dmfs.provider.tasks.utils; -import org.dmfs.jems.function.BiFunction; -import org.dmfs.jems.optional.elementary.Present; -import org.dmfs.jems.single.elementary.ValueSingle; -import org.junit.Test; - import static org.dmfs.jems.hamcrest.matchers.SingleMatcher.hasValue; import static org.dmfs.jems.mockito.doubles.TestDoubles.dummy; import static org.dmfs.jems.mockito.doubles.TestDoubles.failingMock; @@ -29,31 +24,30 @@ import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.doReturn; +import org.dmfs.jems.function.BiFunction; +import org.dmfs.jems.optional.elementary.Present; +import org.dmfs.jems.single.elementary.ValueSingle; +import org.junit.Test; /** * @author Marten Gajda */ -public class ZippedTest -{ +public class ZippedTest { @Test - public void testPresent() - { + public void testPresent() { Object dummyPresentValue = new Object(); Object dummySingleValue = new Object(); Object dummyResult = new Object(); BiFunction mockFunction = failingMock(BiFunction.class); doReturn(dummyResult).when(mockFunction).value(dummyPresentValue, dummySingleValue); - assertThat(new Zipped<>(new Present<>(dummyPresentValue), new ValueSingle<>(dummySingleValue), mockFunction), hasValue(sameInstance(dummyResult))); + assertThat(new Zipped<>(new Present<>(dummyPresentValue), new ValueSingle<>(dummySingleValue), mockFunction), + hasValue(sameInstance(dummyResult))); } - @Test - public void testAbsent() - { + public void testAbsent() { Object dummyObject = new Object(); - assertThat( - new Zipped(absent(), new ValueSingle<>(dummyObject), dummy(BiFunction.class)), - hasValue(sameInstance(dummyObject)) - ); + assertThat(new Zipped(absent(), new ValueSingle<>(dummyObject), dummy(BiFunction.class)), + hasValue(sameInstance(dummyObject))); } -} \ No newline at end of file +} diff --git a/opentasks-theme/build.gradle b/opentasks-theme/build.gradle index d675aad7c72667cb0ee33d602ac4bbda0ae8a9d5..81ca149a9dfbf3183dcef1e5e9d1d037189265f4 100644 --- a/opentasks-theme/build.gradle +++ b/opentasks-theme/build.gradle @@ -26,7 +26,6 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 36 - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" } @@ -37,6 +36,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + compileOptions { sourceCompatibility JavaVersion.VERSION_21 targetCompatibility JavaVersion.VERSION_21 diff --git a/opentasks-theme/src/main/AndroidManifest.xml b/opentasks-theme/src/main/AndroidManifest.xml index 7e97eb3a46ac1307a491dfa22d3d7287e9e71014..a214d0974df40fc98e3a585c807c3fc918704de6 100644 --- a/opentasks-theme/src/main/AndroidManifest.xml +++ b/opentasks-theme/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - \ No newline at end of file + diff --git a/opentasks-theme/src/main/res/values-night/theme_daynight.xml b/opentasks-theme/src/main/res/values-night/theme_daynight.xml index e28d907db0abc615820f84f009b399b317d3dce1..05a6ad1636dc9119024f59805b22ef362f323f2d 100644 --- a/opentasks-theme/src/main/res/values-night/theme_daynight.xml +++ b/opentasks-theme/src/main/res/values-night/theme_daynight.xml @@ -2,9 +2,10 @@ - + - \ No newline at end of file + diff --git a/opentasks/src/main/res/values-night/styles.xml b/opentasks/src/main/res/values-night/styles.xml index 310a63ccabe32f226d5cf8abeebdb22758ac9d28..d9208773ec372a27d933fa595a260d2ca3c1243c 100644 --- a/opentasks/src/main/res/values-night/styles.xml +++ b/opentasks/src/main/res/values-night/styles.xml @@ -1,3 +1,5 @@ - - - \ No newline at end of file + diff --git a/opentasks/src/main/res/values-v27/styles.xml b/opentasks/src/main/res/values-v27/styles.xml index c7d63d7d544a84cc6b765795b1f5b6975f26db4d..9f0901abeb39b1206b2c29c37003436336407423 100644 --- a/opentasks/src/main/res/values-v27/styles.xml +++ b/opentasks/src/main/res/values-v27/styles.xml @@ -1,7 +1,6 @@ - @@ -18,4 +17,4 @@ true - \ No newline at end of file + diff --git a/opentasks/src/main/res/values-zh-rCN/strings.xml b/opentasks/src/main/res/values-zh-rCN/strings.xml index 3a9934b9df3afba6391617aaf8bb2c87105aeaf7..065519ea146ca2c616b78eb42f8a3b90fb8cea48 100644 --- a/opentasks/src/main/res/values-zh-rCN/strings.xml +++ b/opentasks/src/main/res/values-zh-rCN/strings.xml @@ -39,10 +39,9 @@ 发送到 添加项目 - + 项目标题 编辑 @@ -220,7 +219,8 @@ 通知 - 通知方式 + 通知方式 声音 @@ -230,12 +230,17 @@ 通过OpenTasks共享 - 没有权限 -
+ 没有权限 +
请注意,因为Google一个令人遗憾的抉择, 该权限的标注从 "读取用户账号" 变为 "读取通讯录" . 参看Issue 37065963 以获得更详细信息.]]>
- 继续 - 打开设置 - + 继续 + 打开设置 + %1$s, %2$s %1$s, %2$s @@ -277,4 +282,4 @@ 打开 拨打 发邮件给 - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/arrays.xml b/opentasks/src/main/res/values/arrays.xml index e90d4d9326a4a1594afffa01d7461cf62b39dc40..5ba8c1e3916468f132ea0b104060db3e312e1148 100644 --- a/opentasks/src/main/res/values/arrays.xml +++ b/opentasks/src/main/res/values/arrays.xml @@ -88,8 +88,7 @@ "Fiji" "Tonga" - + "Pacific/Majuro" "Pacific/Midway" "Pacific/Honolulu" @@ -176,4 +175,4 @@ "Pacific/Tongatapu" - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/attrs.xml b/opentasks/src/main/res/values/attrs.xml index b8243b8dcb7b3795d547965e895363e13d7b6d6b..446ed4a26cb59644b5948c9860d4566b5808f2dd 100644 --- a/opentasks/src/main/res/values/attrs.xml +++ b/opentasks/src/main/res/values/attrs.xml @@ -1,30 +1,25 @@ - - + + - + - + - + - + - + - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/bools.xml b/opentasks/src/main/res/values/bools.xml index cac900adc3da1795c17021a54b779b460d06aa7f..06ae7a766a8e9b6960d499c6ae2003579a05bb08 100644 --- a/opentasks/src/main/res/values/bools.xml +++ b/opentasks/src/main/res/values/bools.xml @@ -3,11 +3,12 @@ false - + false false true false - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/colors.xml b/opentasks/src/main/res/values/colors.xml index ab5a3021a7a37eccc2ecfd0f9dd25cf27bc5b540..ec694679dbb47c0f9d26b40df30064effd2b2515 100644 --- a/opentasks/src/main/res/values/colors.xml +++ b/opentasks/src/main/res/values/colors.xml @@ -52,4 +52,4 @@ @color/e_accent @color/priority_green @color/e_divider_color - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/dashclock.xml b/opentasks/src/main/res/values/dashclock.xml index 55b3e369830df8b3ceab1de61c7a8f7bb675deec..369dc90ad12e4f983af016790bd4fe42381cdc75 100644 --- a/opentasks/src/main/res/values/dashclock.xml +++ b/opentasks/src/main/res/values/dashclock.xml @@ -16,4 +16,4 @@ - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/dimens.xml b/opentasks/src/main/res/values/dimens.xml index 478ba2bd1a726c0c1ff17b12c16d195904500788..c6c1ec94c74d3a48e75b454c42f20aa88fa6eaaa 100644 --- a/opentasks/src/main/res/values/dimens.xml +++ b/opentasks/src/main/res/values/dimens.xml @@ -10,4 +10,4 @@ 120dp -80dp - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/ids.xml b/opentasks/src/main/res/values/ids.xml index b053cc3c01fdea18763d94021590833eb1db1f95..1c1fad6f0547477e6660fcbc04cd7cf0ce1ff9fc 100644 --- a/opentasks/src/main/res/values/ids.xml +++ b/opentasks/src/main/res/values/ids.xml @@ -1,46 +1,25 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/ints.xml b/opentasks/src/main/res/values/ints.xml index 5c1a7d115b33245f92aaf24f36db506bdde2fd99..96d0f93188bd1c53bec604306352011faabaefda 100644 --- a/opentasks/src/main/res/values/ints.xml +++ b/opentasks/src/main/res/values/ints.xml @@ -1,7 +1,8 @@ - + 2 20 - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/opentasks_defaults.xml b/opentasks/src/main/res/values/opentasks_defaults.xml index 05a7eedbc23b0809515692e1a9325ced914ce108..424e4df8d1c1ca939773a732620ac92394230fab 100644 --- a/opentasks/src/main/res/values/opentasks_defaults.xml +++ b/opentasks/src/main/res/values/opentasks_defaults.xml @@ -1,7 +1,9 @@ - + true - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/prefs.xml b/opentasks/src/main/res/values/prefs.xml index b413e33dc5a318cb1a2950be6b65692ba8df6726..4772f548e3ce93177e6ca05be46ad0f9656a9f4f 100644 --- a/opentasks/src/main/res/values/prefs.xml +++ b/opentasks/src/main/res/values/prefs.xml @@ -2,33 +2,33 @@ opentasks_pref_notification_enabled + translatable="false">opentasks_pref_notification_enabled
opentasks_pref_notification_sound + translatable="false">opentasks_pref_notification_sound opentasks_pref_notification_vibrate + translatable="false">opentasks_pref_notification_vibrate opentasks_pref_notification_lights + translatable="false">opentasks_pref_notification_lights opentasks_pref_list_show_priority + translatable="false">opentasks_pref_list_show_priority opentasks_pref_list_description_lines + translatable="false">opentasks_pref_list_description_lines opentasks_pref_check_list_status + translatable="false">opentasks_pref_check_list_status opentasks_pref_progress_gradient + translatable="false">opentasks_pref_progress_gradient opentasks_pref_system_theme + translatable="false">opentasks_pref_system_theme opentasks_pref_dark_theme + translatable="false">opentasks_pref_dark_theme - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/refs.xml b/opentasks/src/main/res/values/refs.xml index b2529ecc63de08604edbee840e669e66ec59af20..477a0e885eecd7b0c2d9c13072f8a1f2e84c1b74 100644 --- a/opentasks/src/main/res/values/refs.xml +++ b/opentasks/src/main/res/values/refs.xml @@ -1,11 +1,9 @@ - @layout/fragment_visiblelist_list + @layout/fragment_visiblelist_list - @layout/opentasks_layout_tab_icon + @layout/opentasks_layout_tab_icon - \ No newline at end of file + diff --git a/opentasks/src/main/res/values/strings.xml b/opentasks/src/main/res/values/strings.xml index 52ea91f2c94945bb38391d5be7efdb4269e06f80..56cebd9b30761f13e4531e3ccc74bae061d509b4 100644 --- a/opentasks/src/main/res/values/strings.xml +++ b/opentasks/src/main/res/values/strings.xml @@ -67,10 +67,9 @@ Add item - + Item title @@ -187,7 +186,8 @@ Create local list List settings Name - Note: This creates a local list. Tasks in local lists will not be synced. + Note: This creates a local list. Tasks in local + lists will not be synced. List Color @@ -197,7 +197,8 @@ Delete %s - Delete the list and all tasks within?\nNote: There is no way to restore a deleted list. + Delete the list and all tasks within?\nNote: There + is no way to restore a deleted list. %s deleted @@ -260,7 +261,8 @@ %1$s starts - %2$s %1$s starts today Displayed events - Select which events of tasks are displayed in the DashClock widget + Select which events of tasks are displayed in the + DashClock widget Events to display due tasks starting tasks @@ -280,7 +282,8 @@ Notifications - Notification signals + Notification signals Sound @@ -294,17 +297,19 @@ Theme - + Follow system - + - Follow system is experimental and only partially implemented. + Follow system is experimental and only partially + implemented. Dark theme - Dark theme is experimental and only partially implemented. + Dark theme is experimental and only partially + implemented. Task list view @@ -325,13 +330,18 @@ Shared via OpenTasks - Permission needed -
+ Permission needed +
Please note that, due to an unfortunate choice by Google, the permission request will be labeled as "access your contacts" instead of "read your accounts". See Issue 37065963 for further information.]]>
- Continue - Open Settings + Continue + Open Settings - + %1$s, %2$s %1$s, %2$s @@ -352,12 +362,13 @@ Source code Privacy policy Terms of service - An Open Source Task App for Android + An Open Source + Task App for Android Authors - + Open diff --git a/opentasks/src/main/res/values/styles.xml b/opentasks/src/main/res/values/styles.xml index e58f14e0b1104c1cd8e150b686c8cab8c8f9b8e6..1805ca7bed92d8da13271f36eadbb24774b1e910 100644 --- a/opentasks/src/main/res/values/styles.xml +++ b/opentasks/src/main/res/values/styles.xml @@ -1,9 +1,10 @@ - + - @@ -157,7 +159,7 @@ - @@ -199,14 +201,12 @@ 8dp - - - - @@ -264,36 +262,40 @@ - + - - - - - - @@ -335,7 +337,7 @@ - @@ -387,32 +388,31 @@ horizontal - @@ -425,13 +425,12 @@ - - - - - - \ No newline at end of file + diff --git a/opentasks/src/main/res/xml-v29/appearance_preferences.xml b/opentasks/src/main/res/xml-v29/appearance_preferences.xml index c8d0e860e238b1cb9819c73f8bb2bb64045c3e94..05b23672bcc1ad6eae5cd7ca283de10c825c5f7b 100644 --- a/opentasks/src/main/res/xml-v29/appearance_preferences.xml +++ b/opentasks/src/main/res/xml-v29/appearance_preferences.xml @@ -1,45 +1,46 @@ - + - + + android:title="@string/opentasks_preference_system_theme" + android:key="@string/opentasks_pref_appearance_system_theme" + app:disableDependentsState="true" app:isPreferenceVisible="false" + app:summary="@string/opentasks_preference_system_theme_disclaimer" + app:defaultValue="@bool/opentasks_system_theme_default" /> + android:title="@string/opentasks_preference_dark_theme" + android:key="@string/opentasks_pref_appearance_dark_theme" + app:isPreferenceVisible="false" + android:dependency="@string/opentasks_pref_appearance_system_theme" + app:summary="@string/opentasks_preference_dark_theme_disclaimer" + app:defaultValue="@bool/opentasks_dark_theme_default" /> - + + app:title="@string/opentasks_preference_description_preview" + android:summary="@string/opentasks_preference_description_preview_summary" + app:min="0" app:showSeekBarValue="true" + android:max="@integer/opentasks_preferences_description_lines_max" + android:defaultValue="@integer/opentasks_preferences_description_lines_default" + app:key="@string/opentasks_pref_appearance_list_description_lines" /> + app:title="@string/opentasks_preference_show_check_list_summary" + app:key="@string/opentasks_pref_appearance_check_list_summary" + app:defaultValue="@bool/opentasks_list_check_list_summary_default" /> + app:title="@string/opentasks_preference_show_progress_gradient" + app:key="@string/opentasks_pref_appearance_progress_gradient" + app:defaultValue="@bool/opentasks_list_progress_gradient_default" /> + app:title="@string/opentasks_preference_show_priority" + app:defaultValue="true" + app:key="@string/opentasks_pref_appearance_list_show_priority" /> diff --git a/opentasks/src/main/res/xml/about_preferences.xml b/opentasks/src/main/res/xml/about_preferences.xml index c15d1703885096a801bb46ad69dd67e081f4d2a0..25597407f7f18577bd39d69673d767d80c7b4155 100644 --- a/opentasks/src/main/res/xml/about_preferences.xml +++ b/opentasks/src/main/res/xml/about_preferences.xml @@ -1,74 +1,60 @@ - - - - - + + + + - - - - - - - - - + - - + diff --git a/opentasks/src/main/res/xml/app_preferences.xml b/opentasks/src/main/res/xml/app_preferences.xml index d0dbb5202e05e29a8240da490edc462a329e0336..3400d4396552ada35865b94db01dcbb3960e4d1b 100644 --- a/opentasks/src/main/res/xml/app_preferences.xml +++ b/opentasks/src/main/res/xml/app_preferences.xml @@ -1,11 +1,12 @@ - + + app:title="@string/opentasks_settings_notification_enable" + app:key="notifications" + app:fragment="org.dmfs.tasks.AppNotificationSettingsFragment" /> - \ No newline at end of file + app:title="@string/opentasks_preference_appearance" + app:fragment="org.dmfs.tasks.AppAppearanceSettingsFragment" /> + diff --git a/opentasks/src/main/res/xml/appearance_preferences.xml b/opentasks/src/main/res/xml/appearance_preferences.xml index d0616afee6947695e5f0245a92d01faa149757c4..00c77991e25c4cdaf6a816c01c7a500cf2d85c2b 100644 --- a/opentasks/src/main/res/xml/appearance_preferences.xml +++ b/opentasks/src/main/res/xml/appearance_preferences.xml @@ -1,37 +1,39 @@ - + - + + android:title="@string/opentasks_preference_dark_theme" + android:key="@string/opentasks_pref_appearance_dark_theme" + app:isPreferenceVisible="false" + app:defaultValue="@bool/opentasks_dark_theme_default" + app:summary="@string/opentasks_preference_dark_theme_disclaimer" /> - + + app:title="@string/opentasks_preference_description_preview" + android:summary="@string/opentasks_preference_description_preview_summary" + app:min="0" app:showSeekBarValue="true" + android:max="@integer/opentasks_preferences_description_lines_max" + android:defaultValue="@integer/opentasks_preferences_description_lines_default" + app:key="@string/opentasks_pref_appearance_list_description_lines" /> + app:title="@string/opentasks_preference_show_check_list_summary" + app:key="@string/opentasks_pref_appearance_check_list_summary" + app:defaultValue="@bool/opentasks_list_check_list_summary_default" /> + app:title="@string/opentasks_preference_show_progress_gradient" + app:key="@string/opentasks_pref_appearance_progress_gradient" + app:defaultValue="@bool/opentasks_list_progress_gradient_default" /> + app:title="@string/opentasks_preference_show_priority" + app:defaultValue="true" + app:key="@string/opentasks_pref_appearance_list_show_priority" /> diff --git a/opentasks/src/main/res/xml/dashclock_preferences.xml b/opentasks/src/main/res/xml/dashclock_preferences.xml index bdb03d0adc343785453f846d4736a45d905fd5d9..91e4918a94fb146ea05e03dbc2f5b3d8c0f9bf4f 100644 --- a/opentasks/src/main/res/xml/dashclock_preferences.xml +++ b/opentasks/src/main/res/xml/dashclock_preferences.xml @@ -1,13 +1,13 @@ - + - + - \ No newline at end of file + diff --git a/opentasks/src/main/res/xml/listview_tabs.xml b/opentasks/src/main/res/xml/listview_tabs.xml index 4397eeb2771ee0a86bb667f983bf249827ceeff0..d5fdac966418093e47aa113c23fcf898f42cbfe3 100644 --- a/opentasks/src/main/res/xml/listview_tabs.xml +++ b/opentasks/src/main/res/xml/listview_tabs.xml @@ -1,23 +1,18 @@ - - - + + + + icon="@drawable/ic_tab_priority" + title="@string/task_group_priority_title" /> - + icon="@drawable/ic_tab_progress" + title="@string/task_group_progress_title" /> + - \ No newline at end of file + diff --git a/opentasks/src/main/res/xml/notification_preferences.xml b/opentasks/src/main/res/xml/notification_preferences.xml index d4a060f27673eae1130bf81c168f2278bd998ade..02ae2048aac536f0f1d71c2ab72e436cfd3875e4 100644 --- a/opentasks/src/main/res/xml/notification_preferences.xml +++ b/opentasks/src/main/res/xml/notification_preferences.xml @@ -1,32 +1,33 @@ - + + android:key="@string/opentasks_pref_notification_enabled" + android:title="@string/opentasks_settings_notification_enable" + android:defaultValue="true" /> + android:title="@string/opentasks_settings_notification_signals_section_title" + android:dependency="@string/opentasks_pref_notification_enabled"> + android:key="@string/opentasks_pref_notification_sound" + android:title="@string/opentasks_settings_notification_sound" + android:defaultValue="true" /> + android:key="@string/opentasks_pref_notification_vibrate" + android:title="@string/opentasks_settings_notification_vibrate" + android:defaultValue="true" /> + android:key="@string/opentasks_pref_notification_lights" + android:title="@string/opentasks_settings_notification_lights" + android:defaultValue="true" /> - \ No newline at end of file + diff --git a/opentasks/src/main/res/xml/searchable.xml b/opentasks/src/main/res/xml/searchable.xml index c24b90f9c1c72078ae4498c611f2161fffae6bff..58b89939ff31b49538a4fa50247a3a2112d7cc31 100644 --- a/opentasks/src/main/res/xml/searchable.xml +++ b/opentasks/src/main/res/xml/searchable.xml @@ -1,6 +1,7 @@ - + - \ No newline at end of file + diff --git a/opentasks/src/main/res/xml/task_widget_info.xml b/opentasks/src/main/res/xml/task_widget_info.xml index 4bcae6861d53ff8c695379f86a9c329537226527..b2ef12584f530cd582d1123bf4ae25b042ef0146 100644 --- a/opentasks/src/main/res/xml/task_widget_info.xml +++ b/opentasks/src/main/res/xml/task_widget_info.xml @@ -1,11 +1,11 @@ - + - \ No newline at end of file + diff --git a/opentasks/src/main/res/xml/task_widget_info_large.xml b/opentasks/src/main/res/xml/task_widget_info_large.xml index 44c89517129ad4a4af6ac10688d4802a34685e15..21fa5eabe59cdade6c9730a4736d0f75e40bd569 100644 --- a/opentasks/src/main/res/xml/task_widget_info_large.xml +++ b/opentasks/src/main/res/xml/task_widget_info_large.xml @@ -1,11 +1,10 @@ - + - \ No newline at end of file + diff --git a/opentasks/src/test/java/org/dmfs/tasks/model/adapters/DescriptionExtractingTest.java b/opentasks/src/test/java/org/dmfs/tasks/model/adapters/DescriptionExtractingTest.java index a670046898f97e355085eadd1bd933d158c81971..fc1905697ab2b25188f97c9ad3e7486b03108f9c 100644 --- a/opentasks/src/test/java/org/dmfs/tasks/model/adapters/DescriptionExtractingTest.java +++ b/opentasks/src/test/java/org/dmfs/tasks/model/adapters/DescriptionExtractingTest.java @@ -16,23 +16,21 @@ package org.dmfs.tasks.model.adapters; -import org.junit.Test; - import static junit.framework.Assert.assertEquals; import static org.dmfs.tasks.model.adapters.DescriptionStringFieldAdapter.extractDescription; +import org.junit.Test; /** - * Test for the description extraction from the combined description-checklist string. + * Test for the description extraction from the combined description-checklist + * string. * * @author Gabor Keszthelyi */ -public class DescriptionExtractingTest -{ +public class DescriptionExtractingTest { @Test - public void testExtractDescription() - { + public void testExtractDescription() { // No checklist assertEquals("desc", extractDescription("desc")); assertEquals("desc ", extractDescription("desc ")); @@ -87,12 +85,9 @@ public class DescriptionExtractingTest assertEquals("desc", extractDescription("desc\n[x] item1\n[] item2")); } - @Test - public void testExtractDescription_CR_removal() - { + public void testExtractDescription_CR_removal() { assertEquals("desc", extractDescription("desc\r\n[x] item")); assertEquals("desc ", extractDescription("desc \r\n[] item")); } - -} \ No newline at end of file +} diff --git a/opentasks/src/test/java/org/dmfs/tasks/notification/signals/ToggledTest.java b/opentasks/src/test/java/org/dmfs/tasks/notification/signals/ToggledTest.java index 68467b7867c91f8d29a1da0378b4fc66559cfd6d..bebc2ecbd238b4cff3a87b279ef20909b517615f 100644 --- a/opentasks/src/test/java/org/dmfs/tasks/notification/signals/ToggledTest.java +++ b/opentasks/src/test/java/org/dmfs/tasks/notification/signals/ToggledTest.java @@ -16,41 +16,34 @@ package org.dmfs.tasks.notification.signals; -import android.app.Notification; - -import org.junit.Test; - import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import android.app.Notification; +import org.junit.Test; /** * Unit test for {@link Toggled}. * * @author Gabor Keszthelyi */ -public final class ToggledTest -{ +public final class ToggledTest { @Test - public void testValidFlags_dontThrowException() - { + public void testValidFlags_dontThrowException() { new Toggled(Notification.DEFAULT_SOUND, true, new NoSignal()).value(); new Toggled(Notification.DEFAULT_VIBRATE, true, new NoSignal()).value(); new Toggled(Notification.DEFAULT_LIGHTS, true, new NoSignal()).value(); } - @Test(expected = IllegalArgumentException.class) - public void testInValidFlag_throwsException() - { + public void testInValidFlag_throwsException() { new Toggled(15, true, new NoSignal()).value(); } - @Test - public void testAddingFlag() - { - assertThat(new Toggled(Notification.DEFAULT_SOUND, true, new NoSignal()).value(), is(new NoSignal().value() | Notification.DEFAULT_SOUND)); + public void testAddingFlag() { + assertThat(new Toggled(Notification.DEFAULT_SOUND, true, new NoSignal()).value(), + is(new NoSignal().value() | Notification.DEFAULT_SOUND)); assertThat(new Toggled(Notification.DEFAULT_SOUND, false, new NoSignal()).value(), is(new NoSignal().value())); } } diff --git a/opentasks/src/test/java/org/dmfs/tasks/utils/RecentlyUsedListsNullHandlingTest.java b/opentasks/src/test/java/org/dmfs/tasks/utils/RecentlyUsedListsNullHandlingTest.java index 1dcb98bc92b4bd1f0eee689e8793f8c56c90388b..ef193dfaada864d81c53d8d6cb0b7827d3450c6a 100644 --- a/opentasks/src/test/java/org/dmfs/tasks/utils/RecentlyUsedListsNullHandlingTest.java +++ b/opentasks/src/test/java/org/dmfs/tasks/utils/RecentlyUsedListsNullHandlingTest.java @@ -16,56 +16,56 @@ package org.dmfs.tasks.utils; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + import android.app.Application; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; - +import java.util.ArrayList; +import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; -import java.util.ArrayList; -import java.util.List; - -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - - /** - * This test is for checking that the bug 562, which was caused by storing a "null" string in the - * recently used list prefs string, like "null,3,2", is fixed correctly as far as {@link RecentlyUsedLists} is concerned. Calling {@link - * RecentlyUsedLists#use(Context, long)} with null list id will still cause a NPE crash, but this fix will help to track down the original problem - * if it happens again. It also checks that {@link RecentlyUsedLists} removes the "null" so we can possibly remove the code handling that later. + * This test is for checking that the bug + * 562, which was + * caused by storing a "null" string in the recently used list prefs string, + * like "null,3,2", is fixed correctly as far as {@link RecentlyUsedLists} is + * concerned. Calling {@link RecentlyUsedLists#use(Context, long)} with + * null list id will still cause a NPE crash, but this fix will + * help to track down the original problem if it happens again. It also checks + * that {@link RecentlyUsedLists} removes the "null" so we can possibly remove + * the code handling that later. * * @author Gabor Keszthelyi */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class RecentlyUsedListsNullHandlingTest -{ +public class RecentlyUsedListsNullHandlingTest { private static final String PREFERENCE_KEY = "RecentlyUsedLists"; - /** - * That that the {@link RecentlyUsedLists#use(Context, long)} method cannot be called with null value. + * That that the {@link RecentlyUsedLists#use(Context, long)} method cannot be + * called with + * null value. */ @Test(expected = NullPointerException.class) - public void test_use_cannot_be_called_with_null_listId() - { + public void test_use_cannot_be_called_with_null_listId() { Long listId = null; RecentlyUsedLists.use(RuntimeEnvironment.application, listId); } - /** - * Test that even if "null" string had been stored incorrectly previously, it doesn't affect the usage. + * Test that even if "null" string had been stored incorrectly previously, it + * doesn't affect the usage. */ @Test - public void test_getRecentFromList_that_the_stored_null_string_is_ignored() - { + public void test_getRecentFromList_that_the_stored_null_string_is_ignored() { Application context = RuntimeEnvironment.application; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); @@ -85,16 +85,16 @@ public class RecentlyUsedListsNullHandlingTest assertThat(RecentlyUsedLists.getRecentFromList(context, allowedList), is(2L)); } - /** - * Test that if "null" string had been stored incorrectly previously, it is cleared on the first time usage of {@link - * RecentlyUsedLists#getRecentFromList(Context, List)}. + * Test that if "null" string had been stored incorrectly previously, it is + * cleared on the first time usage of + * {@link RecentlyUsedLists#getRecentFromList(Context, List)}. + * *

* This is to ensure that we can remove the "null" handling fix later. */ @Test - public void test_getRecentFromList_that_the_stored_null_string_is_removed() - { + public void test_getRecentFromList_that_the_stored_null_string_is_removed() { Application context = RuntimeEnvironment.application; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); @@ -114,16 +114,16 @@ public class RecentlyUsedListsNullHandlingTest assertThat(prefs.getString(PREFERENCE_KEY, "na"), is("")); } - /** - * Test that if "null" string had been stored incorrectly previously, it is cleared on the first time usage of {@link - * RecentlyUsedLists#use(Context, long)}. + * Test that if "null" string had been stored incorrectly previously, it is + * cleared on the first time usage of + * {@link RecentlyUsedLists#use(Context, long)}. + * *

* This is to ensure that we can remove the "null" handling fix later. */ @Test - public void test_use_that_the_stored_null_string_is_removed() - { + public void test_use_that_the_stored_null_string_is_removed() { Application context = RuntimeEnvironment.application; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); @@ -140,26 +140,24 @@ public class RecentlyUsedListsNullHandlingTest assertThat(prefs.getString(PREFERENCE_KEY, "na"), is("3")); } - /** - * Test that null is not allowed in the allowedList {@link List} either. + * Test that null is not allowed in the allowedList + * {@link List} either. */ @Test(expected = IllegalArgumentException.class) - public void test_getRecentFromList_null_is_not_allowed_in_allowed_strings() - { + public void test_getRecentFromList_null_is_not_allowed_in_allowed_strings() { List allowedList = new ArrayList<>(); allowedList.add(null); allowedList.add(1L); RecentlyUsedLists.getRecentFromList(RuntimeEnvironment.application, allowedList); } - /** - * Test that no value / empty value / null value stored in prefs is still handled correctly after the changes. + * Test that no value / empty value / null value stored in prefs is still + * handled correctly after the changes. */ @Test - public void test_getRecentFromList_empty_or_null_prefs_value_still_works() - { + public void test_getRecentFromList_empty_or_null_prefs_value_still_works() { Application context = RuntimeEnvironment.application; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); @@ -174,5 +172,4 @@ public class RecentlyUsedListsNullHandlingTest prefs.edit().putString(PREFERENCE_KEY, "").apply(); assertThat(RecentlyUsedLists.getRecentFromList(context, allowedList), is(5L)); } - -} \ No newline at end of file +} diff --git a/opentasks/src/test/java/org/dmfs/tasks/utils/ValidatingUriTest.java b/opentasks/src/test/java/org/dmfs/tasks/utils/ValidatingUriTest.java index 6ef039a1d0c204ebcd82eaf3ccd7b9f8a6d374aa..ada82440fd0812ceb13c25c757dcdcc6010dcf16 100644 --- a/opentasks/src/test/java/org/dmfs/tasks/utils/ValidatingUriTest.java +++ b/opentasks/src/test/java/org/dmfs/tasks/utils/ValidatingUriTest.java @@ -16,20 +16,17 @@ package org.dmfs.tasks.utils; -import android.net.Uri; +import static org.dmfs.jems.hamcrest.matchers.BrokenFragileMatcher.isBroken; +import static org.dmfs.jems.hamcrest.matchers.IntactFragileMatcher.isIntact; +import static org.junit.Assert.assertThat; +import android.net.Uri; +import java.net.URISyntaxException; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import java.net.URISyntaxException; - -import static org.dmfs.jems.hamcrest.matchers.BrokenFragileMatcher.isBroken; -import static org.dmfs.jems.hamcrest.matchers.IntactFragileMatcher.isIntact; -import static org.junit.Assert.assertThat; - - /** * Unit test for {@link ValidatingUri}. * @@ -37,25 +34,20 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public final class ValidatingUriTest -{ +public final class ValidatingUriTest { @Test - public void testValidVariations() - { + public void testValidVariations() { assertThat(new ValidatingUri("http://abc.com"), isIntact(Uri.parse("http://abc.com"))); assertThat(new ValidatingUri("https://abc.com/path"), isIntact(Uri.parse("https://abc.com/path"))); assertThat(new ValidatingUri("tel:1234"), isIntact(Uri.parse("tel:1234"))); assertThat(new ValidatingUri("mailto:example@abc.com"), isIntact((Uri.parse("mailto:example@abc.com")))); } - @Test - public void testInValidVariations() - { + public void testInValidVariations() { assertThat(new ValidatingUri(null), isBroken(URISyntaxException.class)); assertThat(new ValidatingUri(""), isBroken(URISyntaxException.class)); assertThat(new ValidatingUri("h h"), isBroken(URISyntaxException.class)); } - -} \ No newline at end of file +} diff --git a/opentaskspal/build.gradle b/opentaskspal/build.gradle index c9261579e585b44b35d9c5140fe3e9f32bf69c06..fc938303b145afca978be0eb43d9b1bb5ea6c23c 100644 --- a/opentaskspal/build.gradle +++ b/opentaskspal/build.gradle @@ -10,10 +10,12 @@ android { minSdkVersion 21 targetSdkVersion 36 } + packagingOptions { exclude 'META-INF/NOTICE' exclude 'META-INF/LICENSE' } + compileOptions { sourceCompatibility JavaVersion.VERSION_21 targetCompatibility JavaVersion.VERSION_21 diff --git a/opentaskspal/src/main/AndroidManifest.xml b/opentaskspal/src/main/AndroidManifest.xml index 991848ef32958325526e5071c32adbf0394c2486..cc9c9f9f0ab9f59f3eadc8e2eb5b5625b07d1914 100644 --- a/opentaskspal/src/main/AndroidManifest.xml +++ b/opentaskspal/src/main/AndroidManifest.xml @@ -1,9 +1,10 @@ + package="org.dmfs.opentaskspal"> - - + + - + diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/operations/SubtaskRelation.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/operations/SubtaskRelation.java index 8df920a74f9e828f6423cc379e9db4d9ff78004b..5b59552f8f4642c8ac5095dc063375e263d96cb4 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/operations/SubtaskRelation.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/operations/SubtaskRelation.java @@ -18,7 +18,6 @@ package org.dmfs.opentaskspal.operations; import android.content.ContentProviderOperation; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.InsertOperation; import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.RowSnapshot; @@ -30,36 +29,31 @@ import org.dmfs.opentaskspal.tables.PropertiesTable; import org.dmfs.opentaskspal.tasks.ParentTaskRelationData; import org.dmfs.tasks.contract.TaskContract; - /** - * {@link InsertOperation} for adding a 'subtask relation' property to {@link TaskContract.Properties} table. + * {@link InsertOperation} for adding a 'subtask relation' property to + * {@link TaskContract.Properties} table. * * @author Gabor Keszthelyi */ -public final class SubtaskRelation implements InsertOperation -{ +public final class SubtaskRelation implements InsertOperation { private final Operation mDelegate; - - public SubtaskRelation(String authority, RowSnapshot subtask, RowSnapshot parentTask) - { + public SubtaskRelation(String authority, RowSnapshot subtask, + RowSnapshot parentTask) { mDelegate = new Insert<>(new PropertiesTable(authority), new ParentTaskRelationData(parentTask, subtask)); } - @NonNull @Override - public Optional> reference() - { + public Optional> reference() { return mDelegate.reference(); } - @NonNull @Override - public ContentProviderOperation.Builder contentOperationBuilder(@NonNull TransactionContext transactionContext) throws UnsupportedOperationException - { + public ContentProviderOperation.Builder contentOperationBuilder(@NonNull TransactionContext transactionContext) + throws UnsupportedOperationException { return mDelegate.contentOperationBuilder(transactionContext); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/operations/TaskListTask.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/operations/TaskListTask.java index 9bb419d9c016f517d69285bba1c024152bfefb1d..e23ca8b9e8c333b6a050531136453c53339fcf3f 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/operations/TaskListTask.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/operations/TaskListTask.java @@ -18,7 +18,6 @@ package org.dmfs.opentaskspal.operations; import android.content.ContentProviderOperation; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.InsertOperation; import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.RowSnapshot; @@ -28,35 +27,29 @@ import org.dmfs.android.contentpal.operations.Referring; import org.dmfs.jems.optional.Optional; import org.dmfs.tasks.contract.TaskContract; - /** * {@link InsertOperation} decorator which relates a new task to a task list. * * @author Gabor Keszthelyi */ -public final class TaskListTask implements InsertOperation -{ +public final class TaskListTask implements InsertOperation { private final Operation mDelegate; - - public TaskListTask(@NonNull RowSnapshot taskList, @NonNull InsertOperation original) - { + public TaskListTask(@NonNull RowSnapshot taskList, + @NonNull InsertOperation original) { mDelegate = new Referring<>(taskList, TaskContract.Tasks.LIST_ID, original); } - @NonNull @Override - public Optional> reference() - { + public Optional> reference() { return mDelegate.reference(); } - @NonNull @Override - public ContentProviderOperation.Builder contentOperationBuilder(@NonNull TransactionContext transactionContext) throws UnsupportedOperationException - { + public ContentProviderOperation.Builder contentOperationBuilder(@NonNull TransactionContext transactionContext) + throws UnsupportedOperationException { return mDelegate.contentOperationBuilder(transactionContext); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/IsProperty.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/IsProperty.java index 514327237b0258496cf479dad039680da4b52e5d..40db0d203c763e59b24c5fd3c183a79a25a64208 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/IsProperty.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/IsProperty.java @@ -21,16 +21,14 @@ import org.dmfs.android.contentpal.predicates.DelegatingPredicate; import org.dmfs.android.contentpal.predicates.EqArg; import org.dmfs.tasks.contract.TaskContract; - /** - * {@link Predicate} for selecting rows from {@link TaskContract.Properties} table representing a certain property identified by its mimeType. + * {@link Predicate} for selecting rows from {@link TaskContract.Properties} + * table representing a certain property identified by its mimeType. * * @author Gabor Keszthelyi */ -public final class IsProperty extends DelegatingPredicate -{ - public IsProperty(String mimeType) - { +public final class IsProperty extends DelegatingPredicate { + public IsProperty(String mimeType) { super(new EqArg<>(TaskContract.PropertyColumns.MIMETYPE, mimeType)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/IsRelation.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/IsRelation.java index e8bf9c9673a8364b6362a581c1e249572b701eb2..c0546499835da3c82624ca07217b31ae9b36e109 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/IsRelation.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/IsRelation.java @@ -20,16 +20,14 @@ import org.dmfs.android.contentpal.Predicate; import org.dmfs.android.contentpal.predicates.DelegatingPredicate; import org.dmfs.tasks.contract.TaskContract; - /** - * {@link Predicate} for selecting {@link TaskContract.Property.Relation} properties from {@link TaskContract.Properties} table. + * {@link Predicate} for selecting {@link TaskContract.Property.Relation} + * properties from {@link TaskContract.Properties} table. * * @author Gabor Keszthelyi */ -public final class IsRelation extends DelegatingPredicate -{ - public IsRelation() - { +public final class IsRelation extends DelegatingPredicate { + public IsRelation() { super(new IsProperty(TaskContract.Property.Relation.CONTENT_ITEM_TYPE)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/TaskOnList.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/TaskOnList.java index bd758ee620468b6a7738375f263609a9bdd73f26..68b7cbab9b9cae5321b75a8628f1f6b087534f12 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/TaskOnList.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/predicates/TaskOnList.java @@ -23,17 +23,15 @@ import org.dmfs.android.contentpal.predicates.DelegatingPredicate; import org.dmfs.android.contentpal.predicates.ReferringTo; import org.dmfs.tasks.contract.TaskContract; - /** - * {@link Predicate} decorator that adds selection for tasks having the task list referred to by the given {@link RowSnapshot}. + * {@link Predicate} decorator that adds selection for tasks having the task + * list referred to by the given {@link RowSnapshot}. * * @author Gabor Keszthelyi */ -public final class TaskOnList extends DelegatingPredicate -{ - public TaskOnList(RowSnapshot taskListRow, Predicate predicate) - { +public final class TaskOnList extends DelegatingPredicate { + public TaskOnList(RowSnapshot taskListRow, + Predicate predicate) { super(new AllOf<>(predicate, new ReferringTo<>(TaskContract.Tasks.LIST_ID, taskListRow))); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveDueDate.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveDueDate.java index 50441ffd7c0f7976a8654caf5e28abc8281a31e6..7126d6db888601b74bcac1e49c3608cfd094b570 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveDueDate.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveDueDate.java @@ -16,6 +16,7 @@ package org.dmfs.opentaskspal.readdata; +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.Composite; @@ -29,31 +30,20 @@ import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; -import androidx.annotation.NonNull; - - /** - * {@link Optional} representing the effective due date of a task. It's either taken directly from the due value (if present) or from start + duration (if both - * are present). + * {@link Optional} representing the effective due date of a task. It's either + * taken directly from the due value (if present) or from start + duration (if + * both are present). * * @author Marten Gajda */ -public final class EffectiveDueDate extends DelegatingOptional -{ +public final class EffectiveDueDate extends DelegatingOptional { public static final Projection PROJECTION = new Composite<>( - new MultiProjection<>(Tasks.DUE, Tasks.DTSTART), - TaskDateTime.PROJECTION, - TaskDuration.PROJECTION); - + new MultiProjection<>(Tasks.DUE, Tasks.DTSTART), TaskDateTime.PROJECTION, TaskDuration.PROJECTION); - public EffectiveDueDate(@NonNull RowDataSnapshot rowDataSnapshot) - { - super(new FirstPresent<>( - new Seq<>( - new TaskDateTime(Tasks.DUE, rowDataSnapshot), - new Zipped<>( - new TaskDateTime(Tasks.DTSTART, rowDataSnapshot), - new TaskDuration(rowDataSnapshot), - DateTime::addDuration)))); + public EffectiveDueDate(@NonNull RowDataSnapshot rowDataSnapshot) { + super(new FirstPresent<>(new Seq<>(new TaskDateTime(Tasks.DUE, rowDataSnapshot), + new Zipped<>(new TaskDateTime(Tasks.DTSTART, rowDataSnapshot), new TaskDuration(rowDataSnapshot), + DateTime::addDuration)))); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveTaskColor.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveTaskColor.java index cc153d3771ff4b0d35d7de69eb69880ec7d29f0b..200fbd0a72009f374f57010b9c0a70c26f38cd22 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveTaskColor.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveTaskColor.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.bolts.color.Color; import org.dmfs.android.bolts.color.elementary.DelegatingColor; import org.dmfs.android.bolts.color.elementary.SingleColor; @@ -29,25 +28,18 @@ import org.dmfs.opentaskspal.readdata.functions.StringToColor; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** - * {@link Color} for a task. Uses {@link Tasks#TASK_COLOR} if available, - * fall backs to the mandatory {@link Tasks#LIST_COLOR} otherwise. + * {@link Color} for a task. Uses {@link Tasks#TASK_COLOR} if available, fall + * backs to the mandatory {@link Tasks#LIST_COLOR} otherwise. * * @author Gabor Keszthelyi */ -public final class EffectiveTaskColor extends DelegatingColor -{ - public static final Projection PROJECTION = new MultiProjection<>(Tasks.TASK_COLOR, Tasks.LIST_COLOR); +public final class EffectiveTaskColor extends DelegatingColor { + public static final Projection PROJECTION = new MultiProjection<>( + Tasks.TASK_COLOR, Tasks.LIST_COLOR); - - public EffectiveTaskColor(@NonNull RowDataSnapshot rowData) - { - super(new SingleColor( - new Backed( - rowData.data(Tasks.TASK_COLOR, StringToColor.FUNCTION), - () -> rowData.data(Tasks.LIST_COLOR, StringToColor.FUNCTION).value() - ))); + public EffectiveTaskColor(@NonNull RowDataSnapshot rowData) { + super(new SingleColor(new Backed(rowData.data(Tasks.TASK_COLOR, StringToColor.FUNCTION), + () -> rowData.data(Tasks.LIST_COLOR, StringToColor.FUNCTION).value()))); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveTimezone.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveTimezone.java index 2299bc595c692e692bce6c1531665103a9cb330a..c85e32dd1ba27aa66ddd88c93ae1c41faaf9321d 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveTimezone.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/EffectiveTimezone.java @@ -17,7 +17,7 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - +import java.util.TimeZone; import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.SingleColProjection; @@ -27,23 +27,17 @@ import org.dmfs.jems.single.elementary.ValueSingle; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; -import java.util.TimeZone; - - /** - * The {@link Single} effective {@link TimeZone} of a task. If the task has no TimeZone, i.e. is floating, this will return the local {@link TimeZone}. + * The {@link Single} effective {@link TimeZone} of a task. If the task has no + * TimeZone, i.e. is floating, this will return the local {@link TimeZone}. * * @author Marten Gajda * @author Gabor Keszthelyi */ -public final class EffectiveTimezone extends DelegatingSingle -{ +public final class EffectiveTimezone extends DelegatingSingle { public static final Projection PROJECTION = new SingleColProjection<>(Tasks.TZ); - - public EffectiveTimezone(@NonNull RowDataSnapshot rowData) - { + public EffectiveTimezone(@NonNull RowDataSnapshot rowData) { super(new ValueSingle<>(rowData.data(Tasks.TZ, TimeZone::getTimeZone).value())); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/Id.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/Id.java index 85a5c4e6921f5358b302b8b81ad56729d820f7a3..c0b05163886b27f65570299f1fd2f064ee75a2ea 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/Id.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/Id.java @@ -17,7 +17,7 @@ package org.dmfs.opentaskspal.readdata; import android.provider.BaseColumns; - +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.SingleColProjection; @@ -25,22 +25,15 @@ import org.dmfs.jems.single.Single; import org.dmfs.jems.single.decorators.DelegatingSingle; import org.dmfs.jems.single.elementary.ValueSingle; -import androidx.annotation.NonNull; - - /** * {@link Single} for the id ({@link BaseColumns#_ID} of a row. * * @author Gabor Keszthelyi */ -public final class Id extends DelegatingSingle -{ +public final class Id extends DelegatingSingle { public static final Projection PROJECTION = new SingleColProjection<>(BaseColumns._ID); - - public Id(@NonNull RowDataSnapshot rowDataSnapshot) - { + public Id(@NonNull RowDataSnapshot rowDataSnapshot) { super(new ValueSingle<>(rowDataSnapshot.data(BaseColumns._ID, Long::valueOf).value())); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/PercentComplete.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/PercentComplete.java index c6be1960bf52aa9dc947bda0982e9a3d68e48850..555571fbfb94b4fdbefdaf24998477021fe68be3 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/PercentComplete.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/PercentComplete.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.SingleColProjection; @@ -26,19 +25,16 @@ import org.dmfs.jems.optional.decorators.DelegatingOptional; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * {@link Optional} for the {@link Tasks#PERCENT_COMPLETE} value of a task. * * @author Gabor Keszthelyi */ -public final class PercentComplete extends DelegatingOptional -{ - public static final Projection PROJECTION = new SingleColProjection<>(Tasks.PERCENT_COMPLETE); - +public final class PercentComplete extends DelegatingOptional { + public static final Projection PROJECTION = new SingleColProjection<>( + Tasks.PERCENT_COMPLETE); - public PercentComplete(@NonNull RowDataSnapshot rowData) - { + public PercentComplete(@NonNull RowDataSnapshot rowData) { super(rowData.data(Tasks.PERCENT_COMPLETE, Integer::valueOf)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskCompletionTime.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskCompletionTime.java index 4cda815c0765b63ff9adbf23cbe316f4eb9a8420..45613b62b901b020fa946a08fb0fc5cd5aa532ba 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskCompletionTime.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskCompletionTime.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.Composite; @@ -29,23 +28,17 @@ import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * An {@link Optional} of completion {@link DateTime} of a task. * * @author Marten Gajda */ -public final class TaskCompletionTime extends DelegatingOptional -{ +public final class TaskCompletionTime extends DelegatingOptional { public static final Projection PROJECTION = new Composite<>( - new SingleColProjection<>(Tasks.COMPLETED), - EffectiveTimezone.PROJECTION); - + new SingleColProjection<>(Tasks.COMPLETED), EffectiveTimezone.PROJECTION); - public TaskCompletionTime(@NonNull final RowDataSnapshot rowData) - { - super(new Mapped<>( - timeStamp -> new DateTime(timeStamp).shiftTimeZone(new EffectiveTimezone(rowData).value()), + public TaskCompletionTime(@NonNull final RowDataSnapshot rowData) { + super(new Mapped<>(timeStamp -> new DateTime(timeStamp).shiftTimeZone(new EffectiveTimezone(rowData).value()), rowData.data(Tasks.COMPLETED, Long::valueOf))); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskDateTime.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskDateTime.java index 713439c52719f22cab34f571750d2178e07c7092..fa7510443abce8f7b867b182808b2eb5c22a1176 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskDateTime.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskDateTime.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.Composite; @@ -30,26 +29,23 @@ import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * An {@link Optional} of a specific {@link DateTime} value of a task. * * @author Marten Gajda * @author Gabor Keszthelyi */ -public final class TaskDateTime extends DelegatingOptional -{ +public final class TaskDateTime extends DelegatingOptional { public static final Projection PROJECTION = new Composite<>( new MultiProjection<>(Tasks.DTSTART, Tasks.DUE, Tasks.COMPLETED, Tasks.IS_ALLDAY), EffectiveTimezone.PROJECTION); - - public TaskDateTime(@NonNull String columnName, @NonNull final RowDataSnapshot rowData) - { + public TaskDateTime(@NonNull String columnName, + @NonNull final RowDataSnapshot rowData) { super(new Mapped<>( - (Long timeStamp) -> new Backed<>(rowData.data(Tasks.IS_ALLDAY, "1"::equals), false).value() ? - new DateTime(timeStamp).toAllDay() : - new DateTime(timeStamp).shiftTimeZone(new EffectiveTimezone(rowData).value()), + (Long timeStamp) -> new Backed<>(rowData.data(Tasks.IS_ALLDAY, "1"::equals), false).value() + ? new DateTime(timeStamp).toAllDay() + : new DateTime(timeStamp).shiftTimeZone(new EffectiveTimezone(rowData).value()), rowData.data(columnName, Long::valueOf))); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskDuration.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskDuration.java index 97a66597c0b53aaec2ce20db47850f6e385f1d67..c16b34a97b48d11816c57a7a7a7fac888115696f 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskDuration.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskDuration.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.SingleColProjection; @@ -27,19 +26,16 @@ import org.dmfs.rfc5545.Duration; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * The {@link Optional} {@link Duration} of a task {@link RowDataSnapshot}. * * @author Marten Gajda */ -public final class TaskDuration extends DelegatingOptional -{ - public static final Projection PROJECTION = new SingleColProjection<>(Tasks.DURATION); - +public final class TaskDuration extends DelegatingOptional { + public static final Projection PROJECTION = new SingleColProjection<>( + Tasks.DURATION); - public TaskDuration(@NonNull RowDataSnapshot rowData) - { + public TaskDuration(@NonNull RowDataSnapshot rowData) { super(rowData.data(Tasks.DURATION, Duration::parse)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskIsClosed.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskIsClosed.java index 96ecb660557bed98d351dbed810ef2f9735a87d6..296287156c951ba5ccceba2faab6b32697b99a67 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskIsClosed.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskIsClosed.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.SingleColProjection; @@ -27,19 +26,16 @@ import org.dmfs.jems.single.decorators.DelegatingSingle; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * {@link Single} for the {@link Tasks#IS_CLOSED} value of a task. * * @author Marten Gajda */ -public final class TaskIsClosed extends DelegatingSingle -{ - public static final Projection PROJECTION = new SingleColProjection<>(Tasks.IS_CLOSED); - +public final class TaskIsClosed extends DelegatingSingle { + public static final Projection PROJECTION = new SingleColProjection<>( + Tasks.IS_CLOSED); - public TaskIsClosed(@NonNull RowDataSnapshot rowDataSnapshot) - { + public TaskIsClosed(@NonNull RowDataSnapshot rowDataSnapshot) { super(new Backed<>(rowDataSnapshot.data(Tasks.IS_CLOSED, "1"::equals), false)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskPin.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskPin.java index 34c7fc5a1a41397163c93e5424d2c6985a325193..b4cb1da401b872a24b5efa81bf4cdaa6740943de 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskPin.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskPin.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.SingleColProjection; @@ -27,19 +26,16 @@ import org.dmfs.jems.single.decorators.DelegatingSingle; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * {@link Single} for the {@link Tasks#PINNED} value of a task. * * @author Marten Gajda */ -public final class TaskPin extends DelegatingSingle -{ - public static final Projection PROJECTION = new SingleColProjection<>(Tasks.PINNED); - +public final class TaskPin extends DelegatingSingle { + public static final Projection PROJECTION = new SingleColProjection<>( + Tasks.PINNED); - public TaskPin(@NonNull RowDataSnapshot rowDataSnapshot) - { + public TaskPin(@NonNull RowDataSnapshot rowDataSnapshot) { super(new Backed(rowDataSnapshot.data(Tasks.PINNED, "1"::equals), false)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskStart.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskStart.java index 3919239b6987e526b631424cfd5975c9c9bce8ea..64008c75dac64ca41f59a567271b9bfad118ffb5 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskStart.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskStart.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.Composite; @@ -28,20 +27,16 @@ import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * {@link Optional} representing the start date of a task, if present. * * @author Marten Gajda */ -public final class TaskStart extends DelegatingOptional -{ - public static final Projection PROJECTION = - new Composite<>(new SingleColProjection<>(Tasks.DTSTART), TaskDateTime.PROJECTION); - +public final class TaskStart extends DelegatingOptional { + public static final Projection PROJECTION = new Composite<>( + new SingleColProjection<>(Tasks.DTSTART), TaskDateTime.PROJECTION); - public TaskStart(@NonNull RowDataSnapshot rowDataSnapshot) - { + public TaskStart(@NonNull RowDataSnapshot rowDataSnapshot) { super(new TaskDateTime(Tasks.DTSTART, rowDataSnapshot)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskStatus.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskStatus.java index 41b5f69a660caf2b68eb7fa5a45f87d36f5beb0d..dd9182d54d31a2e43439712a5700b2368d0b9a5b 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskStatus.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskStatus.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.SingleColProjection; @@ -27,19 +26,16 @@ import org.dmfs.jems.single.decorators.DelegatingSingle; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * {@link Single} for the {@link Tasks#STATUS} value of a task. * * @author Marten Gajda */ -public final class TaskStatus extends DelegatingSingle -{ - public static final Projection PROJECTION = new SingleColProjection<>(Tasks.STATUS); - +public final class TaskStatus extends DelegatingSingle { + public static final Projection PROJECTION = new SingleColProjection<>( + Tasks.STATUS); - public TaskStatus(@NonNull RowDataSnapshot rowDataSnapshot) - { + public TaskStatus(@NonNull RowDataSnapshot rowDataSnapshot) { super(new Backed<>(rowDataSnapshot.data(Tasks.STATUS, Integer::parseInt), Tasks.STATUS_DEFAULT)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskTitle.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskTitle.java index dce43729b7017fa0a3a72de2be3b3027bf581e7e..c89253f2b416624c9b1b5c61079118b40ae538f2 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskTitle.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskTitle.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.SingleColProjection; @@ -26,19 +25,16 @@ import org.dmfs.jems.optional.decorators.DelegatingOptional; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * {@link Optional} for the title value of a task. * * @author Gabor Keszthelyi */ -public final class TaskTitle extends DelegatingOptional -{ - public static final Projection PROJECTION = new SingleColProjection<>(Tasks.TITLE); - +public final class TaskTitle extends DelegatingOptional { + public static final Projection PROJECTION = new SingleColProjection<>( + Tasks.TITLE); - public TaskTitle(@NonNull RowDataSnapshot rowDataSnapshot) - { + public TaskTitle(@NonNull RowDataSnapshot rowDataSnapshot) { super(rowDataSnapshot.data(Tasks.TITLE, s -> s)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskUri.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskUri.java index 84ecb209cdd3847a892db9cdc5f220e567af54cc..2c7ee3e7619a40c52db7bb971b0eb7675b3150c1 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskUri.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskUri.java @@ -19,39 +19,33 @@ package org.dmfs.opentaskspal.readdata; import android.content.ContentUris; import android.net.Uri; import android.provider.BaseColumns; - +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.jems.single.Single; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; -import androidx.annotation.NonNull; - - /** - * {@link Single} for the content {@link Uri} that refers to the given {@link RowDataSnapshot}. + * {@link Single} for the content {@link Uri} that refers to the given + * {@link RowDataSnapshot}. * * @author Gabor Keszthelyi */ -public final class TaskUri implements Single -{ +public final class TaskUri implements Single { public static final Projection PROJECTION = Id.PROJECTION; private final RowDataSnapshot mRowDataSnapshot; private final String mAuthority; - - public TaskUri(@NonNull String authority, @NonNull RowDataSnapshot rowDataSnapshot) - { + public TaskUri(@NonNull String authority, + @NonNull RowDataSnapshot rowDataSnapshot) { mAuthority = authority; mRowDataSnapshot = rowDataSnapshot; } - @Override - public Uri value() - { + public Uri value() { // TODO: use the instance URI one we support recurrence return ContentUris.withAppendedId(Tasks.getContentUri(mAuthority), new Id(mRowDataSnapshot).value()); } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskVersion.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskVersion.java index 59ac835c334b3e72ae4f4988a4e11d92f19f215d..72107c8c3b4dcdbe7cf5920491a78e43ae535e8c 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskVersion.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/TaskVersion.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.readdata; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowDataSnapshot; import org.dmfs.android.contentpal.projections.SingleColProjection; @@ -27,19 +26,16 @@ import org.dmfs.jems.single.decorators.DelegatingSingle; import org.dmfs.tasks.contract.TaskContract; import org.dmfs.tasks.contract.TaskContract.Tasks; - /** * {@link Single} for the {@link Tasks#VERSION} value of a task. * * @author Marten Gajda */ -public final class TaskVersion extends DelegatingSingle -{ - public static final Projection PROJECTION = new SingleColProjection<>(Tasks.VERSION); - +public final class TaskVersion extends DelegatingSingle { + public static final Projection PROJECTION = new SingleColProjection<>( + Tasks.VERSION); - public TaskVersion(@NonNull RowDataSnapshot rowDataSnapshot) - { + public TaskVersion(@NonNull RowDataSnapshot rowDataSnapshot) { super(new Backed<>(rowDataSnapshot.data(Tasks.VERSION, Integer::parseInt), 0)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/functions/StringToColor.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/functions/StringToColor.java index 48787aec1defa33195fca1c1285781425082a6f9..f61b8328266d8e243619d59f3412b6b7c598b6e2 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/functions/StringToColor.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/readdata/functions/StringToColor.java @@ -20,25 +20,19 @@ import org.dmfs.android.bolts.color.Color; import org.dmfs.android.bolts.color.elementary.ValueColor; import org.dmfs.jems.function.Function; - /** * Pure {@link Function} that converts a String to a {@link Color} * * @author Gabor Keszthelyi */ -public final class StringToColor implements Function -{ +public final class StringToColor implements Function { public static final Function FUNCTION = new StringToColor(); - - private StringToColor() - { + private StringToColor() { } - @Override - public Color value(String stringValue) - { + public Color value(String stringValue) { return new ValueColor(Integer.valueOf(stringValue)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/rowdata/DateTimeListData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/rowdata/DateTimeListData.java index 851fb1869045369da1567f7753c91f2c01ca01fb..da994cd19ea1638b1d6f73f8a3d5cabe3f704aba 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/rowdata/DateTimeListData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/rowdata/DateTimeListData.java @@ -17,42 +17,35 @@ package org.dmfs.opentaskspal.rowdata; import android.content.ContentProviderOperation; -import androidx.annotation.NonNull; import android.text.TextUtils; - +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.TransactionContext; import org.dmfs.jems.iterable.decorators.Mapped; import org.dmfs.rfc5545.DateTime; - /** * {@link RowData} for a field of {@link DateTime}s. * * @param - * The contract of the table this row data goes to. - * + * The contract of the table this row data goes to. * @author Marten Gajda */ -public final class DateTimeListData implements RowData -{ +public final class DateTimeListData implements RowData { private final String mField; private final Iterable mDateTimes; - - public DateTimeListData(String field, @NonNull Iterable dateTimes) - { + public DateTimeListData(String field, @NonNull Iterable dateTimes) { mField = field; mDateTimes = dateTimes; } - @NonNull @Override - public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, @NonNull ContentProviderOperation.Builder builder) - { - String value = TextUtils.join(",", - new Mapped<>(DateTime::toString, new Mapped<>(dt -> dt.isFloating() ? dt : dt.shiftTimeZone(DateTime.UTC), mDateTimes))); + public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, + @NonNull ContentProviderOperation.Builder builder) { + String value = TextUtils.join(",", new Mapped<>(DateTime::toString, + new Mapped<>(dt -> dt.isFloating() ? dt : dt.shiftTimeZone(DateTime.UTC), mDateTimes))); return builder.withValue(mField, value.isEmpty() ? null : value); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/rowsets/Subtasks.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/rowsets/Subtasks.java index 530a47db62a1b28eebdc441d8431aca0fd8210d2..41bfd1646d9749ce16ddac43d8b45b65b5b1de24 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/rowsets/Subtasks.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/rowsets/Subtasks.java @@ -16,6 +16,7 @@ package org.dmfs.opentaskspal.rowsets; +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.Projection; import org.dmfs.android.contentpal.RowReference; import org.dmfs.android.contentpal.RowSet; @@ -25,22 +26,15 @@ import org.dmfs.android.contentpal.rowsets.DelegatingRowSet; import org.dmfs.android.contentpal.rowsets.QueryRowSet; import org.dmfs.tasks.contract.TaskContract.Tasks; -import androidx.annotation.NonNull; - - /** * {@link RowSet} for the subtasks of a given task. * * @author Gabor Keszthelyi */ -public final class Subtasks extends DelegatingRowSet -{ +public final class Subtasks extends DelegatingRowSet { - public Subtasks(@NonNull View view, - @NonNull Projection projection, - @NonNull RowReference parentTask) - { + public Subtasks(@NonNull View view, @NonNull Projection projection, + @NonNull RowReference parentTask) { super(new QueryRowSet<>(view, projection, new ReferringTo<>(Tasks.PARENT_ID, parentTask))); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/InstanceTable.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/InstanceTable.java index 4f774d7028925c0dbc01bfeac7bed393f16b693b..84abb9ae831f8caac78b754efeb5bf7a34083259 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/InstanceTable.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/InstanceTable.java @@ -21,16 +21,13 @@ import org.dmfs.android.contentpal.tables.BaseTable; import org.dmfs.android.contentpal.tables.DelegatingTable; import org.dmfs.tasks.contract.TaskContract; - /** * {@link Table} for {@link TaskContract.Instances}. * * @author Gabor Keszthelyi */ -public final class InstanceTable extends DelegatingTable -{ - public InstanceTable(String authority) - { +public final class InstanceTable extends DelegatingTable { + public InstanceTable(String authority) { super(new BaseTable(TaskContract.Instances.getContentUri(authority))); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/LocalTaskListsTable.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/LocalTaskListsTable.java index 964c55036eebf5d54c63025605b21ecd1b0b5f21..9a52306ac26674a10dbfabb31da35941c5deb17c 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/LocalTaskListsTable.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/LocalTaskListsTable.java @@ -17,30 +17,24 @@ package org.dmfs.opentaskspal.tables; import android.accounts.Account; - +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.Table; import org.dmfs.android.contentpal.tables.DelegatingTable; import org.dmfs.android.contentpal.tables.Synced; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** - * {@link Table} for {@link TaskContract.TaskLists} scoped on local lists, i.e. lists with 'the local account'. + * {@link Table} for {@link TaskContract.TaskLists} scoped on local lists, i.e. + * lists with 'the local account'. * * @author Gabor Keszthelyi */ -public final class LocalTaskListsTable extends DelegatingTable -{ - public LocalTaskListsTable(@NonNull String authority) - { +public final class LocalTaskListsTable extends DelegatingTable { + public LocalTaskListsTable(@NonNull String authority) { this(new Account(TaskContract.LOCAL_ACCOUNT_NAME, TaskContract.LOCAL_ACCOUNT_TYPE), authority); } - - private LocalTaskListsTable(@NonNull Account localAccount, @NonNull String authority) - { + private LocalTaskListsTable(@NonNull Account localAccount, @NonNull String authority) { super(new Synced<>(localAccount, new TaskListsTable(authority))); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/PropertiesTable.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/PropertiesTable.java index 3fe1995a640304541dadf40d2e5ec33b4b83b4c1..3864c19f3132b4efdc272facd712733d06a994f9 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/PropertiesTable.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/PropertiesTable.java @@ -16,23 +16,19 @@ package org.dmfs.opentaskspal.tables; +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.Table; import org.dmfs.android.contentpal.tables.BaseTable; import org.dmfs.android.contentpal.tables.DelegatingTable; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** * {@link Table} for {@link TaskContract.Properties}. * * @author Gabor Keszthelyi */ -public final class PropertiesTable extends DelegatingTable -{ - public PropertiesTable(@NonNull String authority) - { +public final class PropertiesTable extends DelegatingTable { + public PropertiesTable(@NonNull String authority) { super(new BaseTable<>(TaskContract.Properties.getContentUri(authority))); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TaskListScoped.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TaskListScoped.java index 68ea0c3dd8213149a72e6f2c0a1cabddd0a6c5c3..a53d1439ddb0bada19472ac0741cb666d5d3fe45 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TaskListScoped.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TaskListScoped.java @@ -17,7 +17,7 @@ package org.dmfs.opentaskspal.tables; import android.content.ContentProviderClient; - +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.InsertOperation; import org.dmfs.android.contentpal.Operation; import org.dmfs.android.contentpal.Predicate; @@ -29,64 +29,53 @@ import org.dmfs.opentaskspal.operations.TaskListTask; import org.dmfs.opentaskspal.predicates.TaskOnList; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** - * A view onto the {@link TaskContract.Tasks} table which contains only tasks from a specific task list. - * Tasks created with {@link #insertOperation(UriParams)} will automatically be added to this task list. + * A view onto the {@link TaskContract.Tasks} table which contains only tasks + * from a specific task list. Tasks created with + * {@link #insertOperation(UriParams)} will automatically be added to this task + * list. * * @author Marten Gajda * @author Gabor Keszthelyi */ -public final class TaskListScoped implements Table -{ +public final class TaskListScoped implements Table { private final Table mDelegate; private final RowSnapshot mTaskListRow; - - public TaskListScoped(@NonNull RowSnapshot taskListRow, @NonNull Table delegate) - { + public TaskListScoped(@NonNull RowSnapshot taskListRow, + @NonNull Table delegate) { mDelegate = delegate; mTaskListRow = taskListRow; } - @NonNull @Override - public InsertOperation insertOperation(@NonNull UriParams uriParams) - { + public InsertOperation insertOperation(@NonNull UriParams uriParams) { return new TaskListTask(mTaskListRow, mDelegate.insertOperation(uriParams)); } - @NonNull @Override - public Operation updateOperation(@NonNull UriParams uriParams, @NonNull Predicate predicate) - { + public Operation updateOperation(@NonNull UriParams uriParams, + @NonNull Predicate predicate) { return mDelegate.updateOperation(uriParams, new TaskOnList(mTaskListRow, predicate)); } - @NonNull @Override - public Operation deleteOperation(@NonNull UriParams uriParams, @NonNull Predicate predicate) - { + public Operation deleteOperation(@NonNull UriParams uriParams, + @NonNull Predicate predicate) { return mDelegate.deleteOperation(uriParams, new TaskOnList(mTaskListRow, predicate)); } - @NonNull @Override - public Operation assertOperation(@NonNull UriParams uriParams, @NonNull Predicate predicate) - { + public Operation assertOperation(@NonNull UriParams uriParams, + @NonNull Predicate predicate) { return mDelegate.assertOperation(uriParams, new TaskOnList(mTaskListRow, predicate)); } - - public View view(@NonNull ContentProviderClient client) - { + public View view(@NonNull ContentProviderClient client) { return new org.dmfs.opentaskspal.views.TaskListScoped(mTaskListRow, mDelegate.view(client)); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TaskListsTable.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TaskListsTable.java index f211807495cc1dbe1bf624fe6ec08b1675af2e8b..f6f313ce72a8b400459f3fbfce23ccf966a0ad12 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TaskListsTable.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TaskListsTable.java @@ -21,16 +21,13 @@ import org.dmfs.android.contentpal.tables.BaseTable; import org.dmfs.android.contentpal.tables.DelegatingTable; import org.dmfs.tasks.contract.TaskContract; - /** * {@link Table} for {@link TaskContract.TaskLists}. * * @author Gabor Keszthelyi */ -public final class TaskListsTable extends DelegatingTable -{ - public TaskListsTable(String authority) - { +public final class TaskListsTable extends DelegatingTable { + public TaskListsTable(String authority) { super(new BaseTable(TaskContract.TaskLists.getContentUri(authority))); } -} \ No newline at end of file +} diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TasksTable.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TasksTable.java index 693a2905be9fab1b048dd94ba20362cf15176d8b..80733f5673fefc0464556ccd6b668f96146f45ee 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TasksTable.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tables/TasksTable.java @@ -17,22 +17,18 @@ package org.dmfs.opentaskspal.tables; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.Table; import org.dmfs.android.contentpal.tables.BaseTable; import org.dmfs.android.contentpal.tables.DelegatingTable; import org.dmfs.tasks.contract.TaskContract; - /** * {@link Table} for {@link TaskContract.Tasks}. * * @author Gabor Keszthelyi */ -public final class TasksTable extends DelegatingTable -{ - public TasksTable(@NonNull String authority) - { +public final class TasksTable extends DelegatingTable { + public TasksTable(@NonNull String authority) { super(new BaseTable(TaskContract.Tasks.getContentUri(authority))); } -} \ No newline at end of file +} diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/ColorData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/ColorData.java index 0ec88cbb1931d1fd5e61b0c62bb3dfdac2e5426e..0781f9604d567b4d00cf25d08dcd276265c55966 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/ColorData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/ColorData.java @@ -16,25 +16,20 @@ package org.dmfs.opentaskspal.tasklists; +import androidx.annotation.NonNull; import org.dmfs.android.bolts.color.Color; import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** * {@link RowData} of the color of a task list. * * @author Marten Gajda */ -public final class ColorData extends DelegatingRowData -{ +public final class ColorData extends DelegatingRowData { - public ColorData(@NonNull Color color) - { + public ColorData(@NonNull Color color) { super((transactionContext, builder) -> builder.withValue(TaskContract.TaskLists.LIST_COLOR, color.argb())); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/NameData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/NameData.java index f95bf896df1259c56e4636fde99538e7054cc7a6..aad3bdd93030a8b82cc9d375500c9cd67b209bfc 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/NameData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/NameData.java @@ -17,25 +17,22 @@ package org.dmfs.opentaskspal.tasklists; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.CharSequenceRowData; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} to set the name of a task list. * * @author Gabor Keszthelyi */ -public final class NameData extends DelegatingRowData -{ +public final class NameData extends DelegatingRowData { - public NameData(@NonNull CharSequence name) - { - // TODO CharSequenceRowData allows null so this class wouldn't fail with that but erase the value + public NameData(@NonNull CharSequence name) { + // TODO CharSequenceRowData allows null so this class wouldn't fail with that + // but erase the + // value super(new CharSequenceRowData(TaskContract.TaskLists.LIST_NAME, name)); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/OwnerData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/OwnerData.java index f84d0ef38b6382d153743138d339a8072e93472e..3859c47886f51a247d6f5f5a3e59515e23c07ec1 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/OwnerData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/OwnerData.java @@ -16,26 +16,23 @@ package org.dmfs.opentaskspal.tasklists; +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.CharSequenceRowData; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** * {@link RowData} of the owner account of a task list. * * @author Marten Gajda */ -public final class OwnerData extends DelegatingRowData -{ +public final class OwnerData extends DelegatingRowData { - public OwnerData(@NonNull CharSequence owner) - { - // TODO CharSequenceRowData allows null so this class wouldn't fail with that but erase the value + public OwnerData(@NonNull CharSequence owner) { + // TODO CharSequenceRowData allows null so this class wouldn't fail with that + // but erase the + // value super(new CharSequenceRowData<>(TaskContract.TaskLists.OWNER, owner)); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/SyncStatusData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/SyncStatusData.java index 35dbfd6e5661027b70235d7a28faad4641eb5b41..016f75f3417ffacea397a8a2ceeeb1e529587933 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/SyncStatusData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/SyncStatusData.java @@ -20,24 +20,19 @@ import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} of the sync status of a task list. * * @author Marten Gajda */ -public final class SyncStatusData extends DelegatingRowData -{ +public final class SyncStatusData extends DelegatingRowData { - public SyncStatusData() - { + public SyncStatusData() { this(true); } - - public SyncStatusData(boolean syncEnabled) - { - super((transactionContext, builder) -> builder.withValue(TaskContract.TaskLists.SYNC_ENABLED, syncEnabled ? 1 : 0)); + public SyncStatusData(boolean syncEnabled) { + super((transactionContext, builder) -> builder.withValue(TaskContract.TaskLists.SYNC_ENABLED, + syncEnabled ? 1 : 0)); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/VisibilityData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/VisibilityData.java index 61b491a4767908b2fa0ed36209fb5c5ed540c5e1..60faab465d0a47b71ca2d61204644b359c097873 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/VisibilityData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasklists/VisibilityData.java @@ -20,24 +20,18 @@ import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} of the visibility of a task list. * * @author Marten Gajda */ -public final class VisibilityData extends DelegatingRowData -{ +public final class VisibilityData extends DelegatingRowData { - public VisibilityData() - { + public VisibilityData() { this(true); } - - public VisibilityData(boolean visible) - { + public VisibilityData(boolean visible) { super((transactionContext, builder) -> builder.withValue(TaskContract.TaskLists.VISIBLE, visible ? 1 : 0)); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ChildTaskRelationData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ChildTaskRelationData.java index 752947ef1ae9acf9b3fcb4b0c55f307054fcb440..520fac02c98d3d7d68d78d655ecd544c2b695070 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ChildTaskRelationData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ChildTaskRelationData.java @@ -21,24 +21,20 @@ import org.dmfs.android.contentpal.RowSnapshot; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.tasks.contract.TaskContract; - /** - * {@link RowData} to add the {@link TaskContract.Property.Relation#RELTYPE_CHILD} relation between the 2 given tasks, to the {@link TaskContract.Properties} - * table. + * {@link RowData} to add the + * {@link TaskContract.Property.Relation#RELTYPE_CHILD} relation between the 2 + * given tasks, to the {@link TaskContract.Properties} table. * * @author Gabor Keszthelyi */ -public final class ChildTaskRelationData extends DelegatingRowData -{ - public ChildTaskRelationData(RowSnapshot childTask, RowSnapshot parentTask) - { +public final class ChildTaskRelationData extends DelegatingRowData { + public ChildTaskRelationData(RowSnapshot childTask, + RowSnapshot parentTask) { super(new RelationData(parentTask, TaskContract.Property.Relation.RELTYPE_CHILD, childTask)); } - - public ChildTaskRelationData(CharSequence childTaskUid, RowSnapshot parentTask) - { + public ChildTaskRelationData(CharSequence childTaskUid, RowSnapshot parentTask) { super(new RelationData(parentTask, TaskContract.Property.Relation.RELTYPE_CHILD, childTaskUid)); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/DueData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/DueData.java index ad53dfea373f0a7baeab30117148a7cc3d393016..cb6bd86c3cb1477e55d36b027211bf588475b526 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/DueData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/DueData.java @@ -17,41 +17,32 @@ package org.dmfs.opentaskspal.tasks; import android.content.ContentProviderOperation; - +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.TransactionContext; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** - * {@link RowData} for setting only the due datetime of the task, for setting start as well use {@link TimeData}. + * {@link RowData} for setting only the due datetime of the task, for setting + * start as well use {@link TimeData}. * * @author Gabor Keszthelyi */ -public final class DueData implements RowData -{ +public final class DueData implements RowData { private final DateTime mDue; - - public DueData(@NonNull DateTime due) - { + public DueData(@NonNull DateTime due) { mDue = due; } - @NonNull @Override - public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, @NonNull ContentProviderOperation.Builder builder) - { - return builder - .withValue(TaskContract.Tasks.DUE, mDue.getTimestamp()) + public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, + @NonNull ContentProviderOperation.Builder builder) { + return builder.withValue(TaskContract.Tasks.DUE, mDue.getTimestamp()) .withValue(TaskContract.Tasks.TZ, mDue.isAllDay() ? "UTC" : mDue.getTimeZone().getID()) .withValue(TaskContract.Tasks.IS_ALLDAY, mDue.isAllDay() ? 1 : 0) - .withValue(TaskContract.Tasks.DTSTART, null) - .withValue(TaskContract.Tasks.DURATION, null); + .withValue(TaskContract.Tasks.DTSTART, null).withValue(TaskContract.Tasks.DURATION, null); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ExDatesTaskData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ExDatesTaskData.java index ae02fd6c020589b3089dc275a5e299a53474bd6f..b093cab3b92d0a01f7436cc1a5357f3020fa1402 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ExDatesTaskData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ExDatesTaskData.java @@ -17,25 +17,23 @@ package org.dmfs.opentaskspal.tasks; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.opentaskspal.rowdata.DateTimeListData; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} for tasks with EXDATEs + * *

- * TODO: how to make sure this is only ever used with tasks having a start and/or due date? + * TODO: how to make sure this is only ever used with tasks having a start + * and/or due date? * * @author Marten Gajda */ -public final class ExDatesTaskData extends DelegatingRowData -{ - public ExDatesTaskData(@NonNull Iterable exdates) - { +public final class ExDatesTaskData extends DelegatingRowData { + public ExDatesTaskData(@NonNull Iterable exdates) { super(new DateTimeListData<>(TaskContract.Tasks.EXDATE, exdates)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/NoTimeData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/NoTimeData.java index 161284929a87660fcc411f63bec9d7b4b9c84480..64ce6b8d693dcef27b000786e2e29569a309b3c4 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/NoTimeData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/NoTimeData.java @@ -18,33 +18,23 @@ package org.dmfs.opentaskspal.tasks; import android.content.ContentProviderOperation; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.TransactionContext; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} for clearing time data (start, due, duration) for a task. * * @author Gabor Keszthelyi */ -public final class NoTimeData implements RowData -{ +public final class NoTimeData implements RowData { @NonNull @Override - public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, @NonNull ContentProviderOperation.Builder builder) - { - return builder - .withValue(TaskContract.Tasks.DTSTART, null) - .withValue(TaskContract.Tasks.DUE, null) - .withValue(TaskContract.Tasks.DURATION, null) - - .withValue(TaskContract.Tasks.TZ, null) - .withValue(TaskContract.Tasks.IS_ALLDAY, null) - - .withValue(TaskContract.Tasks.RDATE, null) - .withValue(TaskContract.Tasks.RRULE, null) - .withValue(TaskContract.Tasks.EXDATE, null); + public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, + @NonNull ContentProviderOperation.Builder builder) { + return builder.withValue(TaskContract.Tasks.DTSTART, null).withValue(TaskContract.Tasks.DUE, null) + .withValue(TaskContract.Tasks.DURATION, null).withValue(TaskContract.Tasks.TZ, null) + .withValue(TaskContract.Tasks.IS_ALLDAY, null).withValue(TaskContract.Tasks.RDATE, null) + .withValue(TaskContract.Tasks.RRULE, null).withValue(TaskContract.Tasks.EXDATE, null); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/OriginalInstanceData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/OriginalInstanceData.java index 2bb45886abe5377b43fb3c776bea9aaa1835cb85..5d9577a843ae8c807cb7e950c08f94aa559c9725 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/OriginalInstanceData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/OriginalInstanceData.java @@ -16,6 +16,7 @@ package org.dmfs.opentaskspal.tasks; +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.RowSnapshot; import org.dmfs.android.contentpal.rowdata.Composite; @@ -24,21 +25,15 @@ import org.dmfs.android.contentpal.rowdata.Referring; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** * {@link RowData} of an instance override. * * @author Marten Gajda */ -public final class OriginalInstanceData extends DelegatingRowData -{ - public OriginalInstanceData(@NonNull RowSnapshot originalTask, DateTime originalTime) - { - super(new Composite<>( - new Referring<>(TaskContract.Tasks.ORIGINAL_INSTANCE_ID, originalTask), - (transactionContext, builder) -> builder.withValue(TaskContract.Tasks.ORIGINAL_INSTANCE_TIME, originalTime.getTimestamp()))); +public final class OriginalInstanceData extends DelegatingRowData { + public OriginalInstanceData(@NonNull RowSnapshot originalTask, DateTime originalTime) { + super(new Composite<>(new Referring<>(TaskContract.Tasks.ORIGINAL_INSTANCE_ID, originalTask), + (transactionContext, builder) -> builder.withValue(TaskContract.Tasks.ORIGINAL_INSTANCE_TIME, + originalTime.getTimestamp()))); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/OriginalInstanceSyncIdData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/OriginalInstanceSyncIdData.java index 3cd442aa9ae9714e213e37c77d4a7f73275ccf45..e42e69f60331574be55139bc90c848bc5e83bea8 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/OriginalInstanceSyncIdData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/OriginalInstanceSyncIdData.java @@ -17,7 +17,6 @@ package org.dmfs.opentaskspal.tasks; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.CharSequenceRowData; import org.dmfs.android.contentpal.rowdata.Composite; @@ -25,20 +24,20 @@ import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; - /** - * {@link RowData} for adding {@link TaskContract.Tasks#ORIGINAL_INSTANCE_SYNC_ID} + * {@link RowData} for adding + * {@link TaskContract.Tasks#ORIGINAL_INSTANCE_SYNC_ID} * * @author Gabor Keszthelyi */ -public final class OriginalInstanceSyncIdData extends DelegatingRowData -{ - public OriginalInstanceSyncIdData(@NonNull CharSequence originalInstanceSyncId, DateTime originalTime) - { - // TODO CharSequenceRowData allows null so this class wouldn't fail with that but erase the value +public final class OriginalInstanceSyncIdData extends DelegatingRowData { + public OriginalInstanceSyncIdData(@NonNull CharSequence originalInstanceSyncId, DateTime originalTime) { + // TODO CharSequenceRowData allows null so this class wouldn't fail with that + // but erase the + // value super(new Composite<>( new CharSequenceRowData<>(TaskContract.Tasks.ORIGINAL_INSTANCE_SYNC_ID, originalInstanceSyncId), - (transactionContext, builder) -> builder.withValue(TaskContract.Tasks.ORIGINAL_INSTANCE_TIME, originalTime.getTimestamp()))); + (transactionContext, builder) -> builder.withValue(TaskContract.Tasks.ORIGINAL_INSTANCE_TIME, + originalTime.getTimestamp()))); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ParentTaskRelationData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ParentTaskRelationData.java index 194b33c627606e875afe8b620f50aa055f3ea58b..f5d378b1f5b07382adae2c16edd33697e030a75c 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ParentTaskRelationData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/ParentTaskRelationData.java @@ -21,24 +21,20 @@ import org.dmfs.android.contentpal.RowSnapshot; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.tasks.contract.TaskContract; - /** - * {@link RowData} to add the {@link TaskContract.Property.Relation#RELTYPE_PARENT} relation between the 2 given tasks, to the {@link TaskContract.Properties} - * table. + * {@link RowData} to add the + * {@link TaskContract.Property.Relation#RELTYPE_PARENT} relation between the 2 + * given tasks, to the {@link TaskContract.Properties} table. * * @author Gabor Keszthelyi */ -public final class ParentTaskRelationData extends DelegatingRowData -{ - public ParentTaskRelationData(RowSnapshot parentTask, RowSnapshot childTask) - { +public final class ParentTaskRelationData extends DelegatingRowData { + public ParentTaskRelationData(RowSnapshot parentTask, + RowSnapshot childTask) { super(new RelationData(childTask, TaskContract.Property.Relation.RELTYPE_PARENT, parentTask)); } - - public ParentTaskRelationData(CharSequence parentTaskUid, RowSnapshot childTask) - { + public ParentTaskRelationData(CharSequence parentTaskUid, RowSnapshot childTask) { super(new RelationData(childTask, TaskContract.Property.Relation.RELTYPE_PARENT, parentTaskUid)); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/PinnedData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/PinnedData.java index 49b5ff8978543d0db6755797883dc79352e8d844..46317c3a51898ef1008d84055b0d1af0f32d3480 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/PinnedData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/PinnedData.java @@ -18,38 +18,30 @@ package org.dmfs.opentaskspal.tasks; import android.content.ContentProviderOperation; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.TransactionContext; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} for {@link TaskContract.Tasks#PINNED} * * @author Marten Gajda */ -public final class PinnedData implements RowData -{ +public final class PinnedData implements RowData { private final boolean mPinned; - - public PinnedData() - { + public PinnedData() { this(true); } - - public PinnedData(boolean pinned) - { + public PinnedData(boolean pinned) { mPinned = pinned; } - @NonNull @Override - public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, @NonNull ContentProviderOperation.Builder builder) - { + public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, + @NonNull ContentProviderOperation.Builder builder) { return builder.withValue(TaskContract.Tasks.PINNED, mPinned ? 1 : 0); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/PropertyData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/PropertyData.java index 9620eb2abccc9c219c55f3b0373398b20d6fd41a..6e9d75372c01885c393f2cb79657cd31ea051990 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/PropertyData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/PropertyData.java @@ -16,29 +16,24 @@ package org.dmfs.opentaskspal.tasks; +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.CharSequenceRowData; import org.dmfs.android.contentpal.rowdata.Composite; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** * The {@link RowData} of a property row. + * *

- * This just sets the {@link TaskContract.Properties#MIMETYPE} field of the row and leaves everything else to the provided {@link RowData}. + * This just sets the {@link TaskContract.Properties#MIMETYPE} field of the row + * and leaves everything else to the provided {@link RowData}. * * @author Marten Gajda */ -public final class PropertyData extends DelegatingRowData -{ - public PropertyData(@NonNull String mimeType, @NonNull RowData delegate) - { - super(new Composite<>( - new CharSequenceRowData<>(TaskContract.Properties.MIMETYPE, mimeType), - delegate - )); +public final class PropertyData extends DelegatingRowData { + public PropertyData(@NonNull String mimeType, @NonNull RowData delegate) { + super(new Composite<>(new CharSequenceRowData<>(TaskContract.Properties.MIMETYPE, mimeType), delegate)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RDatesTaskData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RDatesTaskData.java index 57765a8afbb54ca2773870f84a237e7e7c4dfba0..3ba6ed8a34c1432b288b5d05a889d0946dae8336 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RDatesTaskData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RDatesTaskData.java @@ -16,6 +16,7 @@ package org.dmfs.opentaskspal.tasks; +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.jems.iterable.elementary.Seq; @@ -23,26 +24,21 @@ import org.dmfs.opentaskspal.rowdata.DateTimeListData; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** * {@link RowData} for tasks with RDATEs. + * *

- * TODO: how to make sure this is only ever used with tasks having a start and/or due date? + * TODO: how to make sure this is only ever used with tasks having a start + * and/or due date? * * @author Marten Gajda */ -public final class RDatesTaskData extends DelegatingRowData -{ - public RDatesTaskData(@NonNull DateTime... rdates) - { +public final class RDatesTaskData extends DelegatingRowData { + public RDatesTaskData(@NonNull DateTime... rdates) { this(new Seq<>(rdates)); } - - public RDatesTaskData(@NonNull Iterable rdates) - { + public RDatesTaskData(@NonNull Iterable rdates) { super(new DateTimeListData<>(TaskContract.Tasks.RDATE, rdates)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RRuleTaskData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RRuleTaskData.java index 4e570023a1f6eea240735af6f197ef8d207a190c..72d77c6a689bd670d30ed6a066807100f37ea7f1 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RRuleTaskData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RRuleTaskData.java @@ -18,35 +18,31 @@ package org.dmfs.opentaskspal.tasks; import android.content.ContentProviderOperation; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.TransactionContext; import org.dmfs.rfc5545.recur.RecurrenceRule; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} for tasks with a recurrence rule. + * *

- * TODO: how to make sure this is only ever used with tasks having a start and/or due date? + * TODO: how to make sure this is only ever used with tasks having a start + * and/or due date? * * @author Marten Gajda */ -public final class RRuleTaskData implements RowData -{ +public final class RRuleTaskData implements RowData { private final RecurrenceRule mRule; - - public RRuleTaskData(@NonNull RecurrenceRule rule) - { + public RRuleTaskData(@NonNull RecurrenceRule rule) { mRule = rule; } - @NonNull @Override - public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, @NonNull ContentProviderOperation.Builder builder) - { + public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, + @NonNull ContentProviderOperation.Builder builder) { return builder.withValue(TaskContract.Tasks.RRULE, mRule.toString()); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RelationData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RelationData.java index b4f74649c2ad86bee70ab9f3fdf21a52f8a8ea3a..ec0be1cfca290388298aff27a008e046dec896ba 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RelationData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/RelationData.java @@ -16,6 +16,7 @@ package org.dmfs.opentaskspal.tasks; +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.RowSnapshot; import org.dmfs.android.contentpal.rowdata.CharSequenceRowData; @@ -25,35 +26,24 @@ import org.dmfs.android.contentpal.rowdata.RawRowData; import org.dmfs.android.contentpal.rowdata.Referring; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** * {@link RowData} for adding a {@link TaskContract.Property.Relation} property. * * @author Gabor Keszthelyi */ -public final class RelationData extends DelegatingRowData -{ - public RelationData(@NonNull RowSnapshot relatingTask, - int relType, - @NonNull RowSnapshot relatedTask) - { +public final class RelationData extends DelegatingRowData { + public RelationData(@NonNull RowSnapshot relatingTask, int relType, + @NonNull RowSnapshot relatedTask) { super(new PropertyData(TaskContract.Property.Relation.CONTENT_ITEM_TYPE, - new Composite<>( - new Referring<>(TaskContract.Property.Relation.TASK_ID, relatingTask), + new Composite<>(new Referring<>(TaskContract.Property.Relation.TASK_ID, relatingTask), new RawRowData<>(TaskContract.Property.Relation.RELATED_TYPE, relType), new Referring<>(TaskContract.Property.Relation.RELATED_ID, relatedTask)))); } - - public RelationData(@NonNull RowSnapshot relatingTask, - int relType, - @NonNull CharSequence relatedTaskUid) - { + public RelationData(@NonNull RowSnapshot relatingTask, int relType, + @NonNull CharSequence relatedTaskUid) { super(new PropertyData(TaskContract.Property.Relation.CONTENT_ITEM_TYPE, - new Composite<>( - new Referring<>(TaskContract.Property.Relation.TASK_ID, relatingTask), + new Composite<>(new Referring<>(TaskContract.Property.Relation.TASK_ID, relatingTask), new RawRowData<>(TaskContract.Property.Relation.RELATED_TYPE, relType), new CharSequenceRowData<>(TaskContract.Property.Relation.RELATED_UID, relatedTaskUid)))); } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/StatusData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/StatusData.java index 921ec6e7b1bb8e96f9c9a0bb711aab3f555e6807..33172db71361d832c6f66514213ffa37c0f41123 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/StatusData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/StatusData.java @@ -18,32 +18,26 @@ package org.dmfs.opentaskspal.tasks; import android.content.ContentProviderOperation; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.TransactionContext; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} for the status of a task. * * @author Marten Gajda */ -public final class StatusData implements RowData -{ +public final class StatusData implements RowData { private final int mStatus; - - public StatusData(int status) - { + public StatusData(int status) { mStatus = status; } - @NonNull @Override - public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, @NonNull ContentProviderOperation.Builder builder) - { + public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, + @NonNull ContentProviderOperation.Builder builder) { return builder.withValue(TaskContract.Tasks.STATUS, mStatus); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/SyncIdData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/SyncIdData.java index cb0170fe39883700f2a76b3ffb7fb0057954e6cb..488ccc2c4197eb6d9fe189bbbe3d1c7218214b9c 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/SyncIdData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/SyncIdData.java @@ -17,23 +17,21 @@ package org.dmfs.opentaskspal.tasks; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.CharSequenceRowData; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} for {@link TaskContract.Tasks#_SYNC_ID} * * @author Gabor Keszthelyi */ -public final class SyncIdData extends DelegatingRowData -{ - public SyncIdData(@NonNull CharSequence syncId) - { - // TODO CharSequenceRowData allows null so this class wouldn't fail with that but erase the value +public final class SyncIdData extends DelegatingRowData { + public SyncIdData(@NonNull CharSequence syncId) { + // TODO CharSequenceRowData allows null so this class wouldn't fail with that + // but erase the + // value super(new CharSequenceRowData(TaskContract.Tasks._SYNC_ID, syncId)); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/TimeData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/TimeData.java index 43799ab22da28b007dcca6564e05d2a02bed0f53..70059989f90cf53e34e9625abc5b949734916c63 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/TimeData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/TimeData.java @@ -17,7 +17,7 @@ package org.dmfs.opentaskspal.tasks; import android.content.ContentProviderOperation; - +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.TransactionContext; import org.dmfs.jems.optional.Optional; @@ -27,73 +27,53 @@ import org.dmfs.rfc5545.DateTime; import org.dmfs.rfc5545.Duration; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** * {@link RowData} for adding start, start+due, or start+duration times. * * @author Gabor Keszthelyi */ -public final class TimeData implements RowData -{ +public final class TimeData implements RowData { private final DateTime mStart; private final Optional mDue; private final Optional mDuration; - - private TimeData(@NonNull DateTime start, @NonNull Optional due, @NonNull Optional duration) - { + private TimeData(@NonNull DateTime start, @NonNull Optional due, @NonNull Optional duration) { mStart = start; mDue = due; mDuration = duration; } - - public TimeData(@NonNull DateTime start, @NonNull DateTime due) - { + public TimeData(@NonNull DateTime start, @NonNull DateTime due) { this(start, new Present<>(due), Absent.absent()); } - - public TimeData(@NonNull DateTime start, @NonNull Duration duration) - { + public TimeData(@NonNull DateTime start, @NonNull Duration duration) { this(start, Absent.absent(), new Present<>(duration)); } - - public TimeData(@NonNull DateTime start) - { + public TimeData(@NonNull DateTime start) { this(start, Absent.absent(), Absent.absent()); } - @NonNull @Override - public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, @NonNull ContentProviderOperation.Builder builder) - { - if (mDue.isPresent() && mStart.isAllDay() != mDue.value().isAllDay()) - { + public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, + @NonNull ContentProviderOperation.Builder builder) { + if (mDue.isPresent() && mStart.isAllDay() != mDue.value().isAllDay()) { throw new IllegalArgumentException("'start' and 'due' must have the same all-day flag"); } DateTime start = mStart; - if (mDue.isPresent() && !mDue.value().isAllDay()) - { + if (mDue.isPresent() && !mDue.value().isAllDay()) { start = mStart.shiftTimeZone(mDue.value().getTimeZone()); } return doUpdateBuilder(start, mDue, mDuration, builder); } - - private static ContentProviderOperation.Builder doUpdateBuilder(DateTime start, - Optional due, - Optional duration, - ContentProviderOperation.Builder builder) - { - return builder - .withValue(TaskContract.Tasks.DTSTART, start.getTimestamp()) + private static ContentProviderOperation.Builder doUpdateBuilder(DateTime start, Optional due, + Optional duration, ContentProviderOperation.Builder builder) { + return builder.withValue(TaskContract.Tasks.DTSTART, start.getTimestamp()) .withValue(TaskContract.Tasks.TZ, start.isAllDay() ? "UTC" : start.getTimeZone().getID()) .withValue(TaskContract.Tasks.IS_ALLDAY, start.isAllDay() ? 1 : 0) .withValue(TaskContract.Tasks.DUE, due.isPresent() ? due.value().getTimestamp() : null) diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/TitleData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/TitleData.java index 0bab9954d2c8a6b690b4663d7234dce2f4dcfd12..39acca1e20b004e408c95d98ac001e458f02dbea 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/TitleData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/TitleData.java @@ -17,24 +17,21 @@ package org.dmfs.opentaskspal.tasks; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.rowdata.CharSequenceRowData; import org.dmfs.android.contentpal.rowdata.DelegatingRowData; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} for the title of the task. * * @author Gabor Keszthelyi */ -public final class TitleData extends DelegatingRowData -{ - public TitleData(@NonNull CharSequence title) - { - // TODO CharSequenceRowData allows null so this class wouldn't fail with that but erase the value +public final class TitleData extends DelegatingRowData { + public TitleData(@NonNull CharSequence title) { + // TODO CharSequenceRowData allows null so this class wouldn't fail with that + // but erase the + // value super(new CharSequenceRowData(TaskContract.Tasks.TITLE, title)); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/VersionData.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/VersionData.java index 3ef2dfd379f1a6ed7c2cbf6a3c3ebcc7d38de2f4..e7a01acbfd14e5fe74ac2b6f452f6281d51b0315 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/VersionData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/tasks/VersionData.java @@ -18,35 +18,31 @@ package org.dmfs.opentaskspal.tasks; import android.content.ContentProviderOperation; import androidx.annotation.NonNull; - import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.TransactionContext; import org.dmfs.android.contentpal.operations.Assert; import org.dmfs.tasks.contract.TaskContract; - /** * {@link RowData} for the {@link TaskContract.Tasks#VERSION}. + * *

- * Note: the task version is read-only. This {@link RowData} may only be used with {@link Assert} operations. + * Note: the task version is read-only. This {@link RowData} may only be used + * with {@link Assert} operations. * * @author Marten Gajda */ -public final class VersionData implements RowData -{ +public final class VersionData implements RowData { private final int mVersion; - - public VersionData(int version) - { + public VersionData(int version) { mVersion = version; } - @NonNull @Override - public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, @NonNull ContentProviderOperation.Builder builder) - { + public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, + @NonNull ContentProviderOperation.Builder builder) { return builder.withValue(TaskContract.Tasks.VERSION, mVersion); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/InstancesView.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/InstancesView.java index ab3e548ac18012435e4626cc7c08921b21652948..c06d1753459f799c377a86cd6ab7e299d80ea36b 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/InstancesView.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/InstancesView.java @@ -17,22 +17,18 @@ package org.dmfs.opentaskspal.views; import android.content.ContentProviderClient; - import org.dmfs.android.contentpal.View; import org.dmfs.android.contentpal.views.BaseView; import org.dmfs.android.contentpal.views.DelegatingView; import org.dmfs.tasks.contract.TaskContract; - /** * {@link View} for the {@link TaskContract.Instances} table. * * @author Marten Gajda */ -public final class InstancesView extends DelegatingView -{ - public InstancesView(String authority, ContentProviderClient client) - { +public final class InstancesView extends DelegatingView { + public InstancesView(String authority, ContentProviderClient client) { super(new BaseView<>(client, TaskContract.Instances.getContentUri(authority))); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TaskListScoped.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TaskListScoped.java index db1ada10d96c1b8471bc810914830f6a4dc9f269..61de2233671721a3bebf53444e51778ae26733b6 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TaskListScoped.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TaskListScoped.java @@ -18,7 +18,7 @@ package org.dmfs.opentaskspal.views; import android.database.Cursor; import android.os.RemoteException; - +import androidx.annotation.NonNull; import org.dmfs.android.contentpal.InsertOperation; import org.dmfs.android.contentpal.Predicate; import org.dmfs.android.contentpal.Projection; @@ -30,41 +30,34 @@ import org.dmfs.jems.optional.Optional; import org.dmfs.opentaskspal.predicates.TaskOnList; import org.dmfs.tasks.contract.TaskContract; -import androidx.annotation.NonNull; - - /** - * A view onto {@link TaskContract.Tasks} which contains only events from a specific task list. - * `{@link InsertOperation}`s returned by the result of {@link #table()} will insert with the given task list by default. + * A view onto {@link TaskContract.Tasks} which contains only events from a + * specific task list. `{@link InsertOperation}`s returned by the result of + * {@link #table()} will insert with the given task list by default. * * @author Gabor Keszthelyi */ -public final class TaskListScoped implements View -{ +public final class TaskListScoped implements View { private final View mDelegate; private final RowSnapshot mTaskListRow; - - public TaskListScoped(@NonNull RowSnapshot taskListRow, @NonNull View delegate) - { + public TaskListScoped(@NonNull RowSnapshot taskListRow, + @NonNull View delegate) { mDelegate = delegate; mTaskListRow = taskListRow; } - @NonNull @Override - public Cursor rows(@NonNull UriParams uriParams, @NonNull Projection projection, @NonNull Predicate predicate, @NonNull Optional sorting) throws RemoteException - { + public Cursor rows(@NonNull UriParams uriParams, @NonNull Projection projection, + @NonNull Predicate predicate, @NonNull Optional sorting) + throws RemoteException { return mDelegate.rows(uriParams, projection, new TaskOnList(mTaskListRow, predicate), sorting); } - @NonNull @Override - public Table table() - { + public Table table() { return new org.dmfs.opentaskspal.tables.TaskListScoped(mTaskListRow, mDelegate.table()); } - } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TaskListsView.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TaskListsView.java index 6143096adee3c7f747f2f8cb873d1fc0524725b4..5d75a08829c78c05d7b5bac58986849383a90c3d 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TaskListsView.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TaskListsView.java @@ -17,22 +17,18 @@ package org.dmfs.opentaskspal.views; import android.content.ContentProviderClient; - import org.dmfs.android.contentpal.View; import org.dmfs.android.contentpal.views.BaseView; import org.dmfs.android.contentpal.views.DelegatingView; import org.dmfs.tasks.contract.TaskContract; - /** * {@link View} for the {@link TaskContract.TaskLists} table. * * @author Marten Gajda */ -public final class TaskListsView extends DelegatingView -{ - public TaskListsView(String authority, ContentProviderClient client) - { +public final class TaskListsView extends DelegatingView { + public TaskListsView(String authority, ContentProviderClient client) { super(new BaseView<>(client, TaskContract.TaskLists.getContentUri(authority))); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TasksView.java b/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TasksView.java index 986cac3e992665c1ce68cb45754010f8a3e85d0e..adb163a0d63fa722e17fb81e9e6d711f9fb4eb1b 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TasksView.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskspal/views/TasksView.java @@ -17,22 +17,18 @@ package org.dmfs.opentaskspal.views; import android.content.ContentProviderClient; - import org.dmfs.android.contentpal.View; import org.dmfs.android.contentpal.views.BaseView; import org.dmfs.android.contentpal.views.DelegatingView; import org.dmfs.tasks.contract.TaskContract; - /** * {@link View} for the {@link TaskContract.Tasks} table. * * @author Gabor Keszthelyi */ -public final class TasksView extends DelegatingView -{ - public TasksView(String authority, ContentProviderClient client) - { +public final class TasksView extends DelegatingView { + public TasksView(String authority, ContentProviderClient client) { super(new BaseView(client, TaskContract.Tasks.getContentUri(authority))); } } diff --git a/opentaskspal/src/main/java/org/dmfs/opentaskstestpal/InstanceTestData.java b/opentaskspal/src/main/java/org/dmfs/opentaskstestpal/InstanceTestData.java index 357faa2b1d9594aa10790325699eca1165a607e5..fabc134db643e0acafd01cf77e312a3149ad144b 100644 --- a/opentaskspal/src/main/java/org/dmfs/opentaskstestpal/InstanceTestData.java +++ b/opentaskspal/src/main/java/org/dmfs/opentaskstestpal/InstanceTestData.java @@ -16,8 +16,11 @@ package org.dmfs.opentaskstestpal; -import android.content.ContentProviderOperation; +import static org.dmfs.jems.optional.elementary.Absent.absent; +import android.content.ContentProviderOperation; +import androidx.annotation.NonNull; +import java.util.TimeZone; import org.dmfs.android.contentpal.RowData; import org.dmfs.android.contentpal.TransactionContext; import org.dmfs.jems.optional.Optional; @@ -28,83 +31,73 @@ import org.dmfs.jems.single.combined.Backed; import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract; -import java.util.TimeZone; - -import androidx.annotation.NonNull; - -import static org.dmfs.jems.optional.elementary.Absent.absent; - - /** - * {@link RowData} of the instance view. This sets all instance values except for {@link TaskContract.Instances#TASK_ID} as well as some instance specific task - * values. + * {@link RowData} of the instance view. This sets all instance values except + * for {@link TaskContract.Instances#TASK_ID} as well as some instance specific + * task values. + * *

- * Note: this is meant for use with an assert operation during tests as the instances table is read only and doesn't allow inserts nor updates. + * Note: this is meant for use with an assert operation during tests as the + * instances table is read only and doesn't allow inserts nor updates. * * @author Marten Gajda */ -public final class InstanceTestData implements RowData -{ +public final class InstanceTestData implements RowData { private final Optional mInstanceStart; private final Optional mInstanceDue; private final Optional mOriginalTime; private final int mDistanceFromCurrent; - - public InstanceTestData(int distanceFromCurrent) - { + public InstanceTestData(int distanceFromCurrent) { this(absent(), absent(), absent(), distanceFromCurrent); } - - public InstanceTestData(@NonNull DateTime instanceStart, @NonNull DateTime instanceDue, @NonNull Optional originalTime, int distanceFromCurrent) - { + public InstanceTestData(@NonNull DateTime instanceStart, @NonNull DateTime instanceDue, + @NonNull Optional originalTime, int distanceFromCurrent) { this(new Present<>(instanceStart), new Present<>(instanceDue), originalTime, distanceFromCurrent); } - - public InstanceTestData(@NonNull Optional instanceStart, @NonNull Optional instanceDue, @NonNull Optional originalTime, int distanceFromCurrent) - { + public InstanceTestData(@NonNull Optional instanceStart, @NonNull Optional instanceDue, + @NonNull Optional originalTime, int distanceFromCurrent) { mInstanceStart = instanceStart; mInstanceDue = instanceDue; mOriginalTime = originalTime; mDistanceFromCurrent = distanceFromCurrent; } - @NonNull @Override - public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, @NonNull ContentProviderOperation.Builder builder) - { + public ContentProviderOperation.Builder updatedBuilder(@NonNull TransactionContext transactionContext, + @NonNull ContentProviderOperation.Builder builder) { return builder - .withValue(TaskContract.Instances.INSTANCE_START, new Mapped<>(DateTime::getTimestamp, mInstanceStart).value(null)) - .withValue(TaskContract.Instances.INSTANCE_START_SORTING, new Mapped<>(this::toInstance, mInstanceStart).value(null)) - .withValue(TaskContract.Instances.INSTANCE_DUE, new Mapped<>(DateTime::getTimestamp, mInstanceDue).value(null)) - .withValue(TaskContract.Instances.INSTANCE_DUE_SORTING, new Mapped<>(this::toInstance, mInstanceDue).value(null)) + .withValue(TaskContract.Instances.INSTANCE_START, + new Mapped<>(DateTime::getTimestamp, mInstanceStart).value(null)) + .withValue(TaskContract.Instances.INSTANCE_START_SORTING, + new Mapped<>(this::toInstance, mInstanceStart).value(null)) + .withValue( + TaskContract.Instances.INSTANCE_DUE, new Mapped<>(DateTime::getTimestamp, mInstanceDue) + .value(null)) + .withValue(TaskContract.Instances.INSTANCE_DUE_SORTING, + new Mapped<>(this::toInstance, mInstanceDue).value(null)) .withValue(TaskContract.Instances.INSTANCE_DURATION, - new Backed<>( - new Zipped<>( - mInstanceStart, - mInstanceDue, - (start, due) -> (due.getTimestamp() - start.getTimestamp())), - () -> null) - .value()) - .withValue(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, new Mapped<>(DateTime::getTimestamp, mOriginalTime).value(null)) + new Backed<>(new Zipped<>(mInstanceStart, mInstanceDue, + (start, due) -> (due.getTimestamp() - start.getTimestamp())), () -> null).value()) + .withValue(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, + new Mapped<>(DateTime::getTimestamp, mOriginalTime).value(null)) .withValue(TaskContract.Instances.DISTANCE_FROM_CURRENT, mDistanceFromCurrent) - // the instances view overrides some of the task values. Since they are closely tied to the instance data we test them here as well. - .withValue(TaskContract.Instances.DTSTART, new Mapped<>(DateTime::getTimestamp, mInstanceStart).value(null)) + // the instances view overrides some of the task values. Since they are closely + // tied to the + // instance data we test them here as well. + .withValue(TaskContract.Instances.DTSTART, + new Mapped<>(DateTime::getTimestamp, mInstanceStart).value(null)) .withValue(TaskContract.Instances.DUE, new Mapped<>(DateTime::getTimestamp, mInstanceDue).value(null)) - .withValue(TaskContract.Instances.ORIGINAL_INSTANCE_TIME, new Mapped<>(DateTime::getTimestamp, mOriginalTime).value(null)) - .withValue(TaskContract.Instances.DURATION, null) - .withValue(TaskContract.Instances.RRULE, null) - .withValue(TaskContract.Instances.RDATE, null) - .withValue(TaskContract.Instances.EXDATE, null); + .withValue(TaskContract.Instances.ORIGINAL_INSTANCE_TIME, + new Mapped<>(DateTime::getTimestamp, mOriginalTime).value(null)) + .withValue(TaskContract.Instances.DURATION, null).withValue(TaskContract.Instances.RRULE, null) + .withValue(TaskContract.Instances.RDATE, null).withValue(TaskContract.Instances.EXDATE, null); } - - private long toInstance(DateTime dateTime) - { + private long toInstance(DateTime dateTime) { return (dateTime.isAllDay() ? dateTime : dateTime.shiftTimeZone(TimeZone.getDefault())).getInstance(); } - } diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/EffectiveDueDateTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/EffectiveDueDateTest.java index a6982422f399843edf2df4c032d2cb38082dbeb7..2858dfc14c9eff26509218ca5220da5f71d9e77f 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/EffectiveDueDateTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/EffectiveDueDateTest.java @@ -16,17 +16,6 @@ package org.dmfs.opentaskspal.readdata; -import org.dmfs.android.contentpal.RowDataSnapshot; -import org.dmfs.jems.hamcrest.matchers.optional.AbsentMatcher; -import org.dmfs.jems.optional.elementary.Present; -import org.dmfs.rfc5545.DateTime; -import org.dmfs.rfc5545.Duration; -import org.dmfs.tasks.contract.TaskContract.Tasks; -import org.junit.Test; - -import java.util.TimeZone; -import java.util.concurrent.TimeUnit; - import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static org.dmfs.jems.mockito.doubles.TestDoubles.failingMock; @@ -37,18 +26,25 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import java.util.TimeZone; +import java.util.concurrent.TimeUnit; +import org.dmfs.android.contentpal.RowDataSnapshot; +import org.dmfs.jems.hamcrest.matchers.optional.AbsentMatcher; +import org.dmfs.jems.optional.elementary.Present; +import org.dmfs.rfc5545.DateTime; +import org.dmfs.rfc5545.Duration; +import org.dmfs.tasks.contract.TaskContract.Tasks; +import org.junit.Test; /** * Unit test for {@link EffectiveDueDate}. * * @author Gabor Keszthelyi */ -public final class EffectiveDueDateTest -{ +public final class EffectiveDueDateTest { @Test - public void test_whenDueIsPresent_shouldUseThat() - { + public void test_whenDueIsPresent_shouldUseThat() { long timestamp = System.currentTimeMillis(); RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); @@ -62,10 +58,8 @@ public final class EffectiveDueDateTest assertEquals(timestamp, actual.getTimestamp()); } - @Test - public void test_whenDueIsAbsent_startIsAbsent_durationIsAbsent_shouldBeAbsent() - { + public void test_whenDueIsAbsent_startIsAbsent_durationIsAbsent_shouldBeAbsent() { RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); doReturn(absent()).when(mockData).data(eq(Tasks.DUE), any()); doReturn(absent()).when(mockData).data(eq(Tasks.DTSTART), any()); @@ -76,10 +70,8 @@ public final class EffectiveDueDateTest assertThat(new EffectiveDueDate(mockData), is(AbsentMatcher.absent())); } - @Test - public void test_whenDueIsAbsent_startIsPresent_durationIsAbsent_shouldBeAbsent() - { + public void test_whenDueIsAbsent_startIsPresent_durationIsAbsent_shouldBeAbsent() { RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); doReturn(absent()).when(mockData).data(eq(Tasks.DUE), any()); doReturn(new Present<>(234234)).when(mockData).data(eq(Tasks.DTSTART), any()); @@ -90,10 +82,8 @@ public final class EffectiveDueDateTest assertThat(new EffectiveDueDate(mockData), is(AbsentMatcher.absent())); } - @Test - public void test_whenDueIsAbsent_startIsAbsent_durationIsPresent_shouldBeAbsent() - { + public void test_whenDueIsAbsent_startIsAbsent_durationIsPresent_shouldBeAbsent() { RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); doReturn(absent()).when(mockData).data(eq(Tasks.DUE), any()); doReturn(absent()).when(mockData).data(eq(Tasks.DTSTART), any()); @@ -104,10 +94,8 @@ public final class EffectiveDueDateTest assertThat(new EffectiveDueDate(mockData), is(AbsentMatcher.absent())); } - @Test - public void test_whenDueIsAbsent_startIsPresent_durationIsPresent_shouldUseStartPlusDuration() - { + public void test_whenDueIsAbsent_startIsPresent_durationIsPresent_shouldUseStartPlusDuration() { long timestamp = System.currentTimeMillis(); RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); @@ -122,5 +110,4 @@ public final class EffectiveDueDateTest assertFalse(actual.isAllDay()); assertEquals("Europe/Berlin", actual.getTimeZone().getID()); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/EffectiveTaskColorTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/EffectiveTaskColorTest.java index a6628d754fa909e73a4e1c8000aec946d6e51a4c..c120368cceebe16ad3ba1479c3c65123dfa1a99b 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/EffectiveTaskColorTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/EffectiveTaskColorTest.java @@ -16,12 +16,6 @@ package org.dmfs.opentaskspal.readdata; -import org.dmfs.android.bolts.color.elementary.ValueColor; -import org.dmfs.android.contentpal.RowDataSnapshot; -import org.dmfs.jems.optional.elementary.Present; -import org.dmfs.tasks.contract.TaskContract.Tasks; -import org.junit.Test; - import static org.dmfs.jems.mockito.doubles.TestDoubles.failingMock; import static org.dmfs.optional.Absent.absent; import static org.hamcrest.CoreMatchers.is; @@ -30,18 +24,21 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import org.dmfs.android.bolts.color.elementary.ValueColor; +import org.dmfs.android.contentpal.RowDataSnapshot; +import org.dmfs.jems.optional.elementary.Present; +import org.dmfs.tasks.contract.TaskContract.Tasks; +import org.junit.Test; /** * Unit test for {@link EffectiveTaskColor}. * * @author Gabor Keszthelyi */ -public final class EffectiveTaskColorTest -{ +public final class EffectiveTaskColorTest { @Test - public void test_whenTaskColorIsPresent_shouldReturnThat() - { + public void test_whenTaskColorIsPresent_shouldReturnThat() { RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); doReturn(new Present<>(new ValueColor(123))).when(mockData).data(eq(Tasks.TASK_COLOR), any()); doReturn(absent()).when(mockData).data(eq(Tasks.LIST_COLOR), any()); @@ -49,10 +46,8 @@ public final class EffectiveTaskColorTest assertThat(new EffectiveTaskColor(mockData).argb(), is(123)); } - @Test - public void test_whenTaskColorIsAbsent_shouldReturnTaskListColor() - { + public void test_whenTaskColorIsAbsent_shouldReturnTaskListColor() { RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); doReturn(absent()).when(mockData).data(eq(Tasks.TASK_COLOR), any()); doReturn(new Present<>(new ValueColor(567))).when(mockData).data(eq(Tasks.LIST_COLOR), any()); @@ -60,15 +55,12 @@ public final class EffectiveTaskColorTest assertThat(new EffectiveTaskColor(mockData).argb(), is(567)); } - @Test(expected = Exception.class) - public void test_whenTaskColorAndListColorAreAbsent_shouldThrow() - { + public void test_whenTaskColorAndListColorAreAbsent_shouldThrow() { RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); doReturn(absent()).when(mockData).data(eq(Tasks.TASK_COLOR), any()); doReturn(absent()).when(mockData).data(eq(Tasks.LIST_COLOR), any()); new EffectiveTaskColor(mockData).argb(); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/TaskDateTimeTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/TaskDateTimeTest.java index 2e240aeb72fcb452ef8ff1e2d5dda083a036c284..e7529493549f125d01447b6afdcef091945ca468 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/TaskDateTimeTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/readdata/TaskDateTimeTest.java @@ -16,15 +16,6 @@ package org.dmfs.opentaskspal.readdata; -import org.dmfs.android.contentpal.RowDataSnapshot; -import org.dmfs.jems.hamcrest.matchers.optional.AbsentMatcher; -import org.dmfs.jems.optional.elementary.Present; -import org.dmfs.rfc5545.DateTime; -import org.dmfs.tasks.contract.TaskContract.Tasks; -import org.junit.Test; - -import java.util.TimeZone; - import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; @@ -36,28 +27,31 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import java.util.TimeZone; +import org.dmfs.android.contentpal.RowDataSnapshot; +import org.dmfs.jems.hamcrest.matchers.optional.AbsentMatcher; +import org.dmfs.jems.optional.elementary.Present; +import org.dmfs.rfc5545.DateTime; +import org.dmfs.tasks.contract.TaskContract.Tasks; +import org.junit.Test; /** * Unit test for {@link TaskDateTime}. * * @author Gabor Keszthelyi */ -public final class TaskDateTimeTest -{ +public final class TaskDateTimeTest { @Test - public void test_whenColumnValueIsAbsent_shouldBeAbsent() - { + public void test_whenColumnValueIsAbsent_shouldBeAbsent() { RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); doReturn(absent()).when(mockData).data(eq(Tasks.DTSTART), any()); assertThat(new TaskDateTime(Tasks.DTSTART, mockData), is(AbsentMatcher.absent())); } - @Test - public void test_whenIsAllDayIsPresentAndTrue_shouldReturnAllDayDateTime() - { + public void test_whenIsAllDayIsPresentAndTrue_shouldReturnAllDayDateTime() { long timeStamp = System.currentTimeMillis(); RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); @@ -69,10 +63,8 @@ public final class TaskDateTimeTest assertEquals(new DateTime(timeStamp).toAllDay(), actual); } - @Test - public void test_whenIsAllDayIsPresentAndFalse_shouldReturnNotAllDayDateTime() - { + public void test_whenIsAllDayIsPresentAndFalse_shouldReturnNotAllDayDateTime() { long timeStamp = System.currentTimeMillis(); RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); @@ -85,10 +77,8 @@ public final class TaskDateTimeTest assertEquals(timeStamp, actual.getTimestamp()); } - @Test - public void test_whenIsAllDayIsFalse_shouldReturnDateTimeWithTimeZoneShifted() - { + public void test_whenIsAllDayIsFalse_shouldReturnDateTimeWithTimeZoneShifted() { long timeStamp = System.currentTimeMillis(); RowDataSnapshot mockData = failingMock(RowDataSnapshot.class); @@ -101,5 +91,4 @@ public final class TaskDateTimeTest assertEquals(timeStamp, actual.getTimestamp()); assertEquals("Europe/Berlin", actual.getTimeZone().getID()); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/rowdata/DateTimeListDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/rowdata/DateTimeListDataTest.java index e302a3255e9bd23711346ffcb2c8933ac4817215..69da70804631e29518bbdcdd0eecccf3ca1ab5a6 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/rowdata/DateTimeListDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/rowdata/DateTimeListDataTest.java @@ -16,14 +16,6 @@ package org.dmfs.opentaskspal.rowdata; -import org.dmfs.iterables.SingletonIterable; -import org.dmfs.iterables.elementary.Seq; -import org.dmfs.rfc5545.DateTime; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; @@ -31,78 +23,61 @@ import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; import static org.dmfs.iterables.EmptyIterable.instance; import static org.junit.Assert.assertThat; +import org.dmfs.iterables.SingletonIterable; +import org.dmfs.iterables.elementary.Seq; +import org.dmfs.rfc5545.DateTime; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class DateTimeListDataTest -{ +public class DateTimeListDataTest { @Test - public void testEmpty() - { + public void testEmpty() { assertThat(new DateTimeListData<>("somefieldname", instance()), - builds( - withValuesOnly( - withNullValue("somefieldname")))); + builds(withValuesOnly(withNullValue("somefieldname")))); } - @Test - public void testSingle() - { - assertThat(new DateTimeListData<>("somefieldname", new SingletonIterable<>(DateTime.parse("Europe/Berlin", "20171212T123456"))), - builds( - withValuesOnly( - containing("somefieldname", "20171212T113456Z")))); + public void testSingle() { + assertThat( + new DateTimeListData<>("somefieldname", + new SingletonIterable<>(DateTime.parse("Europe/Berlin", "20171212T123456"))), + builds(withValuesOnly(containing("somefieldname", "20171212T113456Z")))); } - @Test - public void testSingleFloating() - { + public void testSingleFloating() { assertThat(new DateTimeListData<>("somefieldname", new SingletonIterable<>(DateTime.parse("20171212T123456"))), - builds( - withValuesOnly( - containing("somefieldname", "20171212T123456")))); + builds(withValuesOnly(containing("somefieldname", "20171212T123456")))); } - @Test - public void testSingleAllDay() - { + public void testSingleAllDay() { assertThat(new DateTimeListData<>("somefieldname", new SingletonIterable<>(DateTime.parse("20171212"))), - builds( - withValuesOnly( - containing("somefieldname", "20171212")))); + builds(withValuesOnly(containing("somefieldname", "20171212")))); } - @Test - public void testMulti1() - { - assertThat(new DateTimeListData<>("somefieldname", - new Seq<>( - DateTime.parse("Europe/Berlin", "20171212T123456"), + public void testMulti1() { + assertThat( + new DateTimeListData<>("somefieldname", + new Seq<>(DateTime.parse("Europe/Berlin", "20171212T123456"), DateTime.parse("UTC", "20171213T123456"))), - builds( - withValuesOnly( - containing("somefieldname", "20171212T113456Z,20171213T123456Z")))); + builds(withValuesOnly(containing("somefieldname", "20171212T113456Z,20171213T123456Z")))); } - @Test - public void testMulti2() - { + public void testMulti2() { assertThat(new DateTimeListData<>("somefieldname", - new Seq<>( - DateTime.parse("Europe/Berlin", "20171212T123456"), - DateTime.parse("UTC", "20171213T123456"), - DateTime.parse("America/New_York", "20171214T123456"))), - builds( - withValuesOnly( - containing("somefieldname", "20171212T113456Z,20171213T123456Z,20171214T173456Z")))); + new Seq<>(DateTime.parse("Europe/Berlin", "20171212T123456"), DateTime.parse("UTC", "20171213T123456"), + DateTime.parse("America/New_York", "20171214T123456"))), + builds(withValuesOnly( + containing("somefieldname", "20171212T113456Z,20171213T123456Z,20171214T173456Z")))); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/ColorDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/ColorDataTest.java index 702bc0303f7d4882c5771174ac6354545cc1a5b3..c21b35ddc13c333c217284d93192bb6d7958f888 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/ColorDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/ColorDataTest.java @@ -16,6 +16,11 @@ package org.dmfs.opentaskspal.tasklists; +import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; +import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; +import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; +import static org.junit.Assert.assertThat; + import org.dmfs.android.bolts.color.elementary.ValueColor; import org.dmfs.tasks.contract.TaskContract; import org.junit.Test; @@ -23,12 +28,6 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; -import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; -import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; -import static org.junit.Assert.assertThat; - - /** * Uinit test for {@link ColorData} * @@ -36,14 +35,10 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class ColorDataTest -{ +public class ColorDataTest { @Test - public void test() - { + public void test() { assertThat(new ColorData(new ValueColor(0x12345678)), - builds( - withValuesOnly( - containing(TaskContract.TaskLists.LIST_COLOR, 0x12345678)))); + builds(withValuesOnly(containing(TaskContract.TaskLists.LIST_COLOR, 0x12345678)))); } -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/NameDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/NameDataTest.java index 0ace850755f4a7f16b62b3c47902b5db01531d30..1f4c578388468956e138e7a13b82d1c4634818fe 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/NameDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/NameDataTest.java @@ -16,17 +16,16 @@ package org.dmfs.opentaskspal.tasklists; -import org.dmfs.tasks.contract.TaskContract; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; import static org.junit.Assert.assertThat; +import org.dmfs.tasks.contract.TaskContract; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** * Unit test for {@link NameData}. @@ -35,18 +34,12 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public final class NameDataTest -{ +public final class NameDataTest { @Test - public void test_thatNameIsAdded() - { - assertThat(new NameData("test"), - builds( - withValuesOnly( - containing(TaskContract.TaskLists.LIST_NAME, "test") - ))); + public void test_thatNameIsAdded() { + assertThat(new NameData("test"), builds(withValuesOnly(containing(TaskContract.TaskLists.LIST_NAME, "test")))); } // TODO Test for null validation? -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/OwnerDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/OwnerDataTest.java index abfb7f4ebefd3d45990f58fd024acd98b461bb17..1223fd785011d0e7bfaf7398d6b8dddb68461a27 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/OwnerDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/OwnerDataTest.java @@ -16,17 +16,16 @@ package org.dmfs.opentaskspal.tasklists; -import org.dmfs.tasks.contract.TaskContract; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; import static org.junit.Assert.assertThat; +import org.dmfs.tasks.contract.TaskContract; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** * Unit test for {@link OwnerData}. @@ -35,17 +34,11 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public final class OwnerDataTest -{ +public final class OwnerDataTest { @Test - public void test() - { - assertThat(new OwnerData("test"), - builds( - withValuesOnly( - containing(TaskContract.TaskLists.OWNER, "test") - ))); + public void test() { + assertThat(new OwnerData("test"), builds(withValuesOnly(containing(TaskContract.TaskLists.OWNER, "test")))); } // TODO Test for null validation? -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/SyncStatusDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/SyncStatusDataTest.java index 4dd12a452df3092ba3839d230a0f59fb517a3acc..5908f85f3f364ca4a49869f1a88be9c4d6dd25ef 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/SyncStatusDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/SyncStatusDataTest.java @@ -16,17 +16,16 @@ package org.dmfs.opentaskspal.tasklists; -import org.dmfs.tasks.contract.TaskContract; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; import static org.junit.Assert.assertThat; +import org.dmfs.tasks.contract.TaskContract; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** * Uinit test for {@link SyncStatusData} @@ -35,24 +34,15 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class SyncStatusDataTest -{ +public class SyncStatusDataTest { @Test - public void test() - { - assertThat(new SyncStatusData(), - builds( - withValuesOnly( - containing(TaskContract.TaskLists.SYNC_ENABLED, 1)))); + public void test() { + assertThat(new SyncStatusData(), builds(withValuesOnly(containing(TaskContract.TaskLists.SYNC_ENABLED, 1)))); assertThat(new SyncStatusData(true), - builds( - withValuesOnly( - containing(TaskContract.TaskLists.SYNC_ENABLED, 1)))); + builds(withValuesOnly(containing(TaskContract.TaskLists.SYNC_ENABLED, 1)))); assertThat(new SyncStatusData(false), - builds( - withValuesOnly( - containing(TaskContract.TaskLists.SYNC_ENABLED, 0)))); + builds(withValuesOnly(containing(TaskContract.TaskLists.SYNC_ENABLED, 0)))); } -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/VisibilityDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/VisibilityDataTest.java index 29c401d0564d231d1f491adb9691bc3e81992851..ac3d308aba058eae8ed4fcce53a52fad8dad0af8 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/VisibilityDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasklists/VisibilityDataTest.java @@ -16,17 +16,16 @@ package org.dmfs.opentaskspal.tasklists; -import org.dmfs.tasks.contract.TaskContract; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; import static org.junit.Assert.assertThat; +import org.dmfs.tasks.contract.TaskContract; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** * Uinit test for {@link VisibilityData} @@ -35,24 +34,13 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class VisibilityDataTest -{ +public class VisibilityDataTest { @Test - public void test() - { - assertThat(new VisibilityData(), - builds( - withValuesOnly( - containing(TaskContract.TaskLists.VISIBLE, 1)))); + public void test() { + assertThat(new VisibilityData(), builds(withValuesOnly(containing(TaskContract.TaskLists.VISIBLE, 1)))); - assertThat(new VisibilityData(true), - builds( - withValuesOnly( - containing(TaskContract.TaskLists.VISIBLE, 1)))); + assertThat(new VisibilityData(true), builds(withValuesOnly(containing(TaskContract.TaskLists.VISIBLE, 1)))); - assertThat(new VisibilityData(false), - builds( - withValuesOnly( - containing(TaskContract.TaskLists.VISIBLE, 0)))); + assertThat(new VisibilityData(false), builds(withValuesOnly(containing(TaskContract.TaskLists.VISIBLE, 0)))); } -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/DueDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/DueDataTest.java index cc6a99ed8382316c36edf5027cc699fe86292c63..32ebdf7a70935705eab441ab8f8d28fbc540e2c4 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/DueDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/DueDataTest.java @@ -16,21 +16,19 @@ package org.dmfs.opentaskspal.tasks; -import org.dmfs.rfc5545.DateTime; -import org.dmfs.tasks.contract.TaskContract.Tasks; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -import java.util.TimeZone; - import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; import static org.junit.Assert.assertThat; +import java.util.TimeZone; +import org.dmfs.rfc5545.DateTime; +import org.dmfs.tasks.contract.TaskContract.Tasks; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** * Unit test for {@link DueData}. @@ -39,57 +37,32 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public final class DueDataTest -{ +public final class DueDataTest { @Test - public void test_whenNoTimeZoneNotAllDay_setsValuesAccordingly_andNullsOtherTimeRelatedValues() - { + public void test_whenNoTimeZoneNotAllDay_setsValuesAccordingly_andNullsOtherTimeRelatedValues() { DateTime due = DateTime.now(); assertThat(new DueData<>(due), - builds( - withValuesOnly( - containing(Tasks.DUE, due.getTimestamp()), - containing(Tasks.TZ, "UTC"), - containing(Tasks.IS_ALLDAY, 0), - withNullValue(Tasks.DTSTART), - withNullValue(Tasks.DURATION) - ))); + builds(withValuesOnly(containing(Tasks.DUE, due.getTimestamp()), containing(Tasks.TZ, "UTC"), + containing(Tasks.IS_ALLDAY, 0), withNullValue(Tasks.DTSTART), withNullValue(Tasks.DURATION)))); } - @Test - public void test_whenHasTimeZoneNotAllDay_setsValuesAccordingly_andNullsOtherTimeRelatedValues() - { + public void test_whenHasTimeZoneNotAllDay_setsValuesAccordingly_andNullsOtherTimeRelatedValues() { DateTime due = DateTime.now().shiftTimeZone(TimeZone.getTimeZone("GMT+4")); assertThat(new DueData<>(due), - builds( - withValuesOnly( - containing(Tasks.DUE, due.getTimestamp()), - containing(Tasks.TZ, "GMT+04:00"), - containing(Tasks.IS_ALLDAY, 0), - withNullValue(Tasks.DTSTART), - withNullValue(Tasks.DURATION) - ))); + builds(withValuesOnly(containing(Tasks.DUE, due.getTimestamp()), containing(Tasks.TZ, "GMT+04:00"), + containing(Tasks.IS_ALLDAY, 0), withNullValue(Tasks.DTSTART), withNullValue(Tasks.DURATION)))); } - @Test - public void test_whenNoTimeZoneAndAllDay_setsValuesAccordingly_andNullsOtherTimeRelatedValues() - { + public void test_whenNoTimeZoneAndAllDay_setsValuesAccordingly_andNullsOtherTimeRelatedValues() { DateTime due = DateTime.now().toAllDay(); assertThat(new DueData<>(due), - builds( - withValuesOnly( - containing(Tasks.DUE, due.getTimestamp()), - containing(Tasks.TZ, "UTC"), - containing(Tasks.IS_ALLDAY, 1), - withNullValue(Tasks.DTSTART), - withNullValue(Tasks.DURATION) - ))); + builds(withValuesOnly(containing(Tasks.DUE, due.getTimestamp()), containing(Tasks.TZ, "UTC"), + containing(Tasks.IS_ALLDAY, 1), withNullValue(Tasks.DTSTART), withNullValue(Tasks.DURATION)))); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/ExDatesTaskDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/ExDatesTaskDataTest.java index ef56baf8295070d80929a7a98426bc3204fc28f6..59afce25dade00c7b357b92605df00c7bbf8ef99 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/ExDatesTaskDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/ExDatesTaskDataTest.java @@ -16,6 +16,13 @@ package org.dmfs.opentaskspal.tasks; +import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; +import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; +import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; +import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; +import static org.dmfs.iterables.EmptyIterable.instance; +import static org.junit.Assert.assertThat; + import org.dmfs.iterables.SingletonIterable; import org.dmfs.iterables.elementary.Seq; import org.dmfs.rfc5545.DateTime; @@ -25,85 +32,48 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; -import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; -import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; -import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; -import static org.dmfs.iterables.EmptyIterable.instance; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class ExDatesTaskDataTest -{ +public class ExDatesTaskDataTest { @Test - public void testEmpty() - { - assertThat(new ExDatesTaskData(instance()), - builds( - withValuesOnly( - withNullValue(TaskContract.Tasks.EXDATE)))); + public void testEmpty() { + assertThat(new ExDatesTaskData(instance()), builds(withValuesOnly(withNullValue(TaskContract.Tasks.EXDATE)))); } - @Test - public void testSingle() - { + public void testSingle() { assertThat(new ExDatesTaskData(new SingletonIterable<>(DateTime.parse("Europe/Berlin", "20171212T123456"))), - builds( - withValuesOnly( - containing(TaskContract.Tasks.EXDATE, "20171212T113456Z")))); + builds(withValuesOnly(containing(TaskContract.Tasks.EXDATE, "20171212T113456Z")))); } - @Test - public void testSingleFloating() - { + public void testSingleFloating() { assertThat(new ExDatesTaskData(new SingletonIterable<>(DateTime.parse("20171212T123456"))), - builds( - withValuesOnly( - containing(TaskContract.Tasks.EXDATE, "20171212T123456")))); + builds(withValuesOnly(containing(TaskContract.Tasks.EXDATE, "20171212T123456")))); } - @Test - public void testSingleAllDay() - { + public void testSingleAllDay() { assertThat(new ExDatesTaskData(new SingletonIterable<>(DateTime.parse("20171212"))), - builds( - withValuesOnly( - containing(TaskContract.Tasks.EXDATE, "20171212")))); + builds(withValuesOnly(containing(TaskContract.Tasks.EXDATE, "20171212")))); } - @Test - public void testMulti1() - { - assertThat(new ExDatesTaskData( - new Seq<>( - DateTime.parse("Europe/Berlin", "20171212T123456"), - DateTime.parse("UTC", "20171213T123456"))), - builds( - withValuesOnly( - containing(TaskContract.Tasks.EXDATE, "20171212T113456Z,20171213T123456Z")))); + public void testMulti1() { + assertThat( + new ExDatesTaskData(new Seq<>(DateTime.parse("Europe/Berlin", "20171212T123456"), + DateTime.parse("UTC", "20171213T123456"))), + builds(withValuesOnly(containing(TaskContract.Tasks.EXDATE, "20171212T113456Z,20171213T123456Z")))); } - @Test - public void testMulti2() - { - assertThat(new ExDatesTaskData( - new Seq<>( - DateTime.parse("Europe/Berlin", "20171212T123456"), - DateTime.parse("UTC", "20171213T123456"), - DateTime.parse("America/New_York", "20171214T123456"))), - builds( - withValuesOnly( - containing(TaskContract.Tasks.EXDATE, "20171212T113456Z,20171213T123456Z,20171214T173456Z")))); + public void testMulti2() { + assertThat(new ExDatesTaskData(new Seq<>(DateTime.parse("Europe/Berlin", "20171212T123456"), + DateTime.parse("UTC", "20171213T123456"), DateTime.parse("America/New_York", "20171214T123456"))), + builds(withValuesOnly( + containing(TaskContract.Tasks.EXDATE, "20171212T113456Z,20171213T123456Z,20171214T173456Z")))); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/NoTimeDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/NoTimeDataTest.java index dc6ee49864c52ae7e5dae9ad0a7d5c31ed3ccb9e..0e0c441a5b0418f0ded3c477e50fcb4210f0b705 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/NoTimeDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/NoTimeDataTest.java @@ -16,17 +16,16 @@ package org.dmfs.opentaskspal.tasks; -import org.dmfs.tasks.contract.TaskContract.Tasks; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; import static org.junit.Assert.assertThat; +import org.dmfs.tasks.contract.TaskContract.Tasks; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** * Unit test for {@link NoTimeData}. @@ -35,27 +34,13 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public final class NoTimeDataTest -{ +public final class NoTimeDataTest { @Test - public void test_thatAllTimeRelatedValuesAreNulled() - { + public void test_thatAllTimeRelatedValuesAreNulled() { assertThat(new NoTimeData(), - builds( - withValuesOnly( - withNullValue(Tasks.DTSTART), - withNullValue(Tasks.TZ), - withNullValue(Tasks.IS_ALLDAY), - - withNullValue(Tasks.DUE), - - withNullValue(Tasks.DURATION), - - withNullValue(Tasks.RDATE), - withNullValue(Tasks.RRULE), - withNullValue(Tasks.EXDATE) - ))); + builds(withValuesOnly(withNullValue(Tasks.DTSTART), withNullValue(Tasks.TZ), + withNullValue(Tasks.IS_ALLDAY), withNullValue(Tasks.DUE), withNullValue(Tasks.DURATION), + withNullValue(Tasks.RDATE), withNullValue(Tasks.RRULE), withNullValue(Tasks.EXDATE)))); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/OriginalInstanceSyncIdDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/OriginalInstanceSyncIdDataTest.java index d4085dfe62c3c67856513fdbc328d607b528b348..0417fbaed58919979e9d477033d9e2317971b9fa 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/OriginalInstanceSyncIdDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/OriginalInstanceSyncIdDataTest.java @@ -16,6 +16,11 @@ package org.dmfs.opentaskspal.tasks; +import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; +import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; +import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; +import static org.junit.Assert.assertThat; + import org.dmfs.rfc5545.DateTime; import org.dmfs.tasks.contract.TaskContract.Tasks; import org.junit.Test; @@ -23,12 +28,6 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; -import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; -import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; -import static org.junit.Assert.assertThat; - - /** * Unit test for {@link OriginalInstanceSyncIdData}. * @@ -36,18 +35,13 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public final class OriginalInstanceSyncIdDataTest -{ +public final class OriginalInstanceSyncIdDataTest { @Test - public void test_thatOriginalSyncIdIsAdded() - { + public void test_thatOriginalSyncIdIsAdded() { assertThat(new OriginalInstanceSyncIdData("test", DateTime.parse("20180103")), - builds( - withValuesOnly( - containing(Tasks.ORIGINAL_INSTANCE_SYNC_ID, "test"), - containing(Tasks.ORIGINAL_INSTANCE_TIME, DateTime.parse("20180103").getTimestamp()) - ))); + builds(withValuesOnly(containing(Tasks.ORIGINAL_INSTANCE_SYNC_ID, "test"), + containing(Tasks.ORIGINAL_INSTANCE_TIME, DateTime.parse("20180103").getTimestamp())))); } // TODO Test for null validation? -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/PropertyDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/PropertyDataTest.java index 5b4bf7969e0e92dfe02448ab3bed097d6299621e..97515573fd47d13f47a2e51b81d82c235fd215a1 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/PropertyDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/PropertyDataTest.java @@ -16,17 +16,16 @@ package org.dmfs.opentaskspal.tasks; -import org.dmfs.tasks.contract.TaskContract; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; import static org.junit.Assert.assertThat; +import org.dmfs.tasks.contract.TaskContract; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** * Unit test for {@link PropertyData} @@ -35,21 +34,13 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class PropertyDataTest -{ +public class PropertyDataTest { @Test - public void test() - { + public void test() { assertThat(new PropertyData("test", (context, builder) -> builder), - builds( - withValuesOnly( - containing(TaskContract.Properties.MIMETYPE, "test")))); - - assertThat(new PropertyData("test", (context, builder) -> builder.withValue("key", "value")), - builds( - withValuesOnly( - containing(TaskContract.Properties.MIMETYPE, "test"), - containing("key", "value")))); + builds(withValuesOnly(containing(TaskContract.Properties.MIMETYPE, "test")))); + assertThat(new PropertyData("test", (context, builder) -> builder.withValue("key", "value")), builds( + withValuesOnly(containing(TaskContract.Properties.MIMETYPE, "test"), containing("key", "value")))); } -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RDatesTaskDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RDatesTaskDataTest.java index cd68246b9011bdf12e5e50dd1b8c08a2efaee3a9..902aa32a9baa814d2851ab64c86c40e8155a6e84 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RDatesTaskDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RDatesTaskDataTest.java @@ -16,6 +16,13 @@ package org.dmfs.opentaskspal.tasks; +import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; +import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; +import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; +import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; +import static org.dmfs.iterables.EmptyIterable.instance; +import static org.junit.Assert.assertThat; + import org.dmfs.iterables.SingletonIterable; import org.dmfs.iterables.elementary.Seq; import org.dmfs.rfc5545.DateTime; @@ -25,85 +32,48 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; -import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; -import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; -import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; -import static org.dmfs.iterables.EmptyIterable.instance; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class RDatesTaskDataTest -{ +public class RDatesTaskDataTest { @Test - public void testEmpty() - { - assertThat(new RDatesTaskData(instance()), - builds( - withValuesOnly( - withNullValue(TaskContract.Tasks.RDATE)))); + public void testEmpty() { + assertThat(new RDatesTaskData(instance()), builds(withValuesOnly(withNullValue(TaskContract.Tasks.RDATE)))); } - @Test - public void testSingle() - { + public void testSingle() { assertThat(new RDatesTaskData(new SingletonIterable<>(DateTime.parse("Europe/Berlin", "20171212T123456"))), - builds( - withValuesOnly( - containing(TaskContract.Tasks.RDATE, "20171212T113456Z")))); + builds(withValuesOnly(containing(TaskContract.Tasks.RDATE, "20171212T113456Z")))); } - @Test - public void testSingleFloating() - { + public void testSingleFloating() { assertThat(new RDatesTaskData(new SingletonIterable<>(DateTime.parse("20171212T123456"))), - builds( - withValuesOnly( - containing(TaskContract.Tasks.RDATE, "20171212T123456")))); + builds(withValuesOnly(containing(TaskContract.Tasks.RDATE, "20171212T123456")))); } - @Test - public void testSingleAllDay() - { + public void testSingleAllDay() { assertThat(new RDatesTaskData(new SingletonIterable<>(DateTime.parse("20171212"))), - builds( - withValuesOnly( - containing(TaskContract.Tasks.RDATE, "20171212")))); + builds(withValuesOnly(containing(TaskContract.Tasks.RDATE, "20171212")))); } - @Test - public void testMulti1() - { - assertThat(new RDatesTaskData( - new Seq<>( - DateTime.parse("Europe/Berlin", "20171212T123456"), - DateTime.parse("UTC", "20171213T123456"))), - builds( - withValuesOnly( - containing(TaskContract.Tasks.RDATE, "20171212T113456Z,20171213T123456Z")))); + public void testMulti1() { + assertThat( + new RDatesTaskData(new Seq<>(DateTime.parse("Europe/Berlin", "20171212T123456"), + DateTime.parse("UTC", "20171213T123456"))), + builds(withValuesOnly(containing(TaskContract.Tasks.RDATE, "20171212T113456Z,20171213T123456Z")))); } - @Test - public void testMulti2() - { - assertThat(new RDatesTaskData( - new Seq<>( - DateTime.parse("Europe/Berlin", "20171212T123456"), - DateTime.parse("UTC", "20171213T123456"), - DateTime.parse("America/New_York", "20171214T123456"))), - builds( - withValuesOnly( - containing(TaskContract.Tasks.RDATE, "20171212T113456Z,20171213T123456Z,20171214T173456Z")))); + public void testMulti2() { + assertThat(new RDatesTaskData(new Seq<>(DateTime.parse("Europe/Berlin", "20171212T123456"), + DateTime.parse("UTC", "20171213T123456"), DateTime.parse("America/New_York", "20171214T123456"))), + builds(withValuesOnly( + containing(TaskContract.Tasks.RDATE, "20171212T113456Z,20171213T123456Z,20171214T173456Z")))); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RRuleTaskDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RRuleTaskDataTest.java index 17f607aaadc398845d7638d4ca78c1904e6d4ad5..f01ed5cfe159bd9835ad8ec71bea8c78b7721276 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RRuleTaskDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RRuleTaskDataTest.java @@ -16,6 +16,11 @@ package org.dmfs.opentaskspal.tasks; +import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; +import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; +import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; +import static org.junit.Assert.assertThat; + import org.dmfs.rfc5545.recur.RecurrenceRule; import org.dmfs.tasks.contract.TaskContract; import org.junit.Test; @@ -23,27 +28,16 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; -import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; -import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class RRuleTaskDataTest -{ +public class RRuleTaskDataTest { @Test - public void test() throws Exception - { - assertThat(new RRuleTaskData(new RecurrenceRule("FREQ=MONTHLY;BYMONTHDAY=12", RecurrenceRule.RfcMode.RFC2445_LAX)), - builds( - withValuesOnly( - containing(TaskContract.Tasks.RRULE, "FREQ=MONTHLY;BYMONTHDAY=12")))); - + public void test() throws Exception { + assertThat( + new RRuleTaskData(new RecurrenceRule("FREQ=MONTHLY;BYMONTHDAY=12", RecurrenceRule.RfcMode.RFC2445_LAX)), + builds(withValuesOnly(containing(TaskContract.Tasks.RRULE, "FREQ=MONTHLY;BYMONTHDAY=12")))); } - -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RelationDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RelationDataTest.java index 3850b97e232f21bfe68b6d1062113f17b9fccd31..75b62577e00bf6f8fab0416998b59c954ef63e40 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RelationDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/RelationDataTest.java @@ -16,8 +16,14 @@ package org.dmfs.opentaskspal.tasks; -import android.net.Uri; +import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; +import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; +import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; +import static org.dmfs.jems.mockito.doubles.TestDoubles.failingMock; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.doReturn; +import android.net.Uri; import org.dmfs.android.contentpal.RowSnapshot; import org.dmfs.android.contentpal.references.RowUriReference; import org.dmfs.tasks.contract.TaskContract; @@ -26,14 +32,6 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; -import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; -import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; -import static org.dmfs.jems.mockito.doubles.TestDoubles.failingMock; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.doReturn; - - /** * Unit test for {@link RelationData} * @@ -41,31 +39,25 @@ import static org.mockito.Mockito.doReturn; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class RelationDataTest -{ +public class RelationDataTest { @Test - public void test() - { + public void test() { RowSnapshot child = failingMock(RowSnapshot.class); RowSnapshot parent = failingMock(RowSnapshot.class); doReturn(new RowUriReference<>(Uri.parse("content://tasks/123"))).when(parent).reference(); doReturn(new RowUriReference<>(Uri.parse("content://tasks/124"))).when(child).reference(); - assertThat(new RelationData(parent, TaskContract.Property.Relation.RELTYPE_CHILD, child), - builds( - withValuesOnly( - containing(TaskContract.Property.Relation.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - containing(TaskContract.Property.Relation.RELATED_TYPE, TaskContract.Property.Relation.RELTYPE_CHILD), - containing(TaskContract.Property.Relation.TASK_ID, 123L), - containing(TaskContract.Property.Relation.RELATED_ID, 124L)))); - - assertThat(new RelationData(parent, TaskContract.Property.Relation.RELTYPE_CHILD, "xyz"), - builds( - withValuesOnly( - containing(TaskContract.Property.Relation.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), - containing(TaskContract.Property.Relation.RELATED_TYPE, TaskContract.Property.Relation.RELTYPE_CHILD), - containing(TaskContract.Property.Relation.TASK_ID, 123L), - containing(TaskContract.Property.Relation.RELATED_UID, "xyz")))); + assertThat(new RelationData(parent, TaskContract.Property.Relation.RELTYPE_CHILD, child), builds(withValuesOnly( + containing(TaskContract.Property.Relation.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + containing(TaskContract.Property.Relation.RELATED_TYPE, TaskContract.Property.Relation.RELTYPE_CHILD), + containing(TaskContract.Property.Relation.TASK_ID, 123L), + containing(TaskContract.Property.Relation.RELATED_ID, 124L)))); + + assertThat(new RelationData(parent, TaskContract.Property.Relation.RELTYPE_CHILD, "xyz"), builds(withValuesOnly( + containing(TaskContract.Property.Relation.MIMETYPE, TaskContract.Property.Relation.CONTENT_ITEM_TYPE), + containing(TaskContract.Property.Relation.RELATED_TYPE, TaskContract.Property.Relation.RELTYPE_CHILD), + containing(TaskContract.Property.Relation.TASK_ID, 123L), + containing(TaskContract.Property.Relation.RELATED_UID, "xyz")))); } -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/SyncIdDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/SyncIdDataTest.java index 666f8b37cd706e66e05008e11df16b1f2fde2f77..4d25419faa4c69c4524e08bdc788dde28564e81f 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/SyncIdDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/SyncIdDataTest.java @@ -16,17 +16,16 @@ package org.dmfs.opentaskspal.tasks; -import org.dmfs.tasks.contract.TaskContract.Tasks; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; import static org.junit.Assert.assertThat; +import org.dmfs.tasks.contract.TaskContract.Tasks; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** * Unit test for {@link SyncIdData}. @@ -35,17 +34,11 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public final class SyncIdDataTest -{ +public final class SyncIdDataTest { @Test - public void test_thatSyncIdIsAdded() - { - assertThat(new SyncIdData("test"), - builds( - withValuesOnly( - containing(Tasks._SYNC_ID, "test") - ))); + public void test_thatSyncIdIsAdded() { + assertThat(new SyncIdData("test"), builds(withValuesOnly(containing(Tasks._SYNC_ID, "test")))); } // TODO Test for null validation? -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/TimeDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/TimeDataTest.java index f9c767532bc37b0a32d73eb7a2c075a8b21a4218..8f48ab3441bf178459b4f414a17defefd0eb2577 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/TimeDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/TimeDataTest.java @@ -16,8 +16,15 @@ package org.dmfs.opentaskspal.tasks; -import android.content.ContentProviderOperation; +import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; +import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; +import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; +import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.mock; +import android.content.ContentProviderOperation; +import java.util.TimeZone; import org.dmfs.android.contentpal.TransactionContext; import org.dmfs.rfc5545.DateTime; import org.dmfs.rfc5545.Duration; @@ -27,16 +34,6 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import java.util.TimeZone; - -import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; -import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; -import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; -import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.mock; - - /** * Unit test for {@link TimeData}. * @@ -44,111 +41,71 @@ import static org.mockito.Mockito.mock; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public final class TimeDataTest -{ +public final class TimeDataTest { @Test - public void test_whenStartAndDueAreProvided_setsThemAndNullsDuration() - { + public void test_whenStartAndDueAreProvided_setsThemAndNullsDuration() { DateTime start = DateTime.now(); DateTime due = start.addDuration(new Duration(1, 1, 0)); assertThat(new TimeData<>(start, due), - builds( - withValuesOnly( - containing(Tasks.DTSTART, start.getTimestamp()), - containing(Tasks.TZ, "UTC"), - containing(Tasks.IS_ALLDAY, 0), - containing(Tasks.DUE, due.getTimestamp()), - withNullValue(Tasks.DURATION) - ))); + builds(withValuesOnly(containing(Tasks.DTSTART, start.getTimestamp()), containing(Tasks.TZ, "UTC"), + containing(Tasks.IS_ALLDAY, 0), containing(Tasks.DUE, due.getTimestamp()), + withNullValue(Tasks.DURATION)))); } - @Test - public void test_whenStartAndDurationAreProvided_setsThemAndNullsDue() - { + public void test_whenStartAndDurationAreProvided_setsThemAndNullsDue() { DateTime start = DateTime.now(); Duration duration = new Duration(1, 3, 0); assertThat(new TimeData<>(start, duration), - builds( - withValuesOnly( - containing(Tasks.DTSTART, start.getTimestamp()), - containing(Tasks.TZ, "UTC"), - containing(Tasks.IS_ALLDAY, 0), - withNullValue(Tasks.DUE), - containing(Tasks.DURATION, duration.toString()) - ))); + builds(withValuesOnly(containing(Tasks.DTSTART, start.getTimestamp()), containing(Tasks.TZ, "UTC"), + containing(Tasks.IS_ALLDAY, 0), withNullValue(Tasks.DUE), + containing(Tasks.DURATION, duration.toString())))); } - @Test - public void test_whenOnlyStartIsProvided_setsItAndNullsDueAndDuration() - { + public void test_whenOnlyStartIsProvided_setsItAndNullsDueAndDuration() { DateTime start = DateTime.now(); assertThat(new TimeData<>(start), - builds( - withValuesOnly( - containing(Tasks.DTSTART, start.getTimestamp()), - containing(Tasks.TZ, "UTC"), - containing(Tasks.IS_ALLDAY, 0), - withNullValue(Tasks.DUE), - withNullValue(Tasks.DURATION) - ))); + builds(withValuesOnly(containing(Tasks.DTSTART, start.getTimestamp()), containing(Tasks.TZ, "UTC"), + containing(Tasks.IS_ALLDAY, 0), withNullValue(Tasks.DUE), withNullValue(Tasks.DURATION)))); } - @Test(expected = IllegalArgumentException.class) - public void test_whenStartIsAllDayAndDueIsNot_throwsIllegalArgument() - { - new TimeData<>(DateTime.now().toAllDay(), DateTime.now()) - .updatedBuilder(mock(TransactionContext.class), mock(ContentProviderOperation.Builder.class)); + public void test_whenStartIsAllDayAndDueIsNot_throwsIllegalArgument() { + new TimeData<>(DateTime.now().toAllDay(), DateTime.now()).updatedBuilder(mock(TransactionContext.class), + mock(ContentProviderOperation.Builder.class)); } - @Test(expected = IllegalArgumentException.class) - public void test_whenDueIsAllDayAndStartIsNot_throwsIllegalArgument() - { - new TimeData<>(DateTime.now(), DateTime.now().toAllDay()) - .updatedBuilder(mock(TransactionContext.class), mock(ContentProviderOperation.Builder.class)); + public void test_whenDueIsAllDayAndStartIsNot_throwsIllegalArgument() { + new TimeData<>(DateTime.now(), DateTime.now().toAllDay()).updatedBuilder(mock(TransactionContext.class), + mock(ContentProviderOperation.Builder.class)); } - @Test - public void test_whenStartHasDifferentTimeZoneFromDue_shiftsStartsToDue() - { + public void test_whenStartHasDifferentTimeZoneFromDue_shiftsStartsToDue() { DateTime start = DateTime.now().swapTimeZone(TimeZone.getTimeZone("GMT+3")); DateTime due = start.addDuration(new Duration(1, 3, 0)).swapTimeZone(TimeZone.getTimeZone("GMT+6")); DateTime startExpected = start.shiftTimeZone(TimeZone.getTimeZone("GMT+6")); assertThat(new TimeData<>(start, due), - builds( - withValuesOnly( - containing(Tasks.DTSTART, startExpected.getTimestamp()), - containing(Tasks.TZ, "GMT+06:00"), - containing(Tasks.IS_ALLDAY, 0), - containing(Tasks.DUE, due.getTimestamp()), - withNullValue(Tasks.DURATION) - ))); + builds(withValuesOnly(containing(Tasks.DTSTART, startExpected.getTimestamp()), + containing(Tasks.TZ, "GMT+06:00"), containing(Tasks.IS_ALLDAY, 0), + containing(Tasks.DUE, due.getTimestamp()), withNullValue(Tasks.DURATION)))); } - @Test - public void test_whenStartHasAllDayFlag_correspondingValueIsOne() - { + public void test_whenStartHasAllDayFlag_correspondingValueIsOne() { DateTime start = DateTime.now().toAllDay(); DateTime due = start.addDuration(new Duration(1, 3, 0)); assertThat(new TimeData<>(start, due), - builds( - withValuesOnly( - containing(Tasks.DTSTART, start.getTimestamp()), - containing(Tasks.TZ, "UTC"), - containing(Tasks.IS_ALLDAY, 1), - containing(Tasks.DUE, due.getTimestamp()), - withNullValue(Tasks.DURATION) - ))); + builds(withValuesOnly(containing(Tasks.DTSTART, start.getTimestamp()), containing(Tasks.TZ, "UTC"), + containing(Tasks.IS_ALLDAY, 1), containing(Tasks.DUE, due.getTimestamp()), + withNullValue(Tasks.DURATION)))); } -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/TitleDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/TitleDataTest.java index ce5b096f45af5e801874be0ea149aab6ca159ec2..9d0a0a89783ae266a4c3807d2e994a5c939c247e 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/TitleDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskspal/tasks/TitleDataTest.java @@ -16,17 +16,16 @@ package org.dmfs.opentaskspal.tasks; -import org.dmfs.tasks.contract.TaskContract.Tasks; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; import static org.junit.Assert.assertThat; +import org.dmfs.tasks.contract.TaskContract.Tasks; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** * Unit test for {@link TitleData}. @@ -35,17 +34,11 @@ import static org.junit.Assert.assertThat; */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public final class TitleDataTest -{ +public final class TitleDataTest { @Test - public void test_thatTitleIsAdded() - { - assertThat(new TitleData("test"), - builds( - withValuesOnly( - containing(Tasks.TITLE, "test") - ))); + public void test_thatTitleIsAdded() { + assertThat(new TitleData("test"), builds(withValuesOnly(containing(Tasks.TITLE, "test")))); } // TODO Test for null validation? -} \ No newline at end of file +} diff --git a/opentaskspal/src/test/java/org/dmfs/opentaskstestpal/InstanceTestDataTest.java b/opentaskspal/src/test/java/org/dmfs/opentaskstestpal/InstanceTestDataTest.java index 860c23f1c1f9fa35f831fa85226c9e7f6e78d334..ea2b78975d9d95765c407c6308c81b046f91b2c7 100644 --- a/opentaskspal/src/test/java/org/dmfs/opentaskstestpal/InstanceTestDataTest.java +++ b/opentaskspal/src/test/java/org/dmfs/opentaskstestpal/InstanceTestDataTest.java @@ -16,6 +16,14 @@ package org.dmfs.opentaskstestpal; +import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; +import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; +import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; +import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; +import static org.dmfs.jems.optional.elementary.Absent.absent; +import static org.junit.Assert.assertThat; + +import java.util.TimeZone; import org.dmfs.jems.optional.elementary.Present; import org.dmfs.rfc5545.DateTime; import org.dmfs.rfc5545.Duration; @@ -25,153 +33,108 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; -import java.util.TimeZone; - -import static org.dmfs.android.contentpal.testing.contentoperationbuilder.WithValues.withValuesOnly; -import static org.dmfs.android.contentpal.testing.contentvalues.Containing.containing; -import static org.dmfs.android.contentpal.testing.contentvalues.NullValue.withNullValue; -import static org.dmfs.android.contentpal.testing.rowdata.RowDataMatcher.builds; -import static org.dmfs.jems.optional.elementary.Absent.absent; -import static org.junit.Assert.assertThat; - - /** * @author Marten Gajda */ @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class InstanceTestDataTest -{ +public class InstanceTestDataTest { @Test - public void testNoDate() - { + public void testNoDate() { assertThat(new InstanceTestData(5), - builds( - withValuesOnly( - withNullValue(TaskContract.Instances.INSTANCE_START), - withNullValue(TaskContract.Instances.INSTANCE_START_SORTING), - withNullValue(TaskContract.Instances.INSTANCE_DUE), - withNullValue(TaskContract.Instances.INSTANCE_DUE_SORTING), - withNullValue(TaskContract.Instances.INSTANCE_DURATION), - withNullValue(TaskContract.Instances.INSTANCE_ORIGINAL_TIME), - containing(TaskContract.Instances.DISTANCE_FROM_CURRENT, 5), - withNullValue(TaskContract.Instances.DTSTART), - withNullValue(TaskContract.Instances.DUE), - withNullValue(TaskContract.Instances.ORIGINAL_INSTANCE_TIME), - withNullValue(TaskContract.Instances.DURATION), - withNullValue(TaskContract.Instances.RRULE), - withNullValue(TaskContract.Instances.RDATE), - withNullValue(TaskContract.Instances.EXDATE) - ) - )); + builds(withValuesOnly(withNullValue(TaskContract.Instances.INSTANCE_START), + withNullValue(TaskContract.Instances.INSTANCE_START_SORTING), + withNullValue(TaskContract.Instances.INSTANCE_DUE), + withNullValue(TaskContract.Instances.INSTANCE_DUE_SORTING), + withNullValue(TaskContract.Instances.INSTANCE_DURATION), + withNullValue(TaskContract.Instances.INSTANCE_ORIGINAL_TIME), + containing(TaskContract.Instances.DISTANCE_FROM_CURRENT, 5), + withNullValue(TaskContract.Instances.DTSTART), withNullValue(TaskContract.Instances.DUE), + withNullValue(TaskContract.Instances.ORIGINAL_INSTANCE_TIME), + withNullValue(TaskContract.Instances.DURATION), withNullValue(TaskContract.Instances.RRULE), + withNullValue(TaskContract.Instances.RDATE), withNullValue(TaskContract.Instances.EXDATE)))); } - @Test - public void testWithDate() - { + public void testWithDate() { DateTime start = DateTime.now(); DateTime due = start.addDuration(Duration.parse("P1DT1H")); assertThat(new InstanceTestData(start, due, absent(), 5), - builds( - withValuesOnly( - containing(TaskContract.Instances.INSTANCE_START, start.getTimestamp()), - containing(TaskContract.Instances.INSTANCE_START_SORTING, start.shiftTimeZone(TimeZone.getDefault()).getInstance()), - containing(TaskContract.Instances.INSTANCE_DUE, due.getTimestamp()), - containing(TaskContract.Instances.INSTANCE_DUE_SORTING, due.shiftTimeZone(TimeZone.getDefault()).getInstance()), - containing(TaskContract.Instances.INSTANCE_DURATION, due.getTimestamp() - start.getTimestamp()), - withNullValue(TaskContract.Instances.INSTANCE_ORIGINAL_TIME), - containing(TaskContract.Instances.DISTANCE_FROM_CURRENT, 5), - containing(TaskContract.Instances.DTSTART, start.getTimestamp()), - containing(TaskContract.Instances.DUE, due.getTimestamp()), - withNullValue(TaskContract.Instances.ORIGINAL_INSTANCE_TIME), - withNullValue(TaskContract.Instances.DURATION), - withNullValue(TaskContract.Instances.RRULE), - withNullValue(TaskContract.Instances.RDATE), - withNullValue(TaskContract.Instances.EXDATE) - ) - )); + builds(withValuesOnly(containing(TaskContract.Instances.INSTANCE_START, start.getTimestamp()), + containing(TaskContract.Instances.INSTANCE_START_SORTING, + start.shiftTimeZone(TimeZone.getDefault()).getInstance()), + containing(TaskContract.Instances.INSTANCE_DUE, due.getTimestamp()), + containing(TaskContract.Instances.INSTANCE_DUE_SORTING, + due.shiftTimeZone(TimeZone.getDefault()).getInstance()), + containing(TaskContract.Instances.INSTANCE_DURATION, due.getTimestamp() - start.getTimestamp()), + withNullValue(TaskContract.Instances.INSTANCE_ORIGINAL_TIME), + containing(TaskContract.Instances.DISTANCE_FROM_CURRENT, 5), + containing(TaskContract.Instances.DTSTART, start.getTimestamp()), + containing(TaskContract.Instances.DUE, due.getTimestamp()), + withNullValue(TaskContract.Instances.ORIGINAL_INSTANCE_TIME), + withNullValue(TaskContract.Instances.DURATION), withNullValue(TaskContract.Instances.RRULE), + withNullValue(TaskContract.Instances.RDATE), withNullValue(TaskContract.Instances.EXDATE)))); } - @Test - public void testWithDateAndOriginalTime() - { + public void testWithDateAndOriginalTime() { DateTime start = DateTime.now(); DateTime due = start.addDuration(Duration.parse("P1DT1H")); DateTime original = start.addDuration(Duration.parse("P2DT2H")); assertThat(new InstanceTestData(start, due, new Present<>(original), 5), - builds( - withValuesOnly( - containing(TaskContract.Instances.INSTANCE_START, start.getTimestamp()), - containing(TaskContract.Instances.INSTANCE_START_SORTING, start.shiftTimeZone(TimeZone.getDefault()).getInstance()), - containing(TaskContract.Instances.INSTANCE_DUE, due.getTimestamp()), - containing(TaskContract.Instances.INSTANCE_DUE_SORTING, due.shiftTimeZone(TimeZone.getDefault()).getInstance()), - containing(TaskContract.Instances.INSTANCE_DURATION, due.getTimestamp() - start.getTimestamp()), - containing(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, original.getTimestamp()), - containing(TaskContract.Instances.DISTANCE_FROM_CURRENT, 5), - containing(TaskContract.Instances.DTSTART, start.getTimestamp()), - containing(TaskContract.Instances.DUE, due.getTimestamp()), - containing(TaskContract.Instances.ORIGINAL_INSTANCE_TIME, original.getTimestamp()), - withNullValue(TaskContract.Instances.DURATION), - withNullValue(TaskContract.Instances.RRULE), - withNullValue(TaskContract.Instances.RDATE), - withNullValue(TaskContract.Instances.EXDATE) - ) - )); + builds(withValuesOnly(containing(TaskContract.Instances.INSTANCE_START, start.getTimestamp()), + containing(TaskContract.Instances.INSTANCE_START_SORTING, + start.shiftTimeZone(TimeZone.getDefault()).getInstance()), + containing(TaskContract.Instances.INSTANCE_DUE, due.getTimestamp()), + containing(TaskContract.Instances.INSTANCE_DUE_SORTING, + due.shiftTimeZone(TimeZone.getDefault()).getInstance()), + containing(TaskContract.Instances.INSTANCE_DURATION, due.getTimestamp() - start.getTimestamp()), + containing(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, original.getTimestamp()), + containing(TaskContract.Instances.DISTANCE_FROM_CURRENT, 5), + containing(TaskContract.Instances.DTSTART, start.getTimestamp()), + containing(TaskContract.Instances.DUE, due.getTimestamp()), + containing(TaskContract.Instances.ORIGINAL_INSTANCE_TIME, original.getTimestamp()), + withNullValue(TaskContract.Instances.DURATION), withNullValue(TaskContract.Instances.RRULE), + withNullValue(TaskContract.Instances.RDATE), withNullValue(TaskContract.Instances.EXDATE)))); } - @Test - public void testWithStartDateAndOriginalTime() - { + public void testWithStartDateAndOriginalTime() { DateTime start = DateTime.now(); DateTime original = start.addDuration(Duration.parse("P2DT2H")); assertThat(new InstanceTestData(new Present<>(start), absent(), new Present<>(original), 5), - builds( - withValuesOnly( - containing(TaskContract.Instances.INSTANCE_START, start.getTimestamp()), - containing(TaskContract.Instances.INSTANCE_START_SORTING, start.shiftTimeZone(TimeZone.getDefault()).getInstance()), - withNullValue(TaskContract.Instances.INSTANCE_DUE), - withNullValue(TaskContract.Instances.INSTANCE_DUE_SORTING), - withNullValue(TaskContract.Instances.INSTANCE_DURATION), - containing(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, original.getTimestamp()), - containing(TaskContract.Instances.DISTANCE_FROM_CURRENT, 5), - containing(TaskContract.Instances.DTSTART, start.getTimestamp()), - containing(TaskContract.Instances.ORIGINAL_INSTANCE_TIME, original.getTimestamp()), - withNullValue(TaskContract.Instances.DUE), - withNullValue(TaskContract.Instances.DURATION), - withNullValue(TaskContract.Instances.RRULE), - withNullValue(TaskContract.Instances.RDATE), - withNullValue(TaskContract.Instances.EXDATE) - ) - )); + builds(withValuesOnly(containing(TaskContract.Instances.INSTANCE_START, start.getTimestamp()), + containing(TaskContract.Instances.INSTANCE_START_SORTING, + start.shiftTimeZone(TimeZone.getDefault()).getInstance()), + withNullValue(TaskContract.Instances.INSTANCE_DUE), + withNullValue(TaskContract.Instances.INSTANCE_DUE_SORTING), + withNullValue(TaskContract.Instances.INSTANCE_DURATION), + containing(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, original.getTimestamp()), + containing(TaskContract.Instances.DISTANCE_FROM_CURRENT, 5), + containing(TaskContract.Instances.DTSTART, start.getTimestamp()), + containing(TaskContract.Instances.ORIGINAL_INSTANCE_TIME, original.getTimestamp()), + withNullValue(TaskContract.Instances.DUE), withNullValue(TaskContract.Instances.DURATION), + withNullValue(TaskContract.Instances.RRULE), withNullValue(TaskContract.Instances.RDATE), + withNullValue(TaskContract.Instances.EXDATE)))); } - @Test - public void testWithDueDateAndOriginalTime() - { + public void testWithDueDateAndOriginalTime() { DateTime due = DateTime.now(); DateTime original = due.addDuration(Duration.parse("P2DT2H")); assertThat(new InstanceTestData(absent(), new Present<>(due), new Present<>(original), 5), - builds( - withValuesOnly( - withNullValue(TaskContract.Instances.INSTANCE_START), - withNullValue(TaskContract.Instances.INSTANCE_START_SORTING), - containing(TaskContract.Instances.INSTANCE_DUE, due.getTimestamp()), - containing(TaskContract.Instances.INSTANCE_DUE_SORTING, due.shiftTimeZone(TimeZone.getDefault()).getInstance()), - withNullValue(TaskContract.Instances.INSTANCE_DURATION), - containing(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, original.getTimestamp()), - containing(TaskContract.Instances.DISTANCE_FROM_CURRENT, 5), - withNullValue(TaskContract.Instances.DTSTART), - containing(TaskContract.Instances.DUE, due.getTimestamp()), - containing(TaskContract.Instances.ORIGINAL_INSTANCE_TIME, original.getTimestamp()), - withNullValue(TaskContract.Instances.DURATION), - withNullValue(TaskContract.Instances.RRULE), - withNullValue(TaskContract.Instances.RDATE), - withNullValue(TaskContract.Instances.EXDATE) - ) - )); + builds(withValuesOnly(withNullValue(TaskContract.Instances.INSTANCE_START), + withNullValue(TaskContract.Instances.INSTANCE_START_SORTING), + containing(TaskContract.Instances.INSTANCE_DUE, due.getTimestamp()), + containing(TaskContract.Instances.INSTANCE_DUE_SORTING, + due.shiftTimeZone(TimeZone.getDefault()).getInstance()), + withNullValue(TaskContract.Instances.INSTANCE_DURATION), + containing(TaskContract.Instances.INSTANCE_ORIGINAL_TIME, original.getTimestamp()), + containing(TaskContract.Instances.DISTANCE_FROM_CURRENT, 5), + withNullValue(TaskContract.Instances.DTSTART), + containing(TaskContract.Instances.DUE, due.getTimestamp()), + containing(TaskContract.Instances.ORIGINAL_INSTANCE_TIME, original.getTimestamp()), + withNullValue(TaskContract.Instances.DURATION), withNullValue(TaskContract.Instances.RRULE), + withNullValue(TaskContract.Instances.RDATE), withNullValue(TaskContract.Instances.EXDATE)))); } -} \ No newline at end of file +} diff --git a/releases/CHANGELOG b/releases/CHANGELOG deleted file mode 100644 index 7094503d05a973f3fbf3f4e4d2d44211458f946d..0000000000000000000000000000000000000000 --- a/releases/CHANGELOG +++ /dev/null @@ -1 +0,0 @@ -This change log has been migrated to https://github.com/dmfs/opentasks/releases and is no longer maintained. diff --git a/releases/opentasks-1.1.10.apk b/releases/opentasks-1.1.10.apk deleted file mode 100644 index 90ddb9972345b3fe31643d702f36d1af85764aef..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.10.apk and /dev/null differ diff --git a/releases/opentasks-1.1.11.apk b/releases/opentasks-1.1.11.apk deleted file mode 100644 index 6e1dad383195e04e74040cfcefee368163861f86..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.11.apk and /dev/null differ diff --git a/releases/opentasks-1.1.12.apk b/releases/opentasks-1.1.12.apk deleted file mode 100644 index c6ddb7f18007a16de629824bc8342c2f34faa128..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.12.apk and /dev/null differ diff --git a/releases/opentasks-1.1.13.apk b/releases/opentasks-1.1.13.apk deleted file mode 100644 index 3f11c6e749ac3a7991fe04e766a41872c8fd7b85..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.13.apk and /dev/null differ diff --git a/releases/opentasks-1.1.14.apk b/releases/opentasks-1.1.14.apk deleted file mode 100644 index 81d91bfaf4ba075035d7edab536cf94b48495da8..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.14.apk and /dev/null differ diff --git a/releases/opentasks-1.1.15.apk b/releases/opentasks-1.1.15.apk deleted file mode 100644 index 4616eac34e46a93c4fa5e46ef8c746436bfea53a..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.15.apk and /dev/null differ diff --git a/releases/opentasks-1.1.18.apk b/releases/opentasks-1.1.18.apk deleted file mode 100644 index 332b660417085ea5e2463bd42e69ea22ba78ac28..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.18.apk and /dev/null differ diff --git a/releases/opentasks-1.1.19.apk b/releases/opentasks-1.1.19.apk deleted file mode 100644 index 1c493955b4339a1f52bde9c61367ba7e0f2db266..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.19.apk and /dev/null differ diff --git a/releases/opentasks-1.1.20.apk b/releases/opentasks-1.1.20.apk deleted file mode 100644 index 4232af9a6a35d4e6fa7134ebad742c8609a15947..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.20.apk and /dev/null differ diff --git a/releases/opentasks-1.1.8.1.apk b/releases/opentasks-1.1.8.1.apk deleted file mode 100644 index d6db3d7129b0ed49ed2e16d3a046463cc4df26d9..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.8.1.apk and /dev/null differ diff --git a/releases/opentasks-1.1.8.2.apk b/releases/opentasks-1.1.8.2.apk deleted file mode 100644 index e0e07dd2e28e534dd79fc9657c3ae0b71a02e91e..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.8.2.apk and /dev/null differ diff --git a/releases/opentasks-1.1.8.apk b/releases/opentasks-1.1.8.apk deleted file mode 100644 index 37130022a6df6d2ceeef09a9eab735a6efba4f52..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.8.apk and /dev/null differ diff --git a/releases/opentasks-1.1.9.apk b/releases/opentasks-1.1.9.apk deleted file mode 100644 index f405df82adf46526a0f909d37b098235ad91ffe5..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.1.9.apk and /dev/null differ diff --git a/releases/opentasks-1.2.2.apk b/releases/opentasks-1.2.2.apk deleted file mode 100644 index 660a6795282df032ddb9d66d2226b040fb7f8d6a..0000000000000000000000000000000000000000 Binary files a/releases/opentasks-1.2.2.apk and /dev/null differ diff --git a/releases/tasks-1.0.10.apk b/releases/tasks-1.0.10.apk deleted file mode 100644 index 1231c88ad5e64bcba6908f13c4b31a4ffca92995..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.0.10.apk and /dev/null differ diff --git a/releases/tasks-1.0.11.apk b/releases/tasks-1.0.11.apk deleted file mode 100644 index 260654f76b886668578ae9d600cfa61a17aac79b..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.0.11.apk and /dev/null differ diff --git a/releases/tasks-1.0.12.apk b/releases/tasks-1.0.12.apk deleted file mode 100644 index 411d9cda5a2c8b0a4d2623498aa88c2a40085f02..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.0.12.apk and /dev/null differ diff --git a/releases/tasks-1.0.3.apk b/releases/tasks-1.0.3.apk deleted file mode 100644 index eebe8c146766cf3a0af6801c20fa8a49499d4154..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.0.3.apk and /dev/null differ diff --git a/releases/tasks-1.0.4.apk b/releases/tasks-1.0.4.apk deleted file mode 100644 index bdeb230ce0192f432fce6043beafa4a62432f7ff..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.0.4.apk and /dev/null differ diff --git a/releases/tasks-1.0.5.apk b/releases/tasks-1.0.5.apk deleted file mode 100644 index 49d7c3e9019c24ae550b0ec3c89411b09f092768..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.0.5.apk and /dev/null differ diff --git a/releases/tasks-1.0.6.apk b/releases/tasks-1.0.6.apk deleted file mode 100644 index 43082cfa4bc4f9c17ee97ccb7f0f54c539efc79d..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.0.6.apk and /dev/null differ diff --git a/releases/tasks-1.0.7.apk b/releases/tasks-1.0.7.apk deleted file mode 100644 index 20e5cc1e40da49b13ef0aa9b3036931335f3f28d..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.0.7.apk and /dev/null differ diff --git a/releases/tasks-1.0.8.apk b/releases/tasks-1.0.8.apk deleted file mode 100644 index afc9e376dd287075f9b4930de34e8f5fa68c6378..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.0.8.apk and /dev/null differ diff --git a/releases/tasks-1.0.9.apk b/releases/tasks-1.0.9.apk deleted file mode 100644 index 8305f82b5be16b7cbc971bbb9322bce0084938e6..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.0.9.apk and /dev/null differ diff --git a/releases/tasks-1.1.1.apk b/releases/tasks-1.1.1.apk deleted file mode 100644 index 92b90589747fbdb0a98afd5ccbbf8bdd9c9a785e..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.1.1.apk and /dev/null differ diff --git a/releases/tasks-1.1.2.apk b/releases/tasks-1.1.2.apk deleted file mode 100644 index 8a3d7bc3cb87d7ecaf8250f36da1a790f4e57bd7..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.1.2.apk and /dev/null differ diff --git a/releases/tasks-1.1.4.apk b/releases/tasks-1.1.4.apk deleted file mode 100644 index bed180847d5b910f2a361cfa9b8f11102c8605aa..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.1.4.apk and /dev/null differ diff --git a/releases/tasks-1.1.5.apk b/releases/tasks-1.1.5.apk deleted file mode 100644 index c903eeff7c243daf9730dec15743f92967b4c013..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.1.5.apk and /dev/null differ diff --git a/releases/tasks-1.1.6.apk b/releases/tasks-1.1.6.apk deleted file mode 100644 index 5c8988b8446b9c9fe28075561a074823bf289939..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.1.6.apk and /dev/null differ diff --git a/releases/tasks-1.1.7.apk b/releases/tasks-1.1.7.apk deleted file mode 100644 index 9d041ddc521cd3a44c218d7d142e9b5938e95e61..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.1.7.apk and /dev/null differ diff --git a/releases/tasks-1.1.apk b/releases/tasks-1.1.apk deleted file mode 100644 index e8523d6f7cb0a4371de6c4a0f8a864bf75f85794..0000000000000000000000000000000000000000 Binary files a/releases/tasks-1.1.apk and /dev/null differ