001/*
002 *  Copyright 2016 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.cms.search.solr;
017
018import java.util.Iterator;
019import java.util.NoSuchElementException;
020
021import org.apache.solr.common.SolrDocument;
022import org.slf4j.Logger;
023
024import org.ametys.cms.content.indexing.solr.SolrFieldNames;
025import org.ametys.cms.search.SearchResultsIterator;
026import org.ametys.plugins.repository.AmetysObjectResolver;
027
028/**
029 * This abstract iterator is here for providing common code to an iterator over
030 * SearchResult and to an AmetysObjectIterator
031 * @param <O> the type of elements returned by this iterator
032 */
033abstract class AbstractResponseIterator<O> implements SearchResultsIterator<O>
034{
035    protected AmetysObjectResolver _ametysObjectResolver;
036    private Iterator<SolrDocument> _it;
037    private O _nextObject;
038    private int _position;
039    private long _size;
040    private long _errors;
041    private Logger _logger;
042    
043    public AbstractResponseIterator(Iterator<SolrDocument> it, long size, AmetysObjectResolver resolver, Logger logger)
044    {
045        _it = it;
046        _size = size;
047        _errors = 0;
048        _ametysObjectResolver = resolver;
049        _logger = logger;
050    }
051    
052    @Override
053    public boolean hasNext()
054    {
055        // Prefetch the next object
056        if (_nextObject == null)
057        {
058            while (_it.hasNext())
059            {
060                SolrDocument document = _it.next();
061                String id = (String) document.getFieldValue(SolrFieldNames.ID);
062                
063                if (_ametysObjectResolver.hasAmetysObjectForId(id))
064                {
065                    _nextObject = _setNextObject(document, id);
066                    return true;
067                }
068                else
069                {
070                    // Go to next element
071                    _errors++;
072                    _logger.warn("The Solr indexed Ametys object with id '{}' does not exist. Either autoCommit did not execute yet or a full reindexation is required.", id);
073                }
074            }
075            return false;
076        }
077        return true;
078    }
079    
080    protected abstract O _setNextObject(SolrDocument document, String id);
081    
082    @Override
083    public O next()
084    {
085        if (!hasNext())
086        {
087            throw new NoSuchElementException();
088        }
089        
090        try
091        {
092            _position++;
093            return _nextObject;
094        }
095        finally
096        {
097            _nextObject = null;
098        }
099    }
100    
101    public long getPosition()
102    {
103        return _position;
104    }
105    
106    public long getSize()
107    {
108        return _size - _errors;
109    }
110    
111    @Override
112    public void skip(long skipNum)
113    {
114        if (skipNum <= 0)
115        {
116            return;
117        }
118        
119        long size = getSize();
120        if (size != -1 && skipNum > size - getPosition())
121        {
122            throw new NoSuchElementException();
123        }
124        
125        for (long i = skipNum; i > 0; i--)
126        {
127            next();
128        }
129    }
130}