diff --git a/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_MediaTest.kt b/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_MediaTest.kt index f8006023bd..ff7f618f02 100644 --- a/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_MediaTest.kt +++ b/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_MediaTest.kt @@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit import javax.inject.Inject import kotlin.properties.Delegates.notNull +@Suppress("ClassNaming") @SuppressLint("UseSparseArrays") class MockedStack_MediaTest : MockedStack_Base() { @Inject lateinit var dispatcher: Dispatcher @@ -66,7 +67,7 @@ class MockedStack_MediaTest : MockedStack_Base() { interceptor.respondWithSticky("media-upload-response-success.json") // First, try canceling an image with the default behavior (canceled image is deleted from the store) - newMediaModel("Test Title", sampleImagePath, "image/jpeg").let { testMedia -> + newMediaModel("Test Title", sampleImagePath).let { testMedia -> countDownLatch = CountDownLatch(1) nextEvent = TestEvents.CANCELED_MEDIA val payload = UploadMediaPayload(testSite, testMedia, true) @@ -82,7 +83,7 @@ class MockedStack_MediaTest : MockedStack_Base() { } // Now, try canceling with delete=false (canceled image should be marked as failed and kept in the store) - newMediaModel("Test Title", sampleImagePath, "image/jpeg").let { testMedia -> + newMediaModel("Test Title", sampleImagePath).let { testMedia -> countDownLatch = CountDownLatch(1) nextEvent = TestEvents.CANCELED_MEDIA val payload = UploadMediaPayload(testSite, testMedia, true) @@ -205,7 +206,7 @@ class MockedStack_MediaTest : MockedStack_Base() { Assert.assertEquals(amountToCancel, mediaStore.getSiteMediaWithState(testSite, MediaUploadState.FAILED).size) } - @Suppress("unused") + @Suppress("unused", "ThrowsCount") @Subscribe fun onMediaUploaded(event: OnMediaUploaded) { if (event.isError) { @@ -244,11 +245,11 @@ class MockedStack_MediaTest : MockedStack_Base() { } private fun addMediaModelToUploadArray(title: String) { - val mediaModel = newMediaModel(title, sampleImagePath, "image/jpeg") + val mediaModel = newMediaModel(title, sampleImagePath) uploadedMediaModels[mediaModel.id] = mediaModel } - private fun newMediaModel(testTitle: String, mediaPath: String, mimeType: String): MediaModel { + private fun newMediaModel(testTitle: String, mediaPath: String): MediaModel { val testDescription = "Test Description" val testCaption = "Test Caption" val testAlt = "Test Alt" @@ -256,7 +257,7 @@ class MockedStack_MediaTest : MockedStack_Base() { return mediaStore.instantiateMediaModel().apply { filePath = mediaPath fileExtension = mediaPath.substring(mediaPath.lastIndexOf(".") + 1) - this.mimeType = mimeType + this.mimeType = "image/jpeg" fileName = mediaPath.substring(mediaPath.lastIndexOf("/")) title = testTitle description = testDescription @@ -278,7 +279,7 @@ class MockedStack_MediaTest : MockedStack_Base() { // To imitate a real set of media upload requests as much as possible, each one should return a unique // remote media id. This also makes sure the MediaModel table doesn't treat these as duplicate entries and // deletes them, failing the test. - defaultId: String -> defaultId.replace("9999", remoteIdQueue.poll().toString()) + defaultId: String -> defaultId.replace("9999", remoteIdQueue.poll()?.toString() ?: "") } countDownLatch = CountDownLatch(mediaList.size) @@ -292,7 +293,7 @@ class MockedStack_MediaTest : MockedStack_Base() { // Wait a bit and issue the cancel command TestUtils.waitFor(300) - // We'e only cancelling the first n=howManyFirstToCancel uploads + // We're only cancelling the first n=howManyFirstToCancel uploads for (i in 0 until howManyFirstToCancel) { val media = mediaList[i] val payload = CancelMediaPayload(testSite, media, delete) diff --git a/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_UploadStoreTest.java b/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_UploadStoreTest.java index 464e94f83f..b8092868b7 100644 --- a/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_UploadStoreTest.java +++ b/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_UploadStoreTest.java @@ -27,10 +27,11 @@ /** * Tests using a Mocked Network app component. Test the Store itself and not the underlying network component(s). - * + *

* Tests the interactions between the MediaStore/PostStore and the UploadStore, without directly injecting the * UploadStore in the test class. */ +@SuppressWarnings("NewClassNamingConvention") public class MockedStack_UploadStoreTest extends MockedStack_Base { @Inject Dispatcher mDispatcher; @Inject MediaStore mMediaStore; @@ -58,7 +59,7 @@ public void setUp() throws Exception { @Test public void testUploadMedia() throws InterruptedException { - MediaModel testMedia = newMediaModel(getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(getSampleImagePath()); startSuccessfulMediaUpload(testMedia, getTestSite()); assertTrue(mCountDownLatch.await(TestUtils.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); @@ -89,21 +90,17 @@ public void onMediaUploaded(OnMediaUploaded event) { } } - private MediaModel newMediaModel(String mediaPath, String mimeType) { - return newMediaModel("Test Title", mediaPath, mimeType); - } - - private MediaModel newMediaModel(String testTitle, String mediaPath, String mimeType) { + private MediaModel newMediaModel(String mediaPath) { final String testDescription = "Test Description"; final String testCaption = "Test Caption"; final String testAlt = "Test Alt"; MediaModel testMedia = mMediaStore.instantiateMediaModel(); testMedia.setFilePath(mediaPath); - testMedia.setFileExtension(mediaPath.substring(mediaPath.lastIndexOf(".") + 1, mediaPath.length())); - testMedia.setMimeType(mimeType); - testMedia.setFileName(mediaPath.substring(mediaPath.lastIndexOf("/"), mediaPath.length())); - testMedia.setTitle(testTitle); + testMedia.setFileExtension(mediaPath.substring(mediaPath.lastIndexOf(".") + 1)); + testMedia.setMimeType("image/jpeg"); + testMedia.setFileName(mediaPath.substring(mediaPath.lastIndexOf("/"))); + testMedia.setTitle("Test Title"); testMedia.setDescription(testDescription); testMedia.setCaption(testCaption); testMedia.setAlt(testAlt); diff --git a/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_UploadTest.java b/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_UploadTest.java index 503385340c..d918756d57 100644 --- a/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_UploadTest.java +++ b/example/src/androidTest/java/org/wordpress/android/fluxc/mocked/MockedStack_UploadTest.java @@ -50,6 +50,7 @@ /** * Tests using a Mocked Network app component. Test the Store itself and not the underlying network component(s). */ +@SuppressWarnings("NewClassNamingConvention") public class MockedStack_UploadTest extends MockedStack_Base { private static final String POST_DEFAULT_TITLE = "UploadTest base post"; private static final String POST_DEFAULT_DESCRIPTION = "Hi there, I'm a post from FluxC!"; @@ -88,7 +89,7 @@ public void setUp() throws Exception { @Test public void testUploadMedia() throws InterruptedException { - MediaModel testMedia = newMediaModel(getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(getSampleImagePath()); startSuccessfulMediaUpload(testMedia, getTestSite()); assertTrue(mCountDownLatch.await(TestUtils.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); @@ -101,7 +102,7 @@ public void testUploadMedia() throws InterruptedException { @Test public void testUploadMediaError() throws InterruptedException { - MediaModel testMedia = newMediaModel(getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(getSampleImagePath()); startFailingMediaUpload(testMedia, getTestSite()); assertTrue(mCountDownLatch.await(TestUtils.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); @@ -120,7 +121,7 @@ public void testCancelImageUpload() throws InterruptedException { mInterceptor.respondWithSticky("media-upload-response-success.json", 1000L, null); // First, try canceling an image with the default behavior (canceled image is deleted from the store) - MediaModel testMedia = newMediaModel(getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(getSampleImagePath()); mCountDownLatch = new CountDownLatch(1); mNextEvent = TestEvents.CANCELED_MEDIA; UploadMediaPayload payload = new UploadMediaPayload(getTestSite(), testMedia, true); @@ -141,7 +142,7 @@ public void testCancelImageUpload() throws InterruptedException { assertNull(mediaUploadModel); // Now, try canceling with delete=false (canceled image should be marked as failed and kept in the store) - testMedia = newMediaModel(getSampleImagePath(), "image/jpeg"); + testMedia = newMediaModel(getSampleImagePath()); mCountDownLatch = new CountDownLatch(1); mNextEvent = TestEvents.CANCELED_MEDIA; payload = new UploadMediaPayload(getTestSite(), testMedia, true); @@ -174,7 +175,7 @@ public void testRegisterPostAndUploadMediaWithError() throws InterruptedExceptio setupPostAttributes(); // Start uploading media - MediaModel testMedia = newMediaModel(getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(getSampleImagePath()); testMedia.setLocalPostId(mPost.getId()); startFailingMediaUpload(testMedia, site); @@ -271,7 +272,7 @@ public void testRegisterPostAndUploadMediaWithPostCancellation() throws Interrup setupPostAttributes(); // Start uploading media - MediaModel testMedia = newMediaModel(getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(getSampleImagePath()); testMedia.setLocalPostId(mPost.getId()); startSuccessfulMediaUpload(testMedia, site); @@ -341,7 +342,7 @@ public void testUploadMediaInCancelledPost() throws InterruptedException { setupPostAttributes(); // Start uploading media - MediaModel testMedia = newMediaModel(getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(getSampleImagePath()); testMedia.setLocalPostId(mPost.getId()); startFailingMediaUpload(testMedia, site); @@ -372,7 +373,7 @@ public void testUploadMediaInCancelledPost() throws InterruptedException { clearMedia(mPost, mUploadStore.getFailedMediaForPost(mPost)); // Upload a new media item to the cancelled post - testMedia = newMediaModel(getSampleImagePath(), "image/jpeg"); + testMedia = newMediaModel(getSampleImagePath()); testMedia.setLocalPostId(mPost.getId()); startFailingMediaUpload(testMedia, site); @@ -398,7 +399,7 @@ public void testUpdateMediaModelState() throws InterruptedException { setupPostAttributes(); // Start uploading media - MediaModel testMedia = newMediaModel(getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(getSampleImagePath()); testMedia.setLocalPostId(mPost.getId()); startSuccessfulMediaUpload(testMedia, site); @@ -513,21 +514,17 @@ public void onUploadChanged(OnUploadChanged event) { } } - private MediaModel newMediaModel(String mediaPath, String mimeType) { - return newMediaModel("Test Title", mediaPath, mimeType); - } - - private MediaModel newMediaModel(String testTitle, String mediaPath, String mimeType) { + private MediaModel newMediaModel(String mediaPath) { final String testDescription = "Test Description"; final String testCaption = "Test Caption"; final String testAlt = "Test Alt"; MediaModel testMedia = mMediaStore.instantiateMediaModel(); testMedia.setFilePath(mediaPath); - testMedia.setFileExtension(mediaPath.substring(mediaPath.lastIndexOf(".") + 1, mediaPath.length())); - testMedia.setMimeType(mimeType); - testMedia.setFileName(mediaPath.substring(mediaPath.lastIndexOf("/"), mediaPath.length())); - testMedia.setTitle(testTitle); + testMedia.setFileExtension(mediaPath.substring(mediaPath.lastIndexOf(".") + 1)); + testMedia.setMimeType("image/jpeg"); + testMedia.setFileName(mediaPath.substring(mediaPath.lastIndexOf("/"))); + testMedia.setTitle("Test Title"); testMedia.setDescription(testDescription); testMedia.setCaption(testCaption); testMedia.setAlt(testAlt); @@ -535,9 +532,8 @@ private MediaModel newMediaModel(String testTitle, String mediaPath, String mime return testMedia; } - private PostModel createNewPost(SiteModel site) throws InterruptedException { + private void createNewPost(SiteModel site) { mPost = mPostStore.instantiatePostModel(site, false); - return mPost; } private void setupPostAttributes() { diff --git a/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestJetpack.java b/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestJetpack.java index 0e0ed89db9..9f01b39eda 100644 --- a/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestJetpack.java +++ b/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestJetpack.java @@ -10,7 +10,6 @@ import org.wordpress.android.fluxc.generated.SiteActionBuilder; import org.wordpress.android.fluxc.model.MediaModel; import org.wordpress.android.fluxc.model.SiteModel; -import org.wordpress.android.fluxc.store.AccountStore; import org.wordpress.android.fluxc.store.AccountStore.AuthenticatePayload; import org.wordpress.android.fluxc.store.AccountStore.OnAccountChanged; import org.wordpress.android.fluxc.store.AccountStore.OnAuthenticationChanged; @@ -33,9 +32,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +@SuppressWarnings("NewClassNamingConvention") public class ReleaseStack_MediaTestJetpack extends ReleaseStack_Base { @Inject SiteStore mSiteStore; - @Inject AccountStore mAccountStore; @Inject MediaStore mMediaStore; private enum TestEvents { @@ -72,7 +71,7 @@ public void testUploadMediaLowFilesizeLimit() throws InterruptedException { site = mSiteStore.getSites().get(0); // Attempt to upload an image that exceeds the site's maximum upload_max_filesize or post_max_size - MediaModel testMedia = newMediaModel(site, getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(site, getSampleImagePath()); mNextEvent = TestEvents.ERROR_EXCEEDS_FILESIZE_LIMIT; uploadMedia(site, testMedia); @@ -92,7 +91,7 @@ public void testUploadMediaLowMemoryLimit() throws InterruptedException { site.setMemoryLimit(1985); // Artificially set the site's memory limit, in bytes // Attempt to upload an image that exceeds the site's memory limit - MediaModel testMedia = newMediaModel(site, getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(site, getSampleImagePath()); mNextEvent = TestEvents.ERROR_EXCEEDS_MEMORY_LIMIT; uploadMedia(site, testMedia); @@ -116,7 +115,7 @@ public void testUploadMediaLowQuotaAvailableLimit() throws InterruptedException site.setSpaceUsed(50); // Attempt to upload an image that exceeds the site's memory limit - MediaModel testMedia = newMediaModel(site, getSampleImagePath(), "image/jpeg"); + MediaModel testMedia = newMediaModel(site, getSampleImagePath()); mNextEvent = TestEvents.ERROR_EXCEEDS_SITE_SPACE_QUOTA_LIMIT; uploadMedia(site, testMedia); @@ -148,7 +147,7 @@ public void onMediaUploaded(OnMediaUploaded event) { } } - private MediaModel newMediaModel(SiteModel site, String mediaPath, String mimeType) { + private MediaModel newMediaModel(SiteModel site, String mediaPath) { final String testTitle = "Test Title"; final String testDescription = "Test Description"; final String testCaption = "Test Caption"; @@ -156,9 +155,9 @@ private MediaModel newMediaModel(SiteModel site, String mediaPath, String mimeTy MediaModel testMedia = mMediaStore.instantiateMediaModel(); testMedia.setFilePath(mediaPath); - testMedia.setFileExtension(mediaPath.substring(mediaPath.lastIndexOf(".") + 1, mediaPath.length())); - testMedia.setMimeType(mimeType); - testMedia.setFileName(mediaPath.substring(mediaPath.lastIndexOf("/"), mediaPath.length())); + testMedia.setFileExtension(mediaPath.substring(mediaPath.lastIndexOf(".") + 1)); + testMedia.setMimeType("image/jpeg"); + testMedia.setFileName(mediaPath.substring(mediaPath.lastIndexOf("/"))); testMedia.setTitle(testTitle); testMedia.setDescription(testDescription); testMedia.setCaption(testCaption); diff --git a/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestWPCom.java b/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestWPCom.java index e5bf6fa0c6..0022247180 100644 --- a/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestWPCom.java +++ b/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestWPCom.java @@ -40,6 +40,7 @@ import static org.junit.Assert.assertTrue; @SuppressLint("UseSparseArrays") +@SuppressWarnings("NewClassNamingConvention") public class ReleaseStack_MediaTestWPCom extends ReleaseStack_WPComBase { @Inject MediaStore mMediaStore; @@ -380,10 +381,6 @@ private boolean eventHasKnownImages(OnMediaChanged event) { } private MediaModel newMediaModel(String mediaPath, String mimeType) { - return newMediaModel("Test Title", mediaPath, mimeType); - } - - private MediaModel newMediaModel(String testTitle, String mediaPath, String mimeType) { final String testDescription = "Test Description"; final String testCaption = "Test Caption"; final String testAlt = "Test Alt"; @@ -393,7 +390,7 @@ private MediaModel newMediaModel(String testTitle, String mediaPath, String mime testMedia.setFileExtension(mediaPath.substring(mediaPath.lastIndexOf(".") + 1)); testMedia.setMimeType(mimeType); testMedia.setFileName(mediaPath.substring(mediaPath.lastIndexOf("/"))); - testMedia.setTitle(testTitle); + testMedia.setTitle("Test Title"); testMedia.setDescription(testDescription); testMedia.setCaption(testCaption); testMedia.setAlt(testAlt); diff --git a/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestXMLRPC.java b/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestXMLRPC.java index 9da77d8956..dec57cc573 100644 --- a/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestXMLRPC.java +++ b/example/src/androidTest/java/org/wordpress/android/fluxc/release/ReleaseStack_MediaTestXMLRPC.java @@ -39,6 +39,7 @@ import static org.junit.Assert.assertTrue; @SuppressLint("UseSparseArrays") +@SuppressWarnings("NewClassNamingConvention") public class ReleaseStack_MediaTestXMLRPC extends ReleaseStack_XMLRPCBase { @SuppressWarnings("unused") @Inject AccountStore mAccountStore; @@ -403,10 +404,6 @@ public void onMediaListFetched(OnMediaListFetched event) { } private MediaModel newMediaModel(String mediaPath, String mimeType) { - return newMediaModel("Test Title", mediaPath, mimeType); - } - - private MediaModel newMediaModel(String testTitle, String mediaPath, String mimeType) { final String testDescription = "Test Description"; final String testCaption = "Test Caption"; final String testAlt = "Test Alt"; @@ -416,7 +413,7 @@ private MediaModel newMediaModel(String testTitle, String mediaPath, String mime testMedia.setFileExtension(mediaPath.substring(mediaPath.lastIndexOf(".") + 1)); testMedia.setMimeType(mimeType); testMedia.setFileName(mediaPath.substring(mediaPath.lastIndexOf("/"))); - testMedia.setTitle(testTitle); + testMedia.setTitle("Test Title"); testMedia.setDescription(testDescription); testMedia.setCaption(testCaption); testMedia.setAlt(testAlt); diff --git a/example/src/main/java/org/wordpress/android/fluxc/example/MediaFragment.java b/example/src/main/java/org/wordpress/android/fluxc/example/MediaFragment.java index 10c630dce9..367f7f4b69 100644 --- a/example/src/main/java/org/wordpress/android/fluxc/example/MediaFragment.java +++ b/example/src/main/java/org/wordpress/android/fluxc/example/MediaFragment.java @@ -18,6 +18,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import org.greenrobot.eventbus.Subscribe; @@ -266,8 +267,10 @@ public void onMediaUploaded(OnMediaUploaded event) { } } - private void prependToLog(final String s) { - ((MainExampleActivity) getActivity()).prependToLog(s); + private void prependToLog(@Nullable final String s) { + if (s != null) { + ((MainExampleActivity) getActivity()).prependToLog(s); + } } private void fetchMediaList(@NonNull SiteModel site) { diff --git a/example/src/test/java/org/wordpress/android/fluxc/media/MediaSqlUtilsTest.java b/example/src/test/java/org/wordpress/android/fluxc/media/MediaSqlUtilsTest.java index 2734032ac3..8696b94f41 100644 --- a/example/src/test/java/org/wordpress/android/fluxc/media/MediaSqlUtilsTest.java +++ b/example/src/test/java/org/wordpress/android/fluxc/media/MediaSqlUtilsTest.java @@ -35,7 +35,7 @@ public class MediaSqlUtilsTest { @Before public void setUp() { - Context appContext = RuntimeEnvironment.application.getApplicationContext(); + Context appContext = RuntimeEnvironment.getApplication().getApplicationContext(); WellSqlConfig config = new SingleStoreWellSqlConfigForTests(appContext, MediaModel.class); WellSql.init(config); diff --git a/example/src/test/java/org/wordpress/android/fluxc/media/MediaStoreTest.java b/example/src/test/java/org/wordpress/android/fluxc/media/MediaStoreTest.java index 210ec4d0ef..33e4ded8d4 100644 --- a/example/src/test/java/org/wordpress/android/fluxc/media/MediaStoreTest.java +++ b/example/src/test/java/org/wordpress/android/fluxc/media/MediaStoreTest.java @@ -16,7 +16,6 @@ import org.wordpress.android.fluxc.model.MediaModel.MediaUploadState; import org.wordpress.android.fluxc.model.PostModel; import org.wordpress.android.fluxc.model.SiteModel; -import org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords.ApplicationPasswordsConfiguration; import org.wordpress.android.fluxc.network.rest.wpapi.media.ApplicationPasswordsMediaRestClient; import org.wordpress.android.fluxc.network.rest.wpcom.media.MediaRestClient; import org.wordpress.android.fluxc.network.rest.wpcom.media.wpv2.WPComV2MediaRestClient; @@ -43,16 +42,19 @@ @RunWith(RobolectricTestRunner.class) public class MediaStoreTest { - private MediaStore mMediaStore = new MediaStore(new Dispatcher(), + @SuppressWarnings("KotlinInternalInJava") + private final MediaStore mMediaStore = new MediaStore(new Dispatcher(), Mockito.mock(MediaRestClient.class), Mockito.mock(MediaXMLRPCClient.class), Mockito.mock(WPComV2MediaRestClient.class), Mockito.mock(ApplicationPasswordsMediaRestClient.class), - Mockito.mock(ApplicationPasswordsConfiguration.class)); + Mockito.mock(org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords + .ApplicationPasswordsConfiguration.class) + ); @Before public void setUp() { - Context context = RuntimeEnvironment.application.getApplicationContext(); + Context context = RuntimeEnvironment.getApplication().getApplicationContext(); WellSqlConfig config = new SingleStoreWellSqlConfigForTests(context, MediaModel.class); WellSql.init(config); config.reset(); @@ -79,19 +81,19 @@ public void testGetAllMedia() { public void testMediaCount() { final int testSiteId = 2; SiteModel testSite = getTestSiteWithLocalId(testSiteId); - assertTrue(mMediaStore.getSiteMediaCount(testSite) == 0); + assertEquals(0, mMediaStore.getSiteMediaCount(testSite)); // count after insertion insertRandomMediaIntoDatabase(testSiteId, 5); - assertTrue(mMediaStore.getSiteMediaCount(testSite) == 5); + assertEquals(5, mMediaStore.getSiteMediaCount(testSite)); // count after inserting with different site ID final int wrongSiteId = testSiteId + 1; SiteModel wrongSite = getTestSiteWithLocalId(wrongSiteId); - assertTrue(mMediaStore.getSiteMediaCount(wrongSite) == 0); + assertEquals(0, mMediaStore.getSiteMediaCount(wrongSite)); insertRandomMediaIntoDatabase(wrongSiteId, 1); - assertTrue(mMediaStore.getSiteMediaCount(wrongSite) == 1); - assertTrue(mMediaStore.getSiteMediaCount(testSite) == 5); + assertEquals(1, mMediaStore.getSiteMediaCount(wrongSite)); + assertEquals(5, mMediaStore.getSiteMediaCount(testSite)); } @Test @@ -99,17 +101,17 @@ public void testHasSiteMediaWithId() { final int testSiteId = 24; final long testMediaId = 22; SiteModel testSite = getTestSiteWithLocalId(testSiteId); - assertTrue(mMediaStore.getSiteMediaCount(testSite) == 0); + assertEquals(0, mMediaStore.getSiteMediaCount(testSite)); assertFalse(mMediaStore.hasSiteMediaWithId(testSite, testMediaId)); // add test media MediaModel testMedia = getBasicMedia(); testMedia.setLocalSiteId(testSiteId); testMedia.setMediaId(testMediaId); - assertTrue(insertMediaIntoDatabase(testMedia) == 1); + assertEquals(1, insertMediaIntoDatabase(testMedia)); // verify store has inserted media - assertTrue(mMediaStore.getSiteMediaCount(testSite) == 1); + assertEquals(1, mMediaStore.getSiteMediaCount(testSite)); assertTrue(mMediaStore.hasSiteMediaWithId(testSite, testMediaId)); } @@ -124,7 +126,7 @@ public void testGetSpecificSiteMedia() { MediaModel testMedia = getBasicMedia(); testMedia.setLocalSiteId(testSiteId); testMedia.setMediaId(testMediaId); - assertTrue(insertMediaIntoDatabase(testMedia) == 1); + assertEquals(1, insertMediaIntoDatabase(testMedia)); // cannot get media with incorrect site ID final int wrongSiteId = testSiteId + 1; @@ -144,7 +146,7 @@ public void testGetListOfSiteMedia() { final int testSiteId = 55; SiteModel testSite = getTestSiteWithLocalId(testSiteId); List insertedMedia = insertRandomMediaIntoDatabase(testSiteId, testListSize); - assertTrue(mMediaStore.getSiteMediaCount(testSite) == testListSize); + assertEquals(testListSize, mMediaStore.getSiteMediaCount(testSite)); // create whitelist List whitelist = new ArrayList<>(testListSize / 2); @@ -154,7 +156,7 @@ public void testGetListOfSiteMedia() { final List storeMedia = mMediaStore.getSiteMediaWithIds(testSite, whitelist); assertNotNull(storeMedia); - assertTrue(storeMedia.size() == whitelist.size()); + assertEquals(storeMedia.size(), whitelist.size()); for (MediaModel media : storeMedia) { assertTrue(whitelist.contains(media.getMediaId())); } @@ -178,7 +180,7 @@ public void testGetSiteImages() { final List storeImages = mMediaStore.getSiteImages(getTestSiteWithLocalId(testSiteId)); assertNotNull(storeImages); - assertTrue(storeImages.size() == 1); + assertEquals(1, storeImages.size()); assertEquals(testImageId, storeImages.get(0).getMediaId()); assertTrue(MediaUtils.isImageMimeType(storeImages.get(0).getMimeType())); } @@ -187,7 +189,7 @@ public void testGetSiteImages() { public void testGetSiteImageCount() { final int testSiteId = 9001; SiteModel testSite = getTestSiteWithLocalId(testSiteId); - assertTrue(mMediaStore.getSiteImageCount(testSite) == 0); + assertEquals(0, mMediaStore.getSiteImageCount(testSite)); // insert both images and videos final int testListSize = 10; @@ -198,31 +200,31 @@ public void testGetSiteImageCount() { for (int i = 0; i < testListSize; ++i) { MediaModel testImage = generateMediaFromPath(testSiteId, i, String.format(testImagePath, i)); MediaModel testVideo = generateMediaFromPath(testSiteId, i + testListSize, String.format(testVideoPath, i)); - assertTrue(insertMediaIntoDatabase(testImage) == 1); - assertTrue(insertMediaIntoDatabase(testVideo) == 1); + assertEquals(1, insertMediaIntoDatabase(testImage)); + assertEquals(1, insertMediaIntoDatabase(testVideo)); testImages.add(testImage); testVideos.add(testVideo); } - assertTrue(mMediaStore.getSiteMediaCount(testSite) == testImages.size() + testVideos.size()); - assertTrue(mMediaStore.getSiteImageCount(testSite) == testImages.size()); + assertEquals(mMediaStore.getSiteMediaCount(testSite), testImages.size() + testVideos.size()); + assertEquals(mMediaStore.getSiteImageCount(testSite), testImages.size()); } @Test public void testGetSiteImagesBlacklist() { final int testSiteId = 3; SiteModel testSite = getTestSiteWithLocalId(testSiteId); - assertTrue(mMediaStore.getSiteImageCount(testSite) == 0); + assertEquals(0, mMediaStore.getSiteImageCount(testSite)); final int testListSize = 10; final List testImages = new ArrayList<>(testListSize); final String testImagePath = "/test/test_image%d.png"; for (int i = 0; i < testListSize; ++i) { MediaModel image = generateMediaFromPath(testSiteId, i, String.format(testImagePath, i)); - assertTrue(insertMediaIntoDatabase(image) == 1); + assertEquals(1, insertMediaIntoDatabase(image)); testImages.add(image); } - assertTrue(mMediaStore.getSiteImageCount(testSite) == testListSize); + assertEquals(testListSize, mMediaStore.getSiteImageCount(testSite)); // create blacklist List blacklist = new ArrayList<>(testListSize / 2); @@ -257,7 +259,7 @@ public void testGetUnattachedSiteMedia() { final List storeMedia = mMediaStore.getUnattachedSiteMedia(getTestSiteWithLocalId(testSiteId)); assertNotNull(storeMedia); - assertTrue(storeMedia.size() == unattachedMedia.size()); + assertEquals(storeMedia.size(), unattachedMedia.size()); for (int i = 0; i < storeMedia.size(); ++i) { assertTrue(storeMedia.contains(unattachedMedia.get(i))); } @@ -277,7 +279,7 @@ public void testGetUnattachedSiteMediaCount() { insertMediaIntoDatabase(attached); insertMediaIntoDatabase(unattached); } - assertTrue(mMediaStore.getUnattachedSiteMediaCount(getTestSiteWithLocalId(testSiteId)) == testPoolSize); + assertEquals(testPoolSize, mMediaStore.getUnattachedSiteMediaCount(getTestSiteWithLocalId(testSiteId))); } @Test @@ -331,7 +333,7 @@ public void testGetUrlForVideoWithVideoPressGuid() { final String testVideoPressGuid = "thisisonlyatest"; testVideo.setUrl(testUrl); testVideo.setVideoPressGuid(testVideoPressGuid); - assertTrue(insertMediaIntoDatabase(testVideo) == 1); + assertEquals(1, insertMediaIntoDatabase(testVideo)); // retrieve video and verify final String storeUrl = mMediaStore @@ -349,7 +351,7 @@ public void testGetThumbnailUrl() { final String testUrl = "http://notarealurl.testfluxc.org/not/a/real/resource/path.mp4"; testMedia.setThumbnailUrl(testUrl); testMedia.setMediaId(testMediaId); - assertTrue(insertMediaIntoDatabase(testMedia) == 1); + assertEquals(1, insertMediaIntoDatabase(testMedia)); // retrieve media and verify final String storeUrl = mMediaStore @@ -370,7 +372,7 @@ public void testSearchSiteMediaTitles() { MediaModel testMedia = generateMedia(baseString, null, null, null); testMedia.setLocalSiteId(testSiteId); testMedia.setMediaId(i); - assertTrue(insertMediaIntoDatabase(testMedia) == 1); + assertEquals(1, insertMediaIntoDatabase(testMedia)); baseString += String.valueOf(i); } @@ -378,7 +380,7 @@ public void testSearchSiteMediaTitles() { List storeMedia = mMediaStore .searchSiteMedia(getTestSiteWithLocalId(testSiteId), testTitles[i]); assertNotNull(storeMedia); - assertTrue(storeMedia.size() == testPoolSize - i); + assertEquals(storeMedia.size(), testPoolSize - i); } } @@ -418,7 +420,7 @@ public void testSearchSiteImages() { .searchSiteImages(getTestSiteWithLocalId(testSiteId), "test"); assertNotNull(storeImages); - assertTrue(storeImages.size() == 1); + assertEquals(1, storeImages.size()); assertEquals(testImageId, storeImages.get(0).getMediaId()); assertTrue(MediaUtils.isImageMimeType(storeImages.get(0).getMimeType())); assertEquals(testSiteId, storeImages.get(0).getLocalSiteId()); @@ -457,7 +459,7 @@ public void testSearchSiteVideos() { final List storeVideos = mMediaStore .searchSiteVideos(getTestSiteWithLocalId(testSiteId), "test"); assertNotNull(storeVideos); - assertTrue(storeVideos.size() == 1); + assertEquals(1, storeVideos.size()); assertEquals(testVideoId2, storeVideos.get(0).getMediaId()); assertTrue(MediaUtils.isVideoMimeType(storeVideos.get(0).getMimeType())); assertEquals(testSiteId, storeVideos.get(0).getLocalSiteId()); @@ -505,7 +507,7 @@ public void testSearchSiteAudio() { final List storeAudio = mMediaStore .searchSiteAudio(getTestSiteWithLocalId(testSiteId), "test"); assertNotNull(storeAudio); - assertTrue(storeAudio.size() == 2); + assertEquals(2, storeAudio.size()); assertEquals(testAudioId1, storeAudio.get(0).getMediaId()); assertEquals(testAudioId2, storeAudio.get(1).getMediaId()); @@ -569,7 +571,7 @@ public void testSearchSiteDocuments() { final List storeDocuments = mMediaStore .searchSiteDocuments(getTestSiteWithLocalId(testSiteId), "test"); assertNotNull(storeDocuments); - assertTrue(storeDocuments.size() == 2); + assertEquals(2, storeDocuments.size()); assertEquals(testDocumentId2, storeDocuments.get(0).getMediaId()); assertEquals(testDocumentId3, storeDocuments.get(1).getMediaId()); @@ -706,16 +708,16 @@ public void testHasSiteMediaToDelete() { public void testRemoveAllMedia() { SiteModel testSite1 = getTestSiteWithLocalId(1); insertRandomMediaIntoDatabase(testSite1.getId(), 5); - assertTrue(mMediaStore.getSiteMediaCount(testSite1) == 5); + assertEquals(5, mMediaStore.getSiteMediaCount(testSite1)); SiteModel testSite2 = getTestSiteWithLocalId(2); insertRandomMediaIntoDatabase(testSite2.getId(), 7); - assertTrue(mMediaStore.getSiteMediaCount(testSite2) == 7); + assertEquals(7, mMediaStore.getSiteMediaCount(testSite2)); MediaSqlUtils.deleteAllMedia(); - assertTrue(mMediaStore.getSiteMediaCount(testSite1) == 0); - assertTrue(mMediaStore.getSiteMediaCount(testSite2) == 0); + assertEquals(0, mMediaStore.getSiteMediaCount(testSite1)); + assertEquals(0, mMediaStore.getSiteMediaCount(testSite2)); } private MediaModel getBasicMedia() { diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/BaseUploadRequestBody.java b/fluxc/src/main/java/org/wordpress/android/fluxc/network/BaseUploadRequestBody.java index e497bb9284..f0e1f49f7e 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/BaseUploadRequestBody.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/BaseUploadRequestBody.java @@ -19,17 +19,17 @@ /** * Wrapper for {@link okhttp3.MultipartBody} that reports upload progress as body data is written. - * + *

* A {@link ProgressListener} is required, use {@link okhttp3.MultipartBody} if progress is not needed. - * - * ref http://stackoverflow.com/questions/35528751/okhttp-3-tracking-multipart-upload-progress + *

+ * @see doc */ public abstract class BaseUploadRequestBody extends RequestBody { /** * Callback to report upload progress as body data is written to the sink for network delivery. */ public interface ProgressListener { - void onProgress(MediaModel media, float progress); + void onProgress(@NonNull MediaModel media, float progress); } /** @@ -40,15 +40,15 @@ public interface ProgressListener { *

  • define a file path to a valid local file
  • * * - * @return null if {@code media} is valid, otherwise a string describing why it's invalid + * @return a string describing why {@code media} is invalid */ - public static String hasRequiredData(MediaModel media) { + @NonNull + public static String hasRequiredData(@NonNull MediaModel media) { return checkMediaArg(media).getType().getErrorLogDescription(); } - public static MalformedMediaArgSubType checkMediaArg(MediaModel media) { - if (media == null) return new MalformedMediaArgSubType(Type.MEDIA_WAS_NULL); - + @NonNull + public static MalformedMediaArgSubType checkMediaArg(@NonNull MediaModel media) { // validate MIME type is recognized String mimeType = media.getMimeType(); if (!MediaUtils.isSupportedMimeType(mimeType)) { @@ -72,25 +72,19 @@ public static MalformedMediaArgSubType checkMediaArg(MediaModel media) { return new MalformedMediaArgSubType(Type.NO_ERROR); } - private final MediaModel mMedia; - private final ProgressListener mListener; - - public BaseUploadRequestBody(MediaModel media, ProgressListener listener) { - // validate arguments - if (listener == null) { - throw new IllegalArgumentException("progress listener cannot be null"); - } - String mediaError = hasRequiredData(media); - if (mediaError != null) { - throw new IllegalArgumentException(mediaError); - } + @NonNull private final MediaModel mMedia; + @NonNull private final ProgressListener mListener; + public BaseUploadRequestBody( + @NonNull MediaModel media, + @NonNull ProgressListener listener) { mMedia = media; mListener = listener; } protected abstract float getProgress(long bytesWritten); + @NonNull public MediaModel getMedia() { return mMedia; } @@ -103,7 +97,7 @@ protected final class CountingSink extends ForwardingSink { private long mBytesWritten = 0; private long mLastTimeOnProgressCalled = 0; - public CountingSink(Sink delegate) { + public CountingSink(@NonNull Sink delegate) { super(delegate); } diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaResponseUtils.kt b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaResponseUtils.kt index 7ad5bf84c8..0890c2a428 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaResponseUtils.kt +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaResponseUtils.kt @@ -13,15 +13,16 @@ class MediaResponseUtils /** * Creates a [MediaModel] list from a WP.com REST response to a request for all media. */ - fun getMediaListFromRestResponse(from: MultipleMediaResponse?, localSiteId: Int): List? { - return from?.media?.mapNotNull { getMediaFromRestResponse(it)?.apply { this.localSiteId = localSiteId } } + fun getMediaListFromRestResponse(from: MultipleMediaResponse, localSiteId: Int): List { + return from.media.mapNotNull { + getMediaFromRestResponse(it).apply { this.localSiteId = localSiteId } + } } /** * Creates a [MediaModel] from a WP.com REST response to a fetch request. */ - fun getMediaFromRestResponse(from: MediaWPComRestResponse?): MediaModel? { - if (from == null) return null + fun getMediaFromRestResponse(from: MediaWPComRestResponse): MediaModel { val media = MediaModel() media.mediaId = from.ID media.uploadDate = from.date @@ -36,17 +37,17 @@ class MediaResponseUtils media.caption = StringEscapeUtils.unescapeHtml4(from.caption) media.description = StringEscapeUtils.unescapeHtml4(from.description) media.alt = StringEscapeUtils.unescapeHtml4(from.alt) - if (from.thumbnails != null) { - if (!TextUtils.isEmpty(from.thumbnails.fmt_std)) { - media.thumbnailUrl = from.thumbnails.fmt_std + from.thumbnails?.let { + if (!TextUtils.isEmpty(it.fmt_std)) { + media.thumbnailUrl = it.fmt_std } else { - media.thumbnailUrl = from.thumbnails.thumbnail + media.thumbnailUrl = it.thumbnail } - if (!TextUtils.isEmpty(from.thumbnails.large)) { - media.fileUrlLargeSize = from.thumbnails.large + if (!TextUtils.isEmpty(it.large)) { + media.fileUrlLargeSize = it.large } - if (!TextUtils.isEmpty(from.thumbnails.medium)) { - media.fileUrlMediumSize = from.thumbnails.medium + if (!TextUtils.isEmpty(it.medium)) { + media.fileUrlMediumSize = it.medium } } media.height = from.height diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaRestClient.java b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaRestClient.java index ba885681e1..a5786fd7e7 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaRestClient.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaRestClient.java @@ -4,9 +4,9 @@ import android.text.TextUtils; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.android.volley.RequestQueue; -import com.android.volley.Response.Listener; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -28,8 +28,6 @@ import org.wordpress.android.fluxc.network.UserAgent; import org.wordpress.android.fluxc.network.rest.wpcom.BaseWPComRestClient; import org.wordpress.android.fluxc.network.rest.wpcom.WPComGsonRequest; -import org.wordpress.android.fluxc.network.rest.wpcom.WPComGsonRequest.WPComErrorListener; -import org.wordpress.android.fluxc.network.rest.wpcom.WPComGsonRequest.WPComGsonNetworkError; import org.wordpress.android.fluxc.network.rest.wpcom.auth.AccessToken; import org.wordpress.android.fluxc.network.rest.wpcom.media.MediaWPComRestResponse.MultipleMediaResponse; import org.wordpress.android.fluxc.store.MediaStore.FetchMediaListResponsePayload; @@ -83,32 +81,33 @@ */ @Singleton public class MediaRestClient extends BaseWPComRestClient implements ProgressListener { - private OkHttpClient mOkHttpClient; - private MediaResponseUtils mMediaResponseUtils; + @NonNull private final OkHttpClient mOkHttpClient; + @NonNull private final MediaResponseUtils mMediaResponseUtils; // this will hold which media is being uploaded by which call, in order to be able // to monitor multiple uploads - private ConcurrentHashMap mCurrentUploadCalls = new ConcurrentHashMap<>(); - - @Inject public MediaRestClient(Context appContext, - Dispatcher dispatcher, - @Named("regular") RequestQueue requestQueue, - @Named("regular") OkHttpClient okHttpClient, - AccessToken accessToken, - UserAgent userAgent, - MediaResponseUtils mediaResponseUtils) { + @NonNull private final ConcurrentHashMap mCurrentUploadCalls = new ConcurrentHashMap<>(); + + @Inject public MediaRestClient( + Context appContext, + Dispatcher dispatcher, + @Named("regular") RequestQueue requestQueue, + @NonNull @Named("regular") OkHttpClient okHttpClient, + AccessToken accessToken, + UserAgent userAgent, + @NonNull MediaResponseUtils mediaResponseUtils) { super(appContext, dispatcher, requestQueue, accessToken, userAgent); mOkHttpClient = okHttpClient; mMediaResponseUtils = mediaResponseUtils; } @Override - public void onProgress(MediaModel media, float progress) { + public void onProgress(@NonNull MediaModel media, float progress) { if (mCurrentUploadCalls.containsKey(media.getId())) { notifyMediaProgress(media, Math.min(progress, 0.99f)); } } - public void pushMedia(final SiteModel site, final MediaModel media) { + public void pushMedia(@NonNull final SiteModel site, @Nullable final MediaModel media) { if (media == null) { // caller may be expecting a notification MediaError error = new MediaError(MediaErrorType.NULL_MEDIA_ARG); @@ -120,37 +119,25 @@ public void pushMedia(final SiteModel site, final MediaModel media) { String url = WPCOMREST.sites.site(site.getSiteId()).media.item(media.getMediaId()).getUrlV1_1(); add(WPComGsonRequest.buildPostRequest(url, getEditRequestParams(media), MediaWPComRestResponse.class, - new Listener() { - @Override - public void onResponse(MediaWPComRestResponse response) { - MediaModel responseMedia = mMediaResponseUtils.getMediaFromRestResponse(response); - if (responseMedia != null) { - AppLog.v(T.MEDIA, "media changes pushed for " + responseMedia.getTitle()); - responseMedia.setLocalSiteId(site.getId()); - notifyMediaPushed(site, responseMedia, null); - } else { - MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); - error.logMessage = "Parsed media is null"; - notifyMediaPushed(site, media, error); - } - } - }, new WPComErrorListener() { - @Override - public void onErrorResponse(@NonNull WPComGsonNetworkError error) { - String errorMessage = "error editing remote media: " + error; - AppLog.e(T.MEDIA, errorMessage); - MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); - mediaError.logMessage = errorMessage; - notifyMediaPushed(site, media, mediaError); - } - } - )); + response -> { + MediaModel responseMedia = mMediaResponseUtils.getMediaFromRestResponse(response); + AppLog.v(T.MEDIA, "media changes pushed for " + responseMedia.getTitle()); + responseMedia.setLocalSiteId(site.getId()); + notifyMediaPushed(site, responseMedia, null); + }, + error -> { + String errorMessage = "error editing remote media: " + error; + AppLog.e(T.MEDIA, errorMessage); + MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); + mediaError.logMessage = errorMessage; + notifyMediaPushed(site, media, mediaError); + })); } /** * Uploads a single media item to a WP.com site. */ - public void uploadMedia(final SiteModel site, final MediaModel media) { + public void uploadMedia(@NonNull final SiteModel site, @Nullable final MediaModel media) { if (media == null || media.getId() == 0) { // we can't have a MediaModel without an ID - otherwise we can't keep track of them. MediaError error = new MediaError(MediaErrorType.INVALID_ID); @@ -176,7 +163,7 @@ public void uploadMedia(final SiteModel site, final MediaModel media) { // Abort upload if it exceeds the site upload limit if (site.hasMaxUploadSize() && body.contentLength() > site.getMaxUploadSize()) { String errorMessage = "Media size of " + body.contentLength() + " exceeds site limit of " - + site.getMaxUploadSize(); + + site.getMaxUploadSize(); AppLog.d(T.MEDIA, errorMessage); MediaError error = new MediaError(MediaErrorType.EXCEEDS_FILESIZE_LIMIT); error.logMessage = errorMessage; @@ -188,7 +175,7 @@ public void uploadMedia(final SiteModel site, final MediaModel media) { double maxFilesizeForMemoryLimit = MediaUtils.getMaxFilesizeForMemoryLimit(site.getMemoryLimit()); if (site.hasMemoryLimit() && body.contentLength() > maxFilesizeForMemoryLimit) { String errorMessage = "Media size of " + body.contentLength() + " exceeds safe memory limit of " - + maxFilesizeForMemoryLimit + " for this site"; + + maxFilesizeForMemoryLimit + " for this site"; AppLog.d(T.MEDIA, errorMessage); MediaError error = new MediaError(MediaErrorType.EXCEEDS_MEMORY_LIMIT); error.logMessage = errorMessage; @@ -199,7 +186,7 @@ public void uploadMedia(final SiteModel site, final MediaModel media) { // Abort upload if it exceeds the space quota limit for the site if (site.hasDiskSpaceQuotaInformation() && body.contentLength() > site.getSpaceAvailable()) { String errorMessage = "Media size of " + body.contentLength() + " exceeds disk space quota remaining " - + site.getSpaceAvailable() + " for this site"; + + site.getSpaceAvailable() + " for this site"; AppLog.d(T.MEDIA, errorMessage); MediaError error = new MediaError(MediaErrorType.EXCEEDS_SITE_SPACE_QUOTA_LIMIT); error.logMessage = errorMessage; @@ -253,9 +240,10 @@ public void onResponse(@NonNull Call call, @NonNull Response response) throws IO reader.setLenient(true); MultipleMediaResponse mediaResponse = gson.fromJson(reader, MultipleMediaResponse.class); - List responseMedia = - mMediaResponseUtils.getMediaListFromRestResponse(mediaResponse, site.getId()); - if (responseMedia != null && !responseMedia.isEmpty()) { + List responseMedia = mMediaResponseUtils.getMediaListFromRestResponse( + mediaResponse, + site.getId()); + if (!responseMedia.isEmpty()) { MediaModel uploadedMedia = responseMedia.get(0); uploadedMedia.setId(media.getId()); uploadedMedia.setLocalPostId(media.getLocalPostId()); @@ -272,7 +260,7 @@ public void onResponse(@NonNull Call call, @NonNull Response response) throws IO MediaError error = parseUploadError(response, site); - if (null != error && error.type == MediaErrorType.BAD_REQUEST) { + if (error.type == MediaErrorType.BAD_REQUEST) { AppLog.e(T.MEDIA, "media upload error message: " + error.message); } @@ -299,11 +287,15 @@ public void onFailure(@NonNull Call call, @NonNull IOException e) { /** * Gets a list of media items given the offset on a WP.com site. - * + *

    * NOTE: Only media item data is gathered, the actual media file can be downloaded from the URL * provided in the response {@link MediaModel}'s (via {@link MediaModel#getUrl()}). */ - public void fetchMediaList(final SiteModel site, final int number, final int offset, final MimeType.Type mimeType) { + public void fetchMediaList( + @NonNull final SiteModel site, + final int number, + final int offset, + @Nullable final MimeType.Type mimeType) { final Map params = new HashMap<>(); params.put("number", String.valueOf(number)); if (offset > 0) { @@ -314,41 +306,28 @@ public void fetchMediaList(final SiteModel site, final int number, final int off } String url = WPCOMREST.sites.site(site.getSiteId()).media.getUrlV1_1(); add(WPComGsonRequest.buildGetRequest(url, params, MultipleMediaResponse.class, - new Listener() { - @Override - public void onResponse(MultipleMediaResponse response) { - List mediaList = - mMediaResponseUtils.getMediaListFromRestResponse(response, site.getId()); - if (mediaList != null) { - AppLog.v(T.MEDIA, "Fetched media list for site with size: " + mediaList.size()); - boolean canLoadMore = mediaList.size() == number; - notifyMediaListFetched(site, mediaList, offset > 0, canLoadMore, mimeType); - } else { - String errorMessage = "could not parse Fetch all media response: " + response; - AppLog.w(T.MEDIA, errorMessage); - MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); - error.logMessage = errorMessage; - notifyMediaListFetched(site, error, mimeType); - } - } - }, new WPComErrorListener() { - @Override - public void onErrorResponse(@NonNull WPComGsonNetworkError error) { - String errorMessage = "VolleyError Fetching media: " + error; - AppLog.e(T.MEDIA, errorMessage); - MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); - mediaError.message = error.message; - mediaError.logMessage = error.apiError; - notifyMediaListFetched(site, mediaError, mimeType); - } - } - )); + response -> { + List mediaList = mMediaResponseUtils.getMediaListFromRestResponse( + response, + site.getId()); + AppLog.v(T.MEDIA, "Fetched media list for site with size: " + mediaList.size()); + boolean canLoadMore = mediaList.size() == number; + notifyMediaListFetched(site, mediaList, offset > 0, canLoadMore, mimeType); + }, + error -> { + String errorMessage = "VolleyError Fetching media: " + error; + AppLog.e(T.MEDIA, errorMessage); + MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); + mediaError.message = error.message; + mediaError.logMessage = error.apiError; + notifyMediaListFetched(site, mediaError, mimeType); + })); } /** * Gets a list of media items whose media IDs match the provided list. */ - public void fetchMedia(final SiteModel site, final MediaModel media) { + public void fetchMedia(@NonNull final SiteModel site, @Nullable final MediaModel media) { if (media == null) { // caller may be expecting a notification MediaError error = new MediaError(MediaErrorType.NULL_MEDIA_ARG); @@ -359,39 +338,25 @@ public void fetchMedia(final SiteModel site, final MediaModel media) { String url = WPCOMREST.sites.site(site.getSiteId()).media.item(media.getMediaId()).getUrlV1_1(); add(WPComGsonRequest.buildGetRequest(url, null, MediaWPComRestResponse.class, - new Listener() { - @Override - public void onResponse(MediaWPComRestResponse response) { - MediaModel responseMedia = mMediaResponseUtils.getMediaFromRestResponse(response); - if (responseMedia != null) { - responseMedia.setLocalSiteId(site.getId()); - AppLog.v(T.MEDIA, "Fetched media with ID: " + media.getMediaId()); - notifyMediaFetched(site, responseMedia, null); - } else { - String message = "could not parse Fetch media response, ID: " + media.getMediaId(); - AppLog.w(T.MEDIA, message); - MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); - error.logMessage = message; - notifyMediaFetched(site, media, error); - } - } - }, new WPComErrorListener() { - @Override - public void onErrorResponse(@NonNull WPComGsonNetworkError error) { - AppLog.e(T.MEDIA, "VolleyError Fetching media: " + error); - MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); - mediaError.message = error.message; - mediaError.logMessage = error.apiError; - notifyMediaFetched(site, media, mediaError); - } - } - )); + response -> { + MediaModel responseMedia = mMediaResponseUtils.getMediaFromRestResponse(response); + responseMedia.setLocalSiteId(site.getId()); + AppLog.v(T.MEDIA, "Fetched media with ID: " + media.getMediaId()); + notifyMediaFetched(site, responseMedia, null); + }, + error -> { + AppLog.e(T.MEDIA, "VolleyError Fetching media: " + error); + MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); + mediaError.message = error.message; + mediaError.logMessage = error.apiError; + notifyMediaFetched(site, media, mediaError); + })); } /** * Deletes media from a WP.com site whose media ID is in the provided list. */ - public void deleteMedia(final SiteModel site, final MediaModel media) { + public void deleteMedia(@NonNull final SiteModel site, @Nullable final MediaModel media) { if (media == null) { // caller may be expecting a notification MediaError error = new MediaError(MediaErrorType.NULL_MEDIA_ARG); @@ -402,39 +367,25 @@ public void deleteMedia(final SiteModel site, final MediaModel media) { String url = WPCOMREST.sites.site(site.getSiteId()).media.item(media.getMediaId()).delete.getUrlV1_1(); add(WPComGsonRequest.buildPostRequest(url, null, MediaWPComRestResponse.class, - new Listener() { - @Override - public void onResponse(MediaWPComRestResponse response) { - MediaModel deletedMedia = mMediaResponseUtils.getMediaFromRestResponse(response); - if (deletedMedia != null) { - AppLog.v(T.MEDIA, "deleted media: " + media.getTitle()); - notifyMediaDeleted(site, media, null); - } else { - String message = "could not parse delete media response, ID: " + media.getMediaId(); - AppLog.w(T.MEDIA, message); - MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); - error.logMessage = message; - notifyMediaDeleted(site, media, error); - } - } - }, new WPComErrorListener() { - @Override - public void onErrorResponse(@NonNull WPComGsonNetworkError error) { - AppLog.e(T.MEDIA, "VolleyError deleting media (ID=" + media.getMediaId() + "): " + error); - MediaErrorType mediaErrorType = MediaErrorType.fromBaseNetworkError(error); - if (mediaErrorType == MediaErrorType.NOT_FOUND) { - AppLog.i(T.MEDIA, "Attempted to delete media that does not exist remotely."); - } - MediaError mediaError = new MediaError(mediaErrorType); - mediaError.message = error.message; - mediaError.logMessage = error.apiError; - notifyMediaDeleted(site, media, mediaError); + response -> { + mMediaResponseUtils.getMediaFromRestResponse(response); + AppLog.v(T.MEDIA, "deleted media: " + media.getTitle()); + notifyMediaDeleted(site, media, null); + }, + error -> { + AppLog.e(T.MEDIA, "VolleyError deleting media (ID=" + media.getMediaId() + "): " + error); + MediaErrorType mediaErrorType = MediaErrorType.fromBaseNetworkError(error); + if (mediaErrorType == MediaErrorType.NOT_FOUND) { + AppLog.i(T.MEDIA, "Attempted to delete media that does not exist remotely."); } - } - )); + MediaError mediaError = new MediaError(mediaErrorType); + mediaError.message = error.message; + mediaError.logMessage = error.apiError; + notifyMediaDeleted(site, media, mediaError); + })); } - public void cancelUpload(final MediaModel media) { + public void cancelUpload(@Nullable final MediaModel media) { if (media == null) { MediaError error = new MediaError(MediaErrorType.NULL_MEDIA_ARG); error.logMessage = "Null media on cancel upload"; @@ -457,7 +408,7 @@ public void cancelUpload(final MediaModel media) { private void removeCallFromCurrentUploadsMap(int id) { mCurrentUploadCalls.remove(id); AppLog.d(T.MEDIA, "mediaRestClient: removed id: " + id + " from current uploads, remaining: " - + mCurrentUploadCalls.size()); + + mCurrentUploadCalls.size()); } public void uploadStockMedia(@NonNull final SiteModel site, @@ -477,25 +428,24 @@ public void uploadStockMedia(@NonNull final SiteModel site, body.put("service", "pexels"); body.put("external_ids", jsonBody); - WPComGsonRequest request = WPComGsonRequest.buildPostRequest(url, body, MultipleMediaResponse.class, - new com.android.volley.Response.Listener() { - @Override - public void onResponse(MultipleMediaResponse response) { - // response is a list of media, exactly like that of MediaRestClient.fetchMediaList() - List mediaList = - mMediaResponseUtils.getMediaListFromRestResponse(response, site.getId()); - UploadedStockMediaPayload payload = new UploadedStockMediaPayload(site, mediaList); - mDispatcher.dispatch(MediaActionBuilder.newUploadedStockMediaAction(payload)); - } - }, new WPComErrorListener() { - @Override - public void onErrorResponse(@NonNull WPComGsonNetworkError error) { - AppLog.e(AppLog.T.MEDIA, "VolleyError uploading stock media: " + error); - UploadStockMediaError mediaError = new UploadStockMediaError( - UploadStockMediaErrorType.fromNetworkError(error), error.message); - UploadedStockMediaPayload payload = new UploadedStockMediaPayload(site, mediaError); - mDispatcher.dispatch(MediaActionBuilder.newUploadedStockMediaAction(payload)); - } + WPComGsonRequest request = WPComGsonRequest.buildPostRequest( + url, + body, + MultipleMediaResponse.class, + response -> { + // response is a list of media, exactly like that of MediaRestClient.fetchMediaList() + List mediaList = mMediaResponseUtils.getMediaListFromRestResponse( + response, + site.getId()); + UploadedStockMediaPayload payload = new UploadedStockMediaPayload(site, mediaList); + mDispatcher.dispatch(MediaActionBuilder.newUploadedStockMediaAction(payload)); + }, + error -> { + AppLog.e(T.MEDIA, "VolleyError uploading stock media: " + error); + UploadStockMediaError mediaError = new UploadStockMediaError( + UploadStockMediaErrorType.fromNetworkError(error), error.message); + UploadedStockMediaPayload payload = new UploadedStockMediaPayload(site, mediaError); + mDispatcher.dispatch(MediaActionBuilder.newUploadedStockMediaAction(payload)); }); add(request); @@ -504,7 +454,10 @@ public void onErrorResponse(@NonNull WPComGsonNetworkError error) { // // Helper methods to dispatch media actions // - private MediaError parseUploadError(Response response, SiteModel siteModel) { + @NonNull + private MediaError parseUploadError( + @NonNull Response response, + @NonNull SiteModel siteModel) { MediaError mediaError = new MediaError(MediaErrorType.fromHttpStatusCode(response.code())); mediaError.statusCode = response.code(); mediaError.logMessage = response.message(); @@ -559,17 +512,20 @@ private MediaError parseUploadError(Response response, SiteModel siteModel) { return mediaError; } - private void notifyMediaPushed(SiteModel site, MediaModel media, MediaError error) { + private void notifyMediaPushed( + @NonNull SiteModel site, + @Nullable MediaModel media, + @Nullable MediaError error) { MediaPayload payload = new MediaPayload(site, media, error); mDispatcher.dispatch(MediaActionBuilder.newPushedMediaAction(payload)); } - private void notifyMediaProgress(MediaModel media, float progress) { + private void notifyMediaProgress(@NonNull MediaModel media, float progress) { ProgressPayload payload = new ProgressPayload(media, progress, false, null); mDispatcher.dispatch(UploadActionBuilder.newUploadedMediaAction(payload)); } - private void notifyMediaUploaded(MediaModel media, MediaError error) { + private void notifyMediaUploaded(@Nullable MediaModel media, @Nullable MediaError error) { if (media != null) { media.setUploadState(error == null ? MediaUploadState.UPLOADED : MediaUploadState.FAILED); removeCallFromCurrentUploadsMap(media.getId()); @@ -579,32 +535,42 @@ private void notifyMediaUploaded(MediaModel media, MediaError error) { mDispatcher.dispatch(UploadActionBuilder.newUploadedMediaAction(payload)); } - private void notifyMediaListFetched(SiteModel site, - @NonNull List media, - boolean loadedMore, - boolean canLoadMore, - MimeType.Type mimeType) { + private void notifyMediaListFetched( + @NonNull SiteModel site, + @NonNull List media, + boolean loadedMore, + boolean canLoadMore, + @Nullable MimeType.Type mimeType) { FetchMediaListResponsePayload payload = new FetchMediaListResponsePayload(site, media, loadedMore, canLoadMore, mimeType); mDispatcher.dispatch(MediaActionBuilder.newFetchedMediaListAction(payload)); } - private void notifyMediaListFetched(SiteModel site, MediaError error, MimeType.Type mimeType) { + private void notifyMediaListFetched( + @NonNull SiteModel site, + @NonNull MediaError error, + @Nullable MimeType.Type mimeType) { FetchMediaListResponsePayload payload = new FetchMediaListResponsePayload(site, error, mimeType); mDispatcher.dispatch(MediaActionBuilder.newFetchedMediaListAction(payload)); } - private void notifyMediaFetched(SiteModel site, MediaModel media, MediaError error) { + private void notifyMediaFetched( + @NonNull SiteModel site, + @Nullable MediaModel media, + @Nullable MediaError error) { MediaPayload payload = new MediaPayload(site, media, error); mDispatcher.dispatch(MediaActionBuilder.newFetchedMediaAction(payload)); } - private void notifyMediaDeleted(SiteModel site, MediaModel media, MediaError error) { + private void notifyMediaDeleted( + @NonNull SiteModel site, + @Nullable MediaModel media, + @Nullable MediaError error) { MediaPayload payload = new MediaPayload(site, media, error); mDispatcher.dispatch(MediaActionBuilder.newDeletedMediaAction(payload)); } - private void notifyMediaUploadCanceled(MediaModel media) { + private void notifyMediaUploadCanceled(@NonNull MediaModel media) { ProgressPayload payload = new ProgressPayload(media, 0.f, false, true); mDispatcher.dispatch(MediaActionBuilder.newCanceledMediaUploadAction(payload)); } @@ -616,12 +582,12 @@ private void notifyMediaUploadCanceled(MediaModel media) { /** * The current REST API call (v1.1) accepts 'title', 'description', 'caption', 'alt', * and 'parent_id' for all media. Audio media also accepts 'artist' and 'album' attributes. + *

    * - * ref https://developer.wordpress.com/docs/api/1.1/post/sites/%24site/media/ + * @see documentation */ - private Map getEditRequestParams(final MediaModel media) { - if (media == null) return null; - + @NonNull + private Map getEditRequestParams(@NonNull final MediaModel media) { MediaFields[] fieldsToUpdate = media.getFieldsToUpdate(); final Map params = new HashMap<>(); diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaWPComRestResponse.java b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaWPComRestResponse.java index d659d023ae..dcbd0d2da5 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaWPComRestResponse.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/MediaWPComRestResponse.java @@ -1,49 +1,50 @@ package org.wordpress.android.fluxc.network.rest.wpcom.media; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import org.wordpress.android.fluxc.network.Response; import java.util.List; /** * Response to GET request for media items - * - * https://developer.wordpress.com/docs/api/1.1/get/sites/%24site/media/%24media_ID/ + *

    + * @see doc */ +@SuppressWarnings("NotNullFieldNotInitialized") public class MediaWPComRestResponse implements Response { public static final String DELETED_STATUS = "deleted"; - public class MultipleMediaResponse { - public List media; - public List errors; - public int found; + public static class MultipleMediaResponse { + @NonNull public List media; } - public class Thumbnails { - public String thumbnail; - public String medium; - public String large; - public String post_thumbnail; - public String fmt_std; + public static class Thumbnails { + @Nullable public String thumbnail; + @Nullable public String medium; + @Nullable public String large; + @Nullable public String fmt_std; } public long ID; - public String date; + @NonNull public String date; public long post_ID; public long author_ID; - public String URL; - public String guid; - public String file; - public String extension; - public String mime_type; - public String title; - public String caption; - public String description; - public String alt; - public Thumbnails thumbnails; + @NonNull public String URL; + @NonNull public String guid; + @NonNull public String file; + @NonNull public String extension; + @NonNull public String mime_type; + @NonNull public String title; + @NonNull public String caption; + @NonNull public String description; + @NonNull public String alt; + @Nullable public Thumbnails thumbnails; public int height; public int width; public int length; - public String videopress_guid; + @Nullable public String videopress_guid; public boolean videopress_processing_done; - public String status; + @Nullable public String status; } diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/RestUploadRequestBody.java b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/RestUploadRequestBody.java index 6bc6485ee2..6355b4f1a1 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/RestUploadRequestBody.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/media/RestUploadRequestBody.java @@ -20,19 +20,22 @@ /** * Wrapper for {@link MultipartBody} that reports upload progress as body data is written. - * + *

    * A {@link ProgressListener} is required, use {@link MultipartBody} if progress is not needed. - * - * ref http://stackoverflow.com/questions/35528751/okhttp-3-tracking-multipart-upload-progress + *

    + * @see doc */ public class RestUploadRequestBody extends BaseUploadRequestBody { private static final String MEDIA_DATA_KEY = "media[0]"; private static final String MEDIA_ATTRIBUTES_KEY = "attrs[0]"; private static final String MEDIA_PARAM_FORMAT = MEDIA_ATTRIBUTES_KEY + "[%s]"; - private final MultipartBody mMultipartBody; + @NonNull private final MultipartBody mMultipartBody; - public RestUploadRequestBody(MediaModel media, Map params, ProgressListener listener) { + public RestUploadRequestBody( + @NonNull MediaModel media, + @NonNull Map params, + @NonNull ProgressListener listener) { super(media, listener); mMultipartBody = buildMultipartBody(params); } @@ -52,6 +55,7 @@ public long contentLength() { return -1L; } + @NonNull @Override public MediaType contentType() { return mMultipartBody.contentType(); @@ -65,13 +69,18 @@ public void writeTo(@NonNull BufferedSink sink) throws IOException { bufferedSink.flush(); } - private MultipartBody buildMultipartBody(Map params) { + @NonNull + @SuppressWarnings("deprecation") + private MultipartBody buildMultipartBody(@NonNull Map params) { MediaModel media = getMedia(); MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM); // add media attributes for (String key : params.keySet()) { - builder.addFormDataPart(String.format(MEDIA_PARAM_FORMAT, key), params.get(key).toString()); + Object value = params.get(key); + if (value != null) { + builder.addFormDataPart(String.format(MEDIA_PARAM_FORMAT, key), value.toString()); + } } // add media file data diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/stockmedia/StockMediaRestClient.kt b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/stockmedia/StockMediaRestClient.kt index c3ee88245b..25ae6ba3eb 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/stockmedia/StockMediaRestClient.kt +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/stockmedia/StockMediaRestClient.kt @@ -110,7 +110,7 @@ class StockMediaRestClient @Inject constructor( val mediaList: List = mediaResponseUtils.getMediaListFromRestResponse( response.data, site.id - ) ?: listOf() + ) UploadedStockMediaPayload(site, mediaList) } is Error -> { diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/xmlrpc/media/MediaXMLRPCClient.java b/fluxc/src/main/java/org/wordpress/android/fluxc/network/xmlrpc/media/MediaXMLRPCClient.java index ff9c83a76c..169c7650ba 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/xmlrpc/media/MediaXMLRPCClient.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/xmlrpc/media/MediaXMLRPCClient.java @@ -4,6 +4,7 @@ import android.util.Base64; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.android.volley.RequestQueue; import com.android.volley.Response.Listener; @@ -18,7 +19,6 @@ import org.wordpress.android.fluxc.model.MediaModel.MediaUploadState; import org.wordpress.android.fluxc.model.SiteModel; import org.wordpress.android.fluxc.network.BaseRequest; -import org.wordpress.android.fluxc.network.BaseRequest.BaseErrorListener; import org.wordpress.android.fluxc.network.BaseRequest.BaseNetworkError; import org.wordpress.android.fluxc.network.BaseUploadRequestBody.ProgressListener; import org.wordpress.android.fluxc.network.HTTPAuthManager; @@ -48,9 +48,8 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -75,71 +74,74 @@ public class MediaXMLRPCClient extends BaseXMLRPCClient implements ProgressListe private static final String[] REQUIRED_UPLOAD_RESPONSE_FIELDS = { "attachment_id", "parent", "title", "caption", "description", "thumbnail", "date_created_gmt", "link"}; - private OkHttpClient mOkHttpClient; + @NonNull private final OkHttpClient mOkHttpClient; // this will hold which media is being uploaded by which call, in order to be able // to monitor multiple uploads - private ConcurrentHashMap mCurrentUploadCalls = new ConcurrentHashMap<>(); - - @Inject public MediaXMLRPCClient(Dispatcher dispatcher, - @Named("custom-ssl") RequestQueue requestQueue, - @Named("custom-ssl") OkHttpClient okHttpClient, - UserAgent userAgent, - HTTPAuthManager httpAuthManager) { + @NonNull private final ConcurrentHashMap mCurrentUploadCalls = new ConcurrentHashMap<>(); + + @Inject public MediaXMLRPCClient( + Dispatcher dispatcher, + @Named("custom-ssl") RequestQueue requestQueue, + @NonNull @Named("custom-ssl") OkHttpClient okHttpClient, + UserAgent userAgent, + HTTPAuthManager httpAuthManager) { super(dispatcher, requestQueue, userAgent, httpAuthManager); mOkHttpClient = okHttpClient; } @Override - public void onProgress(MediaModel media, float progress) { + public void onProgress(@NonNull MediaModel media, float progress) { if (mCurrentUploadCalls.containsKey(media.getId())) { notifyMediaProgress(media, Math.min(progress, 0.99f)); } } - public void pushMedia(final SiteModel site, final MediaModel media) { + public void pushMedia(@NonNull final SiteModel site, @Nullable final MediaModel media) { + if (media == null) { + // caller may be expecting a notification + MediaError error = new MediaError(MediaErrorType.NULL_MEDIA_ARG); + error.logMessage = "Pushed media is null"; + notifyMediaPushed(site, null, error); + return; + } + List params = getBasicParams(site, media); params.add(getEditMediaFields(media)); add(new XMLRPCRequest(site.getXmlRpcUrl(), XMLRPC.EDIT_POST, params, - new Listener() { - @Override - public void onResponse(Object response) { - // response should be a boolean indicating result of push request - if (response == null || !(response instanceof Boolean) || !(Boolean) response) { - String message = "could not parse XMLRPC.EDIT_MEDIA response: " + response; - AppLog.w(T.MEDIA, message); - MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); - error.logMessage = message; - notifyMediaPushed(site, media, error); - return; - } + (Listener) response -> { + // response should be a boolean indicating result of push request + if (!(response instanceof Boolean) || !(Boolean) response) { + String message = "could not parse XMLRPC.EDIT_MEDIA response: " + response; + AppLog.w(T.MEDIA, message); + MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); + error.logMessage = message; + notifyMediaPushed(site, media, error); + return; + } - // success! - AppLog.i(T.MEDIA, "Media updated on remote: " + media.getTitle()); + // success! + AppLog.i(T.MEDIA, "Media updated on remote: " + media.getTitle()); + notifyMediaPushed(site, media, null); + }, + error -> { + String errorMessage = "error response to XMLRPC.EDIT_MEDIA request: " + error; + AppLog.e(T.MEDIA, errorMessage); + if (is404Response(error)) { + AppLog.e(T.MEDIA, "media does not exist, no need to report error"); notifyMediaPushed(site, media, null); + } else { + MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); + mediaError.message = error.message; + mediaError.logMessage = errorMessage; + notifyMediaPushed(site, media, mediaError); } - }, new BaseErrorListener() { - @Override - public void onErrorResponse(@NonNull BaseNetworkError error) { - String errorMessage = "error response to XMLRPC.EDIT_MEDIA request: " + error; - AppLog.e(T.MEDIA, errorMessage); - if (is404Response(error)) { - AppLog.e(T.MEDIA, "media does not exist, no need to report error"); - notifyMediaPushed(site, media, null); - } else { - MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); - mediaError.message = error.message; - mediaError.logMessage = errorMessage; - notifyMediaPushed(site, media, mediaError); - } - } - } - )); + })); } /** - * ref: https://codex.wordpress.org/XML-RPC_WordPress_API/Media#wp.uploadFile + * @see documentation */ - public void uploadMedia(final SiteModel site, final MediaModel media) { + public void uploadMedia(@NonNull final SiteModel site, @Nullable final MediaModel media) { URL xmlrpcUrl; try { xmlrpcUrl = new URL(site.getXmlRpcUrl()); @@ -204,7 +206,8 @@ public void uploadMedia(final SiteModel site, final MediaModel media) { AppLog.d(T.MEDIA, "starting upload for: " + media.getId()); call.enqueue(new Callback() { @Override - public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { + @SuppressWarnings("rawtypes") + public void onResponse(@NonNull Call call, @NonNull Response response) { if (response.code() == HttpURLConnection.HTTP_OK) { // HTTP_OK code doesn't mean the upload is successful, XML-RPC API returns code 200 with an // xml field "faultCode" on error. @@ -221,13 +224,21 @@ public void onResponse(@NonNull Call call, @NonNull Response response) throws IO fetchMedia(site, media, true); } else { MediaModel responseMedia = getMediaFromXmlrpcResponse(responseMap); - // Retain local IDs - responseMedia.setId(media.getId()); - responseMedia.setLocalSiteId(site.getId()); - responseMedia.setLocalPostId(media.getLocalPostId()); - responseMedia.setMarkedLocallyAsFeatured(media.getMarkedLocallyAsFeatured()); - - notifyMediaUploaded(responseMedia, null); + if (responseMedia != null) { + // Retain local IDs + responseMedia.setId(media.getId()); + responseMedia.setLocalSiteId(site.getId()); + responseMedia.setLocalPostId(media.getLocalPostId()); + responseMedia.setMarkedLocallyAsFeatured(media.getMarkedLocallyAsFeatured()); + + notifyMediaUploaded(responseMedia, null); + } else { + String message = "could not parse Upload media response, ID: " + media.getMediaId(); + AppLog.w(T.MEDIA, message); + MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); + error.logMessage = "XMLRPC: " + message; + notifyMediaUploaded(media, error); + } } } else { String message = "error uploading media - malformed response: " + response.message(); @@ -270,9 +281,13 @@ public void onFailure(@NonNull Call call, @NonNull IOException e) { } /** - * ref: https://codex.wordpress.org/XML-RPC_WordPress_API/Media#wp.getMediaLibrary + * @see documentation */ - public void fetchMediaList(final SiteModel site, final int number, final int offset, final MimeType.Type mimeType) { + public void fetchMediaList( + @NonNull final SiteModel site, + final int number, + final int offset, + @Nullable final MimeType.Type mimeType) { List params = getBasicParams(site, null); Map queryParams = new HashMap<>(); queryParams.put("number", number); @@ -285,44 +300,33 @@ public void fetchMediaList(final SiteModel site, final int number, final int off params.add(queryParams); add(new XMLRPCRequest(site.getXmlRpcUrl(), XMLRPC.GET_MEDIA_LIBRARY, params, - new Listener() { - @Override - public void onResponse(Object[] response) { - List mediaList = getMediaListFromXmlrpcResponse(response, site.getId()); - if (mediaList != null) { - AppLog.v(T.MEDIA, "Fetched media list for site via XMLRPC.GET_MEDIA_LIBRARY"); - boolean canLoadMore = mediaList.size() == number; - notifyMediaListFetched(site, mediaList, offset > 0, canLoadMore, mimeType); - } else { - String message = "could not parse XMLRPC.GET_MEDIA_LIBRARY response: " - + Arrays.toString(response); - AppLog.w(T.MEDIA, message); - MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); - error.logMessage = "XMLRPC: " + message; - notifyMediaListFetched(site, error, mimeType); - } - } - }, new BaseErrorListener() { - @Override - public void onErrorResponse(@NonNull BaseNetworkError error) { - String message = "XMLRPC.GET_MEDIA_LIBRARY error response:"; - AppLog.e(T.MEDIA, message, error.volleyError); - MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); - mediaError.logMessage = "XMLRPC: " + message; - notifyMediaListFetched(site, mediaError, mimeType); - } - } - )); + response -> { + List mediaList = getMediaListFromXmlrpcResponse(response, site.getId()); + AppLog.v(T.MEDIA, "Fetched media list for site via XMLRPC.GET_MEDIA_LIBRARY"); + boolean canLoadMore = mediaList.size() == number; + notifyMediaListFetched(site, mediaList, offset > 0, canLoadMore, mimeType); + }, + error -> { + String message = "XMLRPC.GET_MEDIA_LIBRARY error response:"; + AppLog.e(T.MEDIA, message, error.volleyError); + MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); + mediaError.logMessage = "XMLRPC: " + message; + notifyMediaListFetched(site, mediaError, mimeType); + })); } - public void fetchMedia(final SiteModel site, final MediaModel media) { + public void fetchMedia(@NonNull final SiteModel site, @Nullable final MediaModel media) { fetchMedia(site, media, false); } /** - * ref: https://codex.wordpress.org/XML-RPC_WordPress_API/Media#wp.getMediaItem + * @see documentation */ - private void fetchMedia(final SiteModel site, final MediaModel media, final boolean isFreshUpload) { + @SuppressWarnings("rawtypes") + private void fetchMedia( + @NonNull final SiteModel site, + @Nullable final MediaModel media, + final boolean isFreshUpload) { if (media == null) { // caller may be expecting a notification MediaError error = new MediaError(MediaErrorType.NULL_MEDIA_ARG); @@ -337,59 +341,53 @@ private void fetchMedia(final SiteModel site, final MediaModel media, final bool List params = getBasicParams(site, media); add(new XMLRPCRequest(site.getXmlRpcUrl(), XMLRPC.GET_MEDIA_ITEM, params, - new Listener() { - @Override - public void onResponse(Object response) { - AppLog.v(T.MEDIA, "Fetched media for site via XMLRPC.GET_MEDIA_ITEM"); - MediaModel responseMedia = getMediaFromXmlrpcResponse((HashMap) response); - if (responseMedia != null) { - AppLog.v(T.MEDIA, "Fetched media with remoteId= " + media.getMediaId() - + " localId=" + media.getId()); - // Retain local IDs - responseMedia.setId(media.getId()); - responseMedia.setLocalSiteId(site.getId()); - responseMedia.setLocalPostId(media.getLocalPostId()); - responseMedia.setMarkedLocallyAsFeatured(media.getMarkedLocallyAsFeatured()); - - if (isFreshUpload) { - notifyMediaUploaded(responseMedia, null); - } else { - notifyMediaFetched(site, responseMedia, null); - } + (Listener) response -> { + AppLog.v(T.MEDIA, "Fetched media for site via XMLRPC.GET_MEDIA_ITEM"); + MediaModel responseMedia = getMediaFromXmlrpcResponse((HashMap) response); + if (responseMedia != null) { + AppLog.v(T.MEDIA, "Fetched media with remoteId= " + media.getMediaId() + + " localId=" + media.getId()); + // Retain local IDs + responseMedia.setId(media.getId()); + responseMedia.setLocalSiteId(site.getId()); + responseMedia.setLocalPostId(media.getLocalPostId()); + responseMedia.setMarkedLocallyAsFeatured(media.getMarkedLocallyAsFeatured()); + + if (isFreshUpload) { + notifyMediaUploaded(responseMedia, null); } else { - String message = "could not parse Fetch media response, ID: " + media.getMediaId(); - AppLog.w(T.MEDIA, message); - MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); - error.logMessage = "XMLRPC: " + message; - if (isFreshUpload) { - notifyMediaUploaded(media, error); - } else { - notifyMediaFetched(site, media, error); - } + notifyMediaFetched(site, responseMedia, null); } - } - }, new BaseErrorListener() { - @Override - public void onErrorResponse(@NonNull BaseNetworkError error) { - String message = "XMLRPC.GET_MEDIA_ITEM error response: " + error; - AppLog.e(T.MEDIA, message); + } else { + String message = "could not parse Fetch media response, ID: " + media.getMediaId(); + AppLog.w(T.MEDIA, message); + MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); + error.logMessage = "XMLRPC: " + message; if (isFreshUpload) { - // we tried to fetch a media that's just uploaded but failed, so we should return - // an upload error and not a fetch error as initially parsing the upload response failed - MediaError mediaError = new MediaError(MediaErrorType.PARSE_ERROR); - mediaError.logMessage = "XMLRPC: " + message; - notifyMediaUploaded(media, mediaError); + notifyMediaUploaded(media, error); } else { - MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); - mediaError.logMessage = "XMLRPC: " + message; - notifyMediaFetched(site, media, mediaError); + notifyMediaFetched(site, media, error); } } - } - )); + }, + error -> { + String message = "XMLRPC.GET_MEDIA_ITEM error response: " + error; + AppLog.e(T.MEDIA, message); + if (isFreshUpload) { + // we tried to fetch a media that's just uploaded but failed, so we should return + // an upload error and not a fetch error as initially parsing the upload response failed + MediaError mediaError = new MediaError(MediaErrorType.PARSE_ERROR); + mediaError.logMessage = "XMLRPC: " + message; + notifyMediaUploaded(media, mediaError); + } else { + MediaError mediaError = new MediaError(MediaErrorType.fromBaseNetworkError(error)); + mediaError.logMessage = "XMLRPC: " + message; + notifyMediaFetched(site, media, mediaError); + } + })); } - public void deleteMedia(final SiteModel site, final MediaModel media) { + public void deleteMedia(@NonNull final SiteModel site, @Nullable final MediaModel media) { if (media == null) { // caller may be expecting a notification MediaError error = new MediaError(MediaErrorType.NULL_MEDIA_ARG); @@ -400,37 +398,31 @@ public void deleteMedia(final SiteModel site, final MediaModel media) { List params = getBasicParams(site, media); add(new XMLRPCRequest(site.getXmlRpcUrl(), XMLRPC.DELETE_POST, params, - new Listener() { - @Override - public void onResponse(Object response) { - // response should be a boolean indicating result of push request - if (response == null || !(response instanceof Boolean) || !(Boolean) response) { - String message = "could not parse XMLRPC.DELETE_MEDIA response: " + response; - AppLog.w(T.MEDIA, message); - MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); - error.logMessage = "XMLRPC: " + message; - notifyMediaDeleted(site, media, error); - return; - } - - AppLog.v(T.MEDIA, "Successful response from XMLRPC.DELETE_MEDIA"); - notifyMediaDeleted(site, media, null); - } - }, new BaseErrorListener() { - @Override - public void onErrorResponse(@NonNull BaseNetworkError error) { - String message = "Error response from XMLRPC.DELETE_MEDIA:" + error; - AppLog.e(T.MEDIA, message); - MediaErrorType mediaErrorType = MediaErrorType.fromBaseNetworkError(error); - MediaError mediaError = new MediaError(mediaErrorType); - mediaError.logMessage = "XMLRPC: " + message; - notifyMediaDeleted(site, media, mediaError); + (Listener) response -> { + // response should be a boolean indicating result of push request + if (!(response instanceof Boolean) || !(Boolean) response) { + String message = "could not parse XMLRPC.DELETE_MEDIA response: " + response; + AppLog.w(T.MEDIA, message); + MediaError error = new MediaError(MediaErrorType.PARSE_ERROR); + error.logMessage = "XMLRPC: " + message; + notifyMediaDeleted(site, media, error); + return; } - } - )); + + AppLog.v(T.MEDIA, "Successful response from XMLRPC.DELETE_MEDIA"); + notifyMediaDeleted(site, media, null); + }, + error -> { + String message = "Error response from XMLRPC.DELETE_MEDIA:" + error; + AppLog.e(T.MEDIA, message); + MediaErrorType mediaErrorType = MediaErrorType.fromBaseNetworkError(error); + MediaError mediaError = new MediaError(mediaErrorType); + mediaError.logMessage = "XMLRPC: " + message; + notifyMediaDeleted(site, media, mediaError); + })); } - public void cancelUpload(final MediaModel media) { + public void cancelUpload(@Nullable final MediaModel media) { if (media == null) { MediaError error = new MediaError(MediaErrorType.NULL_MEDIA_ARG); error.logMessage = "XMLRPC: empty media on cancel upload"; @@ -453,24 +445,27 @@ public void cancelUpload(final MediaModel media) { private void removeCallFromCurrentUploadsMap(int id) { mCurrentUploadCalls.remove(id); AppLog.d(T.MEDIA, "mediaXMLRPCClient: removed id: " + id + " from current uploads, remaining: " - + mCurrentUploadCalls.size()); + + mCurrentUploadCalls.size()); } // // Helper methods to dispatch media actions // - private void notifyMediaPushed(SiteModel site, MediaModel media, MediaError error) { + private void notifyMediaPushed( + @NonNull SiteModel site, + @Nullable MediaModel media, + @Nullable MediaError error) { MediaPayload payload = new MediaPayload(site, media, error); mDispatcher.dispatch(MediaActionBuilder.newPushedMediaAction(payload)); } - private void notifyMediaProgress(MediaModel media, float progress) { + private void notifyMediaProgress(@NonNull MediaModel media, float progress) { ProgressPayload payload = new ProgressPayload(media, progress, false, null); mDispatcher.dispatch(UploadActionBuilder.newUploadedMediaAction(payload)); } - private void notifyMediaUploaded(MediaModel media, MediaError error) { + private void notifyMediaUploaded(@Nullable MediaModel media, @Nullable MediaError error) { if (media != null) { media.setUploadState(error == null ? MediaUploadState.UPLOADED : MediaUploadState.FAILED); removeCallFromCurrentUploadsMap(media.getId()); @@ -480,32 +475,42 @@ private void notifyMediaUploaded(MediaModel media, MediaError error) { mDispatcher.dispatch(UploadActionBuilder.newUploadedMediaAction(payload)); } - private void notifyMediaListFetched(SiteModel site, - @NonNull List media, - boolean loadedMore, - boolean canLoadMore, - MimeType.Type mimeType) { + private void notifyMediaListFetched( + @NonNull SiteModel site, + @NonNull List media, + boolean loadedMore, + boolean canLoadMore, + @Nullable MimeType.Type mimeType) { FetchMediaListResponsePayload payload = new FetchMediaListResponsePayload(site, media, loadedMore, canLoadMore, mimeType); mDispatcher.dispatch(MediaActionBuilder.newFetchedMediaListAction(payload)); } - private void notifyMediaListFetched(SiteModel site, MediaError error, MimeType.Type mimeType) { + private void notifyMediaListFetched( + @NonNull SiteModel site, + @NonNull MediaError error, + @Nullable MimeType.Type mimeType) { FetchMediaListResponsePayload payload = new FetchMediaListResponsePayload(site, error, mimeType); mDispatcher.dispatch(MediaActionBuilder.newFetchedMediaListAction(payload)); } - private void notifyMediaFetched(SiteModel site, MediaModel media, MediaError error) { + private void notifyMediaFetched( + @NonNull SiteModel site, + @Nullable MediaModel media, + @Nullable MediaError error) { MediaPayload payload = new MediaPayload(site, media, error); mDispatcher.dispatch(MediaActionBuilder.newFetchedMediaAction(payload)); } - private void notifyMediaDeleted(SiteModel site, MediaModel media, MediaError error) { + private void notifyMediaDeleted( + @NonNull SiteModel site, + @Nullable MediaModel media, + @Nullable MediaError error) { MediaPayload payload = new MediaPayload(site, media, error); mDispatcher.dispatch(MediaActionBuilder.newDeletedMediaAction(payload)); } - private void notifyMediaUploadCanceled(MediaModel media) { + private void notifyMediaUploadCanceled(@NonNull MediaModel media) { ProgressPayload payload = new ProgressPayload(media, 0.f, false, true); mDispatcher.dispatch(MediaActionBuilder.newCanceledMediaUploadAction(payload)); } @@ -515,24 +520,29 @@ private void notifyMediaUploadCanceled(MediaModel media) { // // media list responses should be of type Object[] with each media item in the array represented by a HashMap - private List getMediaListFromXmlrpcResponse(Object[] response, int localSiteId) { - if (response == null) return null; - + @NonNull + @SuppressWarnings("rawtypes") + private List getMediaListFromXmlrpcResponse(@NonNull Object[] response, int localSiteId) { List responseMedia = new ArrayList<>(); for (Object mediaObject : response) { - if (!(mediaObject instanceof HashMap)) continue; + if (!(mediaObject instanceof HashMap)) { + continue; + } MediaModel media = getMediaFromXmlrpcResponse((HashMap) mediaObject); if (media != null) { media.setLocalSiteId(localSiteId); responseMedia.add(media); } } - return responseMedia; } - private MediaModel getMediaFromXmlrpcResponse(Map response) { - if (response == null || response.isEmpty()) return null; + @Nullable + @SuppressWarnings("rawtypes") + private MediaModel getMediaFromXmlrpcResponse(@NonNull Map response) { + if (response.isEmpty()) { + return null; + } MediaModel media = new MediaModel(); media.setMediaId(MapUtils.getMapLong(response, "attachment_id")); @@ -565,8 +575,13 @@ private MediaModel getMediaFromXmlrpcResponse(Map response) { return media; } - private String getFileUrlForSize(String mediaUrl, Map metadataMap, String size) { - if (metadataMap == null || TextUtils.isEmpty(mediaUrl) || !mediaUrl.contains("/")) { + @Nullable + @SuppressWarnings("rawtypes") + private String getFileUrlForSize( + @NonNull String mediaUrl, + @NonNull Map metadataMap, + @NonNull String size) { + if (TextUtils.isEmpty(mediaUrl) || !mediaUrl.contains("/")) { return null; } @@ -576,16 +591,19 @@ private String getFileUrlForSize(String mediaUrl, Map metadataMap, String size) } // make sure the path to the original image is a valid path to a file - if (mediaUrl.lastIndexOf("/") + 1 >= mediaUrl.length()) return null; + if (mediaUrl.lastIndexOf("/") + 1 >= mediaUrl.length()) { + return null; + } String baseURL = mediaUrl.substring(0, mediaUrl.lastIndexOf("/") + 1); return baseURL + fileName; } - private String getFileForSize(Map metadataMap, String size) { - if (metadataMap == null) { - return null; - } + @Nullable + @SuppressWarnings("rawtypes") + private String getFileForSize( + @NonNull Map metadataMap, + @NonNull String size) { Object sizesObject = metadataMap.get("sizes"); if (sizesObject instanceof Map) { Map sizesMap = (Map) sizesObject; @@ -598,7 +616,8 @@ private String getFileForSize(Map metadataMap, String size) { return null; } - private MediaError getMediaErrorFromXMLRPCException(XMLRPCException exception) { + @NonNull + private MediaError getMediaErrorFromXMLRPCException(@NonNull XMLRPCException exception) { MediaError mediaError = new MediaError(MediaErrorType.GENERIC_ERROR); mediaError.message = exception.getLocalizedMessage(); mediaError.logMessage = exception.getMessage(); @@ -621,15 +640,17 @@ private MediaError getMediaErrorFromXMLRPCException(XMLRPCException exception) { return mediaError; } - private static Map getMapFromUploadResponse(Response response) throws XMLRPCException { + @Nullable + @SuppressWarnings("rawtypes") + private static Map getMapFromUploadResponse(@NonNull Response response) throws XMLRPCException { try { ResponseBody responseBody = response.body(); if (responseBody == null) { AppLog.e(T.MEDIA, "Failed to parse XMLRPC.wpUploadFile response - body was empty: " + response); return null; } - String data = new String(responseBody.bytes(), "UTF-8"); - InputStream is = new ByteArrayInputStream(data.getBytes(Charset.forName("UTF-8"))); + String data = new String(responseBody.bytes(), StandardCharsets.UTF_8); + InputStream is = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)); Object responseObject = XMLSerializerUtils.deserialize(XMLSerializerUtils.scrubXmlResponse(is)); if (responseObject instanceof Map) { return (Map) responseObject; @@ -641,7 +662,8 @@ private static Map getMapFromUploadResponse(Response response) throws XMLRPCExce return null; } - private static boolean isDeprecatedUploadResponse(Map responseMap) { + @SuppressWarnings("rawtypes") + private static boolean isDeprecatedUploadResponse(@NonNull Map responseMap) { for (String requiredResponseField : REQUIRED_UPLOAD_RESPONSE_FIELDS) { if (!responseMap.containsKey(requiredResponseField)) { return true; @@ -650,8 +672,11 @@ private static boolean isDeprecatedUploadResponse(Map responseMap) { return false; } - private Map getEditMediaFields(final MediaModel media) { - if (media == null) return null; + @Nullable + private Map getEditMediaFields(@Nullable final MediaModel media) { + if (media == null) { + return null; + } Map mediaFields = new HashMap<>(); mediaFields.put("post_title", media.getTitle()); mediaFields.put("post_content", media.getDescription()); @@ -659,7 +684,7 @@ private Map getEditMediaFields(final MediaModel media) { return mediaFields; } - private boolean is404Response(BaseNetworkError error) { + private boolean is404Response(@NonNull BaseNetworkError error) { if (error.isGeneric() && error.type == BaseRequest.GenericErrorType.NOT_FOUND) { return true; } @@ -667,14 +692,12 @@ private boolean is404Response(BaseNetworkError error) { if (error.hasVolleyError() && error.volleyError != null) { VolleyError volleyError = error.volleyError; if (volleyError.networkResponse != null - && volleyError.networkResponse.statusCode == HttpURLConnection.HTTP_NOT_FOUND) { + && volleyError.networkResponse.statusCode == HttpURLConnection.HTTP_NOT_FOUND) { return true; } if (volleyError.getCause() instanceof XMLRPCFault) { - if (((XMLRPCFault) volleyError.getCause()).getFaultCode() == HttpURLConnection.HTTP_NOT_FOUND) { - return true; - } + return ((XMLRPCFault) volleyError.getCause()).getFaultCode() == HttpURLConnection.HTTP_NOT_FOUND; } } @@ -682,15 +705,13 @@ private boolean is404Response(BaseNetworkError error) { } @NonNull - private List getBasicParams(final SiteModel site, final MediaModel media) { + private List getBasicParams(@NonNull final SiteModel site, @Nullable final MediaModel media) { List params = new ArrayList<>(); - if (site != null) { - params.add(site.getSelfHostedSiteId()); - params.add(site.getUsername()); - params.add(site.getPassword()); - if (media != null) { - params.add(media.getMediaId()); - } + params.add(site.getSelfHostedSiteId()); + params.add(site.getUsername()); + params.add(site.getPassword()); + if (media != null) { + params.add(media.getMediaId()); } return params; } diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/xmlrpc/media/XmlrpcUploadRequestBody.java b/fluxc/src/main/java/org/wordpress/android/fluxc/network/xmlrpc/media/XmlrpcUploadRequestBody.java index 3c23f28718..e36f52b4b7 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/xmlrpc/media/XmlrpcUploadRequestBody.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/xmlrpc/media/XmlrpcUploadRequestBody.java @@ -39,12 +39,16 @@ public class XmlrpcUploadRequestBody extends BaseUploadRequestBody { private static final String APPEND_XML = ""; - private final String mPrependString; + @NonNull private final String mPrependString; private long mMediaSize; private long mContentSize = -1; private long mMediaBytesWritten = 0; - public XmlrpcUploadRequestBody(MediaModel media, ProgressListener listener, SiteModel site) { + @SuppressWarnings("deprecation") + public XmlrpcUploadRequestBody( + @NonNull MediaModel media, + @NonNull ProgressListener listener, + @NonNull SiteModel site) { super(media, listener); // TODO: we should use the XMLRPCSerializer instead of doing this @@ -69,6 +73,7 @@ protected float getProgress(long bytesWritten) { return (float) mMediaBytesWritten / mMediaSize; } + @NonNull @Override public MediaType contentType() { return MEDIA_TYPE; @@ -109,8 +114,7 @@ public void writeTo(@NonNull BufferedSink sink) throws IOException { // write file to xml - FileInputStream fis = new FileInputStream(getMedia().getFilePath()); - try { + try (FileInputStream fis = new FileInputStream(getMedia().getFilePath())) { byte[] buffer = new byte[3600]; // you must use a 24bit multiple int length; String chunk; @@ -119,8 +123,6 @@ public void writeTo(@NonNull BufferedSink sink) throws IOException { mMediaBytesWritten += length; bufferedSink.writeUtf8(chunk); } - } finally { - fis.close(); } // write remainder or XML diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/store/MediaStore.java b/fluxc/src/main/java/org/wordpress/android/fluxc/store/MediaStore.java index ab39f82fca..6bc17dacff 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/store/MediaStore.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/store/MediaStore.java @@ -58,12 +58,14 @@ public class MediaStore extends Store { * Actions: FETCH(ED)_MEDIA, PUSH(ED)_MEDIA, UPLOADED_MEDIA, DELETE(D)_MEDIA, UPDATE_MEDIA, and REMOVE_MEDIA */ public static class MediaPayload extends Payload { - public SiteModel site; - public MediaModel media; - public MediaPayload(SiteModel site, MediaModel media) { + @NonNull public SiteModel site; + @Nullable public MediaModel media; + + public MediaPayload(@NonNull SiteModel site, @NonNull MediaModel media) { this(site, media, null); } - public MediaPayload(SiteModel site, MediaModel media, MediaError error) { + + public MediaPayload(@NonNull SiteModel site, @Nullable MediaModel media, @Nullable MediaError error) { this.site = site; this.media = media; this.error = error; @@ -76,12 +78,19 @@ public MediaPayload(SiteModel site, MediaModel media, MediaError error) { public static class UploadMediaPayload extends MediaPayload { public final boolean stripLocation; - public UploadMediaPayload(SiteModel site, MediaModel media, boolean stripLocation) { + public UploadMediaPayload( + @NonNull SiteModel site, + @Nullable MediaModel media, + boolean stripLocation) { super(site, media, null); this.stripLocation = stripLocation; } - public UploadMediaPayload(SiteModel site, MediaModel media, MediaError error, boolean stripLocation) { + public UploadMediaPayload( + @NonNull SiteModel site, + @Nullable MediaModel media, + @Nullable MediaError error, + boolean stripLocation) { super(site, media, error); this.stripLocation = stripLocation; } @@ -91,22 +100,30 @@ public UploadMediaPayload(SiteModel site, MediaModel media, MediaError error, bo * Actions: FETCH_MEDIA_LIST */ public static class FetchMediaListPayload extends Payload { - public SiteModel site; + @NonNull public SiteModel site; public boolean loadMore; - public MimeType.Type mimeType; + @Nullable public MimeType.Type mimeType; public int number = DEFAULT_NUM_MEDIA_PER_FETCH; - public FetchMediaListPayload(SiteModel site) { + @SuppressWarnings("unused") + public FetchMediaListPayload(@NonNull SiteModel site) { this.site = site; } - public FetchMediaListPayload(SiteModel site, int number, boolean loadMore) { + public FetchMediaListPayload( + @NonNull SiteModel site, + int number, + boolean loadMore) { this.site = site; this.loadMore = loadMore; this.number = number; } - public FetchMediaListPayload(SiteModel site, int number, boolean loadMore, MimeType.Type mimeType) { + public FetchMediaListPayload( + @NonNull SiteModel site, + int number, + boolean loadMore, + @NonNull MimeType.Type mimeType) { this.site = site; this.loadMore = loadMore; this.mimeType = mimeType; @@ -118,16 +135,18 @@ public FetchMediaListPayload(SiteModel site, int number, boolean loadMore, MimeT * Actions: FETCHED_MEDIA_LIST */ public static class FetchMediaListResponsePayload extends Payload { - public SiteModel site; - public List mediaList; + @NonNull public SiteModel site; + @NonNull public List mediaList; public boolean loadedMore; public boolean canLoadMore; - public MimeType.Type mimeType; - public FetchMediaListResponsePayload(SiteModel site, - @NonNull List mediaList, - boolean loadedMore, - boolean canLoadMore, - MimeType.Type mimeType) { + @Nullable public MimeType.Type mimeType; + + public FetchMediaListResponsePayload( + @NonNull SiteModel site, + @NonNull List mediaList, + boolean loadedMore, + boolean canLoadMore, + @Nullable MimeType.Type mimeType) { this.site = site; this.mediaList = mediaList; this.loadedMore = loadedMore; @@ -135,7 +154,10 @@ public FetchMediaListResponsePayload(SiteModel site, this.mimeType = mimeType; } - public FetchMediaListResponsePayload(SiteModel site, MediaError error, MimeType.Type mimeType) { + public FetchMediaListResponsePayload( + @NonNull SiteModel site, + @NonNull MediaError error, + @Nullable MimeType.Type mimeType) { this.mediaList = new ArrayList<>(); this.site = site; this.error = error; @@ -147,15 +169,25 @@ public FetchMediaListResponsePayload(SiteModel site, MediaError error, MimeType. * Actions: UPLOADED_MEDIA, CANCELED_MEDIA_UPLOAD */ public static class ProgressPayload extends Payload { - public MediaModel media; + @Nullable public MediaModel media; public float progress; public boolean completed; public boolean canceled; - public ProgressPayload(MediaModel media, float progress, boolean completed, boolean canceled) { + + public ProgressPayload( + @NonNull MediaModel media, + float progress, + boolean completed, + boolean canceled) { this(media, progress, completed, null); this.canceled = canceled; } - public ProgressPayload(MediaModel media, float progress, boolean completed, MediaError error) { + + public ProgressPayload( + @Nullable MediaModel media, + float progress, + boolean completed, + @Nullable MediaError error) { this.media = media; this.progress = progress; this.completed = completed; @@ -167,15 +199,15 @@ public ProgressPayload(MediaModel media, float progress, boolean completed, Medi * Actions: CANCEL_MEDIA_UPLOAD */ public static class CancelMediaPayload extends Payload { - public SiteModel site; - public MediaModel media; + @NonNull public SiteModel site; + @NonNull public MediaModel media; public boolean delete; - public CancelMediaPayload(SiteModel site, MediaModel media) { + public CancelMediaPayload(@NonNull SiteModel site, @NonNull MediaModel media) { this(site, media, true); } - public CancelMediaPayload(SiteModel site, MediaModel media, boolean delete) { + public CancelMediaPayload(@NonNull SiteModel site, @NonNull MediaModel media, boolean delete) { this.site = site; this.media = media; this.delete = delete; @@ -225,9 +257,11 @@ public static class MediaError implements OnChangedError { public String message; public int statusCode; public String logMessage; + public MediaError(MediaErrorType type) { this.type = type; } + public MediaError(MediaErrorType type, String message) { this.type = type; this.message = message; @@ -274,7 +308,7 @@ public String getApiUserMessageIfAvailable() { if (type == MediaErrorType.BAD_REQUEST) { String[] splitMsg = message.split("\\|", 2); - if (null != splitMsg && splitMsg.length > 1) { + if (splitMsg.length > 1) { String userMessage = splitMsg[1]; if (TextUtils.isEmpty(userMessage)) { @@ -299,6 +333,7 @@ public String getApiUserMessageIfAvailable() { public static class UploadStockMediaError implements OnChangedError { public UploadStockMediaErrorType type; public String message; + public UploadStockMediaError(UploadStockMediaErrorType type, String message) { this.type = type; this.message = message; @@ -308,15 +343,19 @@ public UploadStockMediaError(UploadStockMediaErrorType type, String message) { public static class OnMediaChanged extends OnChanged { public MediaAction cause; public List mediaList; + public OnMediaChanged(MediaAction cause) { - this(cause, new ArrayList(), null); + this(cause, new ArrayList<>(), null); } + public OnMediaChanged(MediaAction cause, @NonNull List mediaList) { this(cause, mediaList, null); } + public OnMediaChanged(MediaAction cause, MediaError error) { - this(cause, new ArrayList(), error); + this(cause, new ArrayList<>(), error); } + public OnMediaChanged(MediaAction cause, @NonNull List mediaList, MediaError error) { this.cause = cause; this.mediaList = mediaList; @@ -328,11 +367,13 @@ public static class OnMediaListFetched extends OnChanged { public SiteModel site; public boolean canLoadMore; public MimeType.Type mimeType; + public OnMediaListFetched(SiteModel site, boolean canLoadMore, MimeType.Type mimeType) { this.site = site; this.canLoadMore = canLoadMore; this.mimeType = mimeType; } + public OnMediaListFetched(SiteModel site, MediaError error, MimeType.Type mimeType) { this.site = site; this.error = error; @@ -345,6 +386,7 @@ public static class OnMediaUploaded extends OnChanged { public float progress; public boolean completed; public boolean canceled; + public OnMediaUploaded(MediaModel media, float progress, boolean completed, boolean canceled) { this.media = media; this.progress = progress; @@ -362,6 +404,7 @@ public OnStockMediaUploaded(@NonNull SiteModel site, @NonNull List m this.site = site; this.mediaList = mediaList; } + public OnStockMediaUploaded(@NonNull SiteModel site, @NonNull UploadStockMediaError error) { this.site = site; this.error = error; @@ -416,6 +459,13 @@ public static MediaErrorType fromBaseNetworkError(BaseNetworkError baseError) { return MediaErrorType.SERVER_ERROR; case TIMEOUT: return MediaErrorType.TIMEOUT; + case NO_CONNECTION: + case NETWORK_ERROR: + case CENSORED: + case INVALID_SSL_CERTIFICATE: + case HTTP_AUTH_ERROR: + case INVALID_RESPONSE: + case UNKNOWN: default: return MediaErrorType.GENERIC_ERROR; } @@ -497,6 +547,7 @@ public static UploadStockMediaErrorType fromNetworkError(WPComGsonNetworkError w @Subscribe(threadMode = ThreadMode.ASYNC) @Override + @SuppressWarnings("rawtypes") public void onAction(Action action) { IAction actionType = action.getType(); if (!(actionType instanceof MediaAction)) { @@ -570,13 +621,13 @@ public void onRegister() { public MediaModel instantiateMediaModel() { MediaModel media = new MediaModel(); - media = MediaSqlUtils.insertMediaForResult(media); + MediaModel insertedMedia = MediaSqlUtils.insertMediaForResult(media); - if (media.getId() == -1) { - media = null; + if (insertedMedia.getId() == -1) { + return null; } - return media; + return insertedMedia; } public List getAllSiteMedia(SiteModel siteModel) { @@ -584,6 +635,7 @@ public List getAllSiteMedia(SiteModel siteModel) { } public static final List NOT_DELETED_STATES = new ArrayList<>(); + static { NOT_DELETED_STATES.add(MediaUploadState.DELETING.toString()); NOT_DELETED_STATES.add(MediaUploadState.FAILED.toString()); @@ -617,14 +669,17 @@ public List getSiteImages(SiteModel siteModel) { return MediaSqlUtils.getSiteImages(siteModel); } + @SuppressWarnings("unused") public List getSiteVideos(SiteModel siteModel) { return MediaSqlUtils.getSiteVideos(siteModel); } + @SuppressWarnings("unused") public List getSiteAudio(SiteModel siteModel) { return MediaSqlUtils.getSiteAudio(siteModel); } + @SuppressWarnings("unused") public List getSiteDocuments(SiteModel siteModel) { return MediaSqlUtils.getSiteDocuments(siteModel); } @@ -694,6 +749,7 @@ public List getMediaForPost(PostImmutableModel postModel) { return MediaSqlUtils.matchPostMedia(postModel.getId()); } + @SuppressWarnings("unused") public List getMediaForPostWithState(PostImmutableModel postModel, MediaUploadState expectedState) { return MediaSqlUtils.matchPostMedia(postModel.getId(), MediaModelTable.UPLOAD_STATE, expectedState); @@ -719,7 +775,7 @@ private void removeAllMedia() { // Action implementations // - void updateMedia(MediaModel media, boolean emit) { + void updateMedia(@Nullable MediaModel media, boolean emit) { OnMediaChanged event = new OnMediaChanged(MediaAction.UPDATE_MEDIA); if (media == null) { @@ -752,7 +808,7 @@ private void removeMedia(MediaModel media) { // Helper methods that choose the appropriate network client to perform an action // - private void performPushMedia(MediaPayload payload) { + private void performPushMedia(@NonNull MediaPayload payload) { if (payload.media == null) { // null or empty media list -or- list contains a null value notifyMediaError(MediaErrorType.NULL_MEDIA_ARG, MediaAction.PUSH_MEDIA, null); @@ -770,6 +826,7 @@ private void performPushMedia(MediaPayload payload) { } } + @SuppressWarnings("SameParameterValue") private void notifyMediaUploadError(MediaErrorType errorType, String errorMessage, MediaModel media, String logMessage, MalformedMediaArgSubType argErrorType) { OnMediaUploaded onMediaUploaded = new OnMediaUploaded(media, 1, false, false); @@ -779,7 +836,13 @@ private void notifyMediaUploadError(MediaErrorType errorType, String errorMessag emitChange(onMediaUploaded); } - private void performUploadMedia(UploadMediaPayload payload) { + private void performUploadMedia(@NonNull UploadMediaPayload payload) { + if (payload.media == null) { + // null or empty media list -or- list contains a null value + notifyMediaError(MediaErrorType.NULL_MEDIA_ARG, MediaAction.UPLOAD_MEDIA, null); + return; + } + MalformedMediaArgSubType argError = MediaUtils.getMediaValidationErrorType(payload.media); if (argError.getType() != Type.NO_ERROR) { @@ -792,8 +855,7 @@ private void performUploadMedia(UploadMediaPayload payload) { argError.getType().getErrorLogDescription(), payload.media, message, - argError - ); + argError); return; } @@ -816,7 +878,7 @@ private void performUploadMedia(UploadMediaPayload payload) { } } - private void performFetchMediaList(FetchMediaListPayload payload) { + private void performFetchMediaList(@NonNull FetchMediaListPayload payload) { int offset = 0; if (payload.loadMore) { List list = new ArrayList<>(); @@ -840,10 +902,10 @@ private void performFetchMediaList(FetchMediaListPayload payload) { } } - private void performFetchMedia(MediaPayload payload) { - if (payload.site == null || payload.media == null) { + private void performFetchMedia(@NonNull MediaPayload payload) { + if (payload.media == null) { // null or empty media list -or- list contains a null value - notifyMediaError(MediaErrorType.NULL_MEDIA_ARG, MediaAction.FETCH_MEDIA, payload.media); + notifyMediaError(MediaErrorType.NULL_MEDIA_ARG, MediaAction.FETCH_MEDIA, null); return; } @@ -868,10 +930,6 @@ private void performDeleteMedia(@NonNull MediaPayload payload) { } private void performCancelUpload(@NonNull CancelMediaPayload payload) { - if (payload.media == null) { - return; - } - MediaModel media = payload.media; if (payload.delete) { MediaSqlUtils.deleteMedia(media); @@ -991,21 +1049,15 @@ private void handleMediaDeleted(@NonNull MediaPayload payload) { emitChange(onMediaChanged); } - private void notifyMediaError(MediaErrorType errorType, String errorMessage, MediaAction cause, - List media) { - OnMediaChanged mediaChange = new OnMediaChanged(cause, media); - mediaChange.error = new MediaError(errorType, errorMessage); - emitChange(mediaChange); - } - - private void notifyMediaError(MediaErrorType errorType, MediaAction cause, MediaModel media) { - notifyMediaError(errorType, null, cause, media); - } - - private void notifyMediaError(MediaErrorType errorType, String errorMessage, MediaAction cause, MediaModel media) { + private void notifyMediaError( + @NonNull MediaErrorType errorType, + @NonNull MediaAction cause, + @Nullable MediaModel media) { List mediaList = new ArrayList<>(); mediaList.add(media); - notifyMediaError(errorType, errorMessage, cause, mediaList); + OnMediaChanged mediaChange = new OnMediaChanged(cause, mediaList); + mediaChange.error = new MediaError(errorType, null); + emitChange(mediaChange); } private void performUploadStockMedia(UploadStockMediaPayload payload) { diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/store/UploadStore.java b/fluxc/src/main/java/org/wordpress/android/fluxc/store/UploadStore.java index c9f019e6bb..b362381670 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/store/UploadStore.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/store/UploadStore.java @@ -131,7 +131,7 @@ private void onUploadAction(UploadAction actionType, Object payload) { } @SuppressWarnings("EnumSwitchStatementWhichMissesCases") - private void onMediaAction(MediaAction actionType, Object payload) { + private void onMediaAction(MediaAction actionType, @NonNull Object payload) { switch (actionType) { case UPLOAD_MEDIA: handleUploadMedia((MediaPayload) payload); @@ -267,7 +267,10 @@ public float getUploadProgressForMedia(MediaModel mediaModel) { return 0; } - private void handleUploadMedia(MediaPayload payload) { + private void handleUploadMedia(@NonNull MediaPayload payload) { + if (payload.media == null) { + return; + } MediaUploadModel mediaUploadModel = new MediaUploadModel(payload.media.getId()); MalformedMediaArgSubType argError = MediaUtils.getMediaValidationErrorType(payload.media); @@ -326,10 +329,6 @@ private void handleMediaUploaded(@NonNull ProgressPayload payload) { } private void handleCancelMedia(@NonNull CancelMediaPayload payload) { - if (payload.media == null) { - return; - } - // If the cancel action has the delete flag, the corresponding MediaModel will be deleted once this action // reaches the MediaStore, along with the MediaUploadModel (because of the FOREIGN KEY association) // Otherwise, we should mark the MediaUploadModel as FAILED diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/utils/MediaUtils.java b/fluxc/src/main/java/org/wordpress/android/fluxc/utils/MediaUtils.java index 789e858c71..9fccb7568c 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/utils/MediaUtils.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/utils/MediaUtils.java @@ -65,10 +65,12 @@ public static String getMimeTypeForExtension(String extension) { // File operations // + @NonNull public static String getMediaValidationError(@NonNull MediaModel media) { return BaseUploadRequestBody.hasRequiredData(media); } + @NonNull public static MalformedMediaArgSubType getMediaValidationErrorType(@NonNull MediaModel media) { return BaseUploadRequestBody.checkMediaArg(media); }