/*
* Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
*
* 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.hazelcast.replicatedmap.impl.record;
import com.hazelcast.replicatedmap.impl.record.LazySet.IteratorFactory;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
class KeySetIteratorFactory<K, V> implements IteratorFactory<K, V, K> {
private final ReplicatedRecordStore recordStore;
KeySetIteratorFactory(ReplicatedRecordStore recordStore) {
this.recordStore = recordStore;
}
@Override
public Iterator<K> create(final Iterator<Map.Entry<K, ReplicatedRecord<K, V>>> iterator) {
return new KeySetIterator(iterator);
}
private final class KeySetIterator
implements Iterator<K> {
private final Iterator<Map.Entry<K, ReplicatedRecord<K, V>>> iterator;
private Map.Entry<K, ReplicatedRecord<K, V>> entry;
private KeySetIterator(Iterator<Map.Entry<K, ReplicatedRecord<K, V>>> iterator) {
this.iterator = iterator;
}
@Override
public boolean hasNext() {
while (iterator.hasNext()) {
entry = iterator.next();
if (testEntry(entry)) {
return true;
}
}
return false;
}
@Override
public K next() {
Map.Entry<K, ReplicatedRecord<K, V>> entry = this.entry;
Object key = entry != null ? entry.getKey() : null;
while (entry == null) {
entry = findNextEntry();
key = entry.getKey();
if (key != null) {
break;
}
}
this.entry = null;
if (key == null) {
throw new NoSuchElementException();
}
key = recordStore.unmarshall(key);
return (K) key;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Lazy structures are not modifiable");
}
private boolean testEntry(Map.Entry<K, ReplicatedRecord<K, V>> entry) {
return entry.getKey() != null && entry.getValue() != null && !entry.getValue().isTombstone();
}
private Map.Entry<K, ReplicatedRecord<K, V>> findNextEntry() {
Map.Entry<K, ReplicatedRecord<K, V>> entry = null;
while (iterator.hasNext()) {
entry = iterator.next();
if (testEntry(entry)) {
break;
}
entry = null;
}
if (entry == null) {
throw new NoSuchElementException();
}
return entry;
}
}
}