package com.apollographql.apollo.cache.normalized; import com.apollographql.apollo.ApolloClient; import com.apollographql.apollo.cache.CacheHeaders; import com.apollographql.apollo.cache.ApolloCacheHeaders; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import javax.annotation.Nonnull; import javax.annotation.Nullable; /** * A provider of {@link Record} for reading requests from cache. * * To serialize a {@link Record} to a standardized form use {@link #recordAdapter()} which handles * call custom scalar types registered on the {@link ApolloClient}. * * If a {@link NormalizedCache} cannot return all the records needed to read a response, it will * be considered a cache miss. * * A {@link NormalizedCache} is recommended to implement support for {@link CacheHeaders} specified in * {@link ApolloCacheHeaders}. * * A {@link NormalizedCache} can choose to store records in any manner. * * See {@link com.apollographql.apollo.cache.normalized.lru.LruNormalizedCache} for a in memory cache. */ public abstract class NormalizedCache { private RecordFieldAdapter recordFieldAdapter; /** * @param recordFieldAdapter An adapter which can deserialize and deserialize {@link Record} */ public NormalizedCache(RecordFieldAdapter recordFieldAdapter) { this.recordFieldAdapter = recordFieldAdapter; } protected RecordFieldAdapter recordAdapter() { return recordFieldAdapter; } /** * @param key The key of the record to read. * @param cacheHeaders The cache headers associated with the request which generated this record. * @return The {@link Record} for key. If not present return null. */ @Nullable public abstract Record loadRecord(@Nonnull String key, @Nonnull CacheHeaders cacheHeaders); /** * Calls through to {@link NormalizedCache#loadRecord(String, CacheHeaders)}. * Implementations should override this method if the underlying storage technology can offer an optimized manner * to read multiple records. * * @param keys The set of {@link Record} keys to read. * @param cacheHeaders The cache headers associated with the request which generated this record. */ @Nonnull public Collection<Record> loadRecords(@Nonnull Collection<String> keys, @Nonnull CacheHeaders cacheHeaders) { List<Record> records = new ArrayList<>(keys.size()); for (String key : keys) { final Record record = loadRecord(key, cacheHeaders); if (record != null) { records.add(record); } } return records; } /** * @param record The {@link Record} to merge. * @param cacheHeaders The {@link CacheHeaders} associated with the request which generated this record. * @return A set of record field keys that have changed. This set is returned by {@link Record#mergeWith(Record)}. */ @Nonnull public abstract Set<String> merge(@Nonnull Record record, @Nonnull CacheHeaders cacheHeaders); /** * Calls through to {@link NormalizedCache#merge(Record, CacheHeaders)}. Implementations should override this * method if the * underlying storage technology can offer an optimized manner to store multiple records. * * @param recordSet The set of Records to merge. * @param cacheHeaders The {@link CacheHeaders} associated with the request which generated this record. * @return A set of record field keys that have changed. This set is returned by {@link Record#mergeWith(Record)}. */ @Nonnull public Set<String> merge(@Nonnull Collection<Record> recordSet, @Nonnull CacheHeaders cacheHeaders) { Set<String> aggregatedDependentKeys = new LinkedHashSet<>(); for (Record record : recordSet) { aggregatedDependentKeys.addAll(merge(record, cacheHeaders)); } return aggregatedDependentKeys; } /** * Clears all records from the cache. * * Clients should call {@link ApolloClient#clearNormalizedCache()} for a thread-safe access to * this method. */ public abstract void clearAll(); }