1 /* 2 * Copyright 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.appsearch.platformstorage.converter; 18 19 import android.os.Build; 20 21 import androidx.annotation.DoNotInline; 22 import androidx.annotation.RequiresApi; 23 import androidx.annotation.RestrictTo; 24 import androidx.appsearch.app.GenericDocument; 25 import androidx.appsearch.app.GetByDocumentIdRequest; 26 import androidx.appsearch.app.PutDocumentsRequest; 27 import androidx.appsearch.app.RemoveByDocumentIdRequest; 28 import androidx.appsearch.app.ReportSystemUsageRequest; 29 import androidx.appsearch.app.ReportUsageRequest; 30 import androidx.core.util.Preconditions; 31 32 import org.jspecify.annotations.NonNull; 33 34 import java.util.List; 35 import java.util.Map; 36 37 /** 38 * Translates between Platform and Jetpack versions of requests. 39 * @exportToFramework:hide 40 */ 41 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 42 @RequiresApi(Build.VERSION_CODES.S) 43 public final class RequestToPlatformConverter { RequestToPlatformConverter()44 private RequestToPlatformConverter() {} 45 46 /** 47 * Translates a jetpack {@link PutDocumentsRequest} into a platform 48 * {@link android.app.appsearch.PutDocumentsRequest}. 49 */ toPlatformPutDocumentsRequest( @onNull PutDocumentsRequest jetpackRequest)50 public static android.app.appsearch.@NonNull PutDocumentsRequest toPlatformPutDocumentsRequest( 51 @NonNull PutDocumentsRequest jetpackRequest) { 52 Preconditions.checkNotNull(jetpackRequest); 53 android.app.appsearch.PutDocumentsRequest.Builder platformBuilder = 54 new android.app.appsearch.PutDocumentsRequest.Builder(); 55 // Convert normal generic documents. 56 for (GenericDocument jetpackDocument : jetpackRequest.getGenericDocuments()) { 57 platformBuilder.addGenericDocuments( 58 GenericDocumentToPlatformConverter.toPlatformGenericDocument(jetpackDocument)); 59 } 60 // Convert taken action generic documents. 61 for (GenericDocument jetpackTakenActionGenericDocument : 62 jetpackRequest.getTakenActionGenericDocuments()) { 63 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { 64 ApiHelperForV.addTakenActionGenericDocuments( 65 platformBuilder, 66 GenericDocumentToPlatformConverter.toPlatformGenericDocument( 67 jetpackTakenActionGenericDocument)); 68 } else { 69 // This version of platform-storage doesn't support the dedicated 70 // addTakenActionGenericDocuments API, but we can still add them to the index via 71 // the put API (just without logging). 72 platformBuilder.addGenericDocuments( 73 GenericDocumentToPlatformConverter.toPlatformGenericDocument( 74 jetpackTakenActionGenericDocument)); 75 } 76 } 77 return platformBuilder.build(); 78 } 79 80 /** 81 * Translates a jetpack {@link GetByDocumentIdRequest} into a platform 82 * {@link android.app.appsearch.GetByDocumentIdRequest}. 83 */ 84 public static android.app.appsearch.@NonNull GetByDocumentIdRequest toPlatformGetByDocumentIdRequest(@onNull GetByDocumentIdRequest jetpackRequest)85 toPlatformGetByDocumentIdRequest(@NonNull GetByDocumentIdRequest jetpackRequest) { 86 Preconditions.checkNotNull(jetpackRequest); 87 android.app.appsearch.GetByDocumentIdRequest.Builder platformBuilder = 88 new android.app.appsearch.GetByDocumentIdRequest.Builder( 89 jetpackRequest.getNamespace()) 90 .addIds(jetpackRequest.getIds()); 91 for (Map.Entry<String, List<String>> projection : 92 jetpackRequest.getProjections().entrySet()) { 93 platformBuilder.addProjection(projection.getKey(), projection.getValue()); 94 } 95 return platformBuilder.build(); 96 } 97 98 /** 99 * Translates a jetpack {@link RemoveByDocumentIdRequest} into a platform 100 * {@link android.app.appsearch.RemoveByDocumentIdRequest}. 101 */ 102 public static android.app.appsearch.@NonNull RemoveByDocumentIdRequest toPlatformRemoveByDocumentIdRequest( @onNull RemoveByDocumentIdRequest jetpackRequest)103 toPlatformRemoveByDocumentIdRequest( 104 @NonNull RemoveByDocumentIdRequest jetpackRequest) { 105 Preconditions.checkNotNull(jetpackRequest); 106 return new android.app.appsearch.RemoveByDocumentIdRequest.Builder( 107 jetpackRequest.getNamespace()) 108 .addIds(jetpackRequest.getIds()) 109 .build(); 110 } 111 112 /** 113 * Translates a jetpack {@link androidx.appsearch.app.ReportUsageRequest} into a platform 114 * {@link android.app.appsearch.ReportUsageRequest}. 115 */ toPlatformReportUsageRequest( @onNull ReportUsageRequest jetpackRequest)116 public static android.app.appsearch.@NonNull ReportUsageRequest toPlatformReportUsageRequest( 117 @NonNull ReportUsageRequest jetpackRequest) { 118 Preconditions.checkNotNull(jetpackRequest); 119 return new android.app.appsearch.ReportUsageRequest.Builder( 120 jetpackRequest.getNamespace(), jetpackRequest.getDocumentId()) 121 .setUsageTimestampMillis(jetpackRequest.getUsageTimestampMillis()) 122 .build(); 123 } 124 125 /** 126 * Translates a jetpack {@link androidx.appsearch.app.ReportSystemUsageRequest} into a platform 127 * {@link android.app.appsearch.ReportSystemUsageRequest}. 128 */ 129 public static android.app.appsearch.@NonNull ReportSystemUsageRequest toPlatformReportSystemUsageRequest(@onNull ReportSystemUsageRequest jetpackRequest)130 toPlatformReportSystemUsageRequest(@NonNull ReportSystemUsageRequest jetpackRequest) { 131 Preconditions.checkNotNull(jetpackRequest); 132 return new android.app.appsearch.ReportSystemUsageRequest.Builder( 133 jetpackRequest.getPackageName(), 134 jetpackRequest.getDatabaseName(), 135 jetpackRequest.getNamespace(), 136 jetpackRequest.getDocumentId()) 137 .setUsageTimestampMillis(jetpackRequest.getUsageTimestampMillis()) 138 .build(); 139 } 140 141 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 142 private static class ApiHelperForV { ApiHelperForV()143 private ApiHelperForV() {} 144 145 @DoNotInline addTakenActionGenericDocuments( android.app.appsearch.PutDocumentsRequest.Builder platformBuilder, android.app.appsearch.GenericDocument platformTakenActionGenericDocument)146 static void addTakenActionGenericDocuments( 147 android.app.appsearch.PutDocumentsRequest.Builder platformBuilder, 148 android.app.appsearch.GenericDocument platformTakenActionGenericDocument) { 149 try { 150 platformBuilder.addTakenActionGenericDocuments(platformTakenActionGenericDocument); 151 } catch (android.app.appsearch.exceptions.AppSearchException e) { 152 // This method incorrectly declares that it throws AppSearchException, whereas in 153 // fact there's nothing in its implementation that would do so. Suppress it here 154 // instead of piping all the way through the stack. 155 throw new RuntimeException( 156 "Unexpected AppSearchException which should not be possible", e); 157 } 158 } 159 } 160 } 161