blob: 57ba920c926bff65fc629b72d0eb9e2d3c24e5af [file] [log] [blame]
// Copyright 2018 The Feed Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.android.libraries.feed.api.host.storage;
import com.google.android.libraries.feed.api.host.storage.ContentOperation.Delete;
import com.google.android.libraries.feed.api.host.storage.ContentOperation.DeleteAll;
import com.google.android.libraries.feed.api.host.storage.ContentOperation.DeleteByPrefix;
import com.google.android.libraries.feed.api.host.storage.ContentOperation.Upsert;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A sequence of {@link ContentOperation} instances. This class is used to commit changes to {@link
* ContentStorage}.
*/
public final class ContentMutation {
private final List<ContentOperation> operations;
private ContentMutation(List<ContentOperation> operations) {
this.operations = Collections.unmodifiableList(operations);
}
/** An unmodifiable list of operations to be committed by {@link ContentStorage}. */
public List<ContentOperation> getOperations() {
return operations;
}
/**
* Creates a {@link ContentMutation}, which can be used to apply mutations to the underlying
* {@link ContentStorage}.
*/
public static final class Builder {
private final ArrayList<ContentOperation> operations = new ArrayList<>();
private final ContentOperationListSimplifier simplifier = new ContentOperationListSimplifier();
/**
* Sets the key/value pair in {@link ContentStorage}, or inserts it if it doesn't exist.
*
* <p>This method can be called repeatedly to assign multiple key/values. If the same key is
* assigned multiple times, only the last value will be persisted.
*/
public Builder upsert(String key, byte[] value) {
operations.add(new Upsert(key, value));
return this;
}
/**
* Deletes the value from {@link ContentStorage} with a matching key, if it exists.
*
* <p>{@link ContentStorage#commit(ContentMutation)} will fulfill with result is {@code TRUE},
* even if {@code key} is not found in {@link ContentStorage}.
*
* <p>If {@link Delete} and {@link Upsert} are committed for the same key, only the last
* operation will take effect.
*/
public Builder delete(String key) {
operations.add(new Delete(key));
return this;
}
/**
* Deletes all values from {@link ContentStorage} with matching key prefixes.
*
* <p>{@link ContentStorage#commit(ContentMutation)} will fulfill with result equal to {@code
* TRUE}, even if no keys have a matching prefix.
*
* <p>If {@link DeleteByPrefix} and {@link Upsert} are committed for the same matching key, only
* the last operation will take effect.
*/
public Builder deleteByPrefix(String prefix) {
operations.add(new DeleteByPrefix(prefix));
return this;
}
/** Deletes all values from {@link ContentStorage}. */
public Builder deleteAll() {
operations.add(new DeleteAll());
return this;
}
/**
* Simplifies the sequence of {@link ContentOperation} instances, and returns a new {@link
* ContentMutation} the simplified list.
*/
public ContentMutation build() {
return new ContentMutation(simplifier.simplify(operations));
}
}
@Override
public boolean equals(/*@Nullable*/ Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ContentMutation that = (ContentMutation) o;
return operations != null ? operations.equals(that.operations) : that.operations == null;
}
@Override
public int hashCode() {
return operations != null ? operations.hashCode() : 0;
}
}