blob: 3ecbef98c4f048852321670c13c569fbceefe8ed [file] [log] [blame]
/*
* Copyright 2011 Google Inc.
*
* 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.ipc.invalidation.ticl;
import com.google.ipc.invalidation.common.DigestFunction;
import com.google.ipc.invalidation.common.ObjectIdDigestUtils;
import com.google.ipc.invalidation.ticl.proto.ClientProtocol.ObjectIdP;
import com.google.ipc.invalidation.util.Bytes;
import com.google.ipc.invalidation.util.InternalBase;
import com.google.ipc.invalidation.util.TextBuilder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* Simple, map-based implementation of {@link DigestStore}.
*
*/
class SimpleRegistrationStore extends InternalBase implements DigestStore<ObjectIdP> {
/** All the registrations in the store mapped from the digest to the Object Id. */
private final SortedMap<Bytes, ObjectIdP> registrations = new TreeMap<Bytes, ObjectIdP>();
/** The function used to compute digests of objects. */
private final DigestFunction digestFunction;
/** The memoized digest of all objects in registrations. */
private Bytes digest;
SimpleRegistrationStore(DigestFunction digestFunction) {
this.digestFunction = digestFunction;
recomputeDigest();
}
@Override
public boolean add(ObjectIdP oid) {
if (registrations.put(ObjectIdDigestUtils.getDigest(oid.getSource(),
oid.getName().getByteArray(), digestFunction), oid) == null) {
recomputeDigest();
return true;
}
return false;
}
@Override
public Collection<ObjectIdP> add(Collection<ObjectIdP> oids) {
Collection<ObjectIdP> addedOids = new ArrayList<ObjectIdP>();
for (ObjectIdP oid : oids) {
if (registrations.put(ObjectIdDigestUtils.getDigest(oid.getSource(),
oid.getName().getByteArray(), digestFunction), oid) == null) {
// There was no previous value, so this is a new item.
addedOids.add(oid);
}
}
if (!addedOids.isEmpty()) {
// Only recompute the digest if we made changes.
recomputeDigest();
}
return addedOids;
}
@Override
public boolean remove(ObjectIdP oid) {
if (registrations.remove(ObjectIdDigestUtils.getDigest(oid.getSource(),
oid.getName().getByteArray(), digestFunction)) != null) {
recomputeDigest();
return true;
}
return false;
}
@Override
public Collection<ObjectIdP> remove(Collection<ObjectIdP> oids) {
Collection<ObjectIdP> removedOids = new ArrayList<ObjectIdP>();
for (ObjectIdP oid : oids) {
if (registrations.remove(ObjectIdDigestUtils.getDigest(oid.getSource(),
oid.getName().getByteArray(), digestFunction)) != null) {
removedOids.add(oid);
}
}
if (!removedOids.isEmpty()) {
// Only recompute the digest if we made changes.
recomputeDigest();
}
return removedOids;
}
@Override
public Collection<ObjectIdP> removeAll() {
Collection<ObjectIdP> result = new ArrayList<ObjectIdP>(registrations.values());
registrations.clear();
recomputeDigest();
return result;
}
@Override
public boolean contains(ObjectIdP oid) {
return registrations.containsKey(ObjectIdDigestUtils.getDigest(oid.getSource(),
oid.getName().getByteArray(), digestFunction));
}
@Override
public int size() {
return registrations.size();
}
@Override
public byte[] getDigest() {
return digest.getByteArray();
}
@Override
public Collection<ObjectIdP> getElements(byte[] oidDigestPrefix, int prefixLen) {
// We always return all the registrations and let the Ticl sort it out.
return registrations.values();
}
/** Recomputes the digests over all objects and sets {@code this.digest}. */
private void recomputeDigest() {
this.digest = ObjectIdDigestUtils.getDigest(registrations.keySet(), digestFunction);
}
@Override
public void toCompactString(TextBuilder builder) {
builder
.append("<SimpleRegistrationStore: registrations=")
.append(registrations.values())
.append(", digest=")
.append(digest)
.append(">");
}
}