/*
* Copyright 2013 Esri.
*
* 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.esri.gpt.framework.dcat;
import com.esri.gpt.framework.dcat.DcatParser.ListenerInternal;
import com.esri.gpt.framework.dcat.dcat.DcatRecord;
import com.esri.gpt.framework.util.ReadOnlyIterator;
import java.io.IOException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* DCAT parser adaptor.
* <p>
* It allows to wrap {@link DcatParser} parser so instead having 'event paradigm'
* based mechanism, an 'iterator paradigm' could be used.
* </p>
*/
public class DcatParserAdaptor implements Iterable<DcatRecord> {
private static final Logger LOGGER = Logger.getLogger(DcatParserAdaptor.class.getCanonicalName());
private DcatParser parser;
/**
* Creates instance of the adaptor.
* @param parser parser
*/
public DcatParserAdaptor(DcatParser parser) {
this.parser = parser;
}
/**
* Closes adaptor.
* <p>
* It also closes underlying parser. This method is called either by the user
* of the adaptor or it will be called automatically if iteration reaches the
* end. Subsequential calls to the method will not case any adverse effects.
* </p>
*/
public void close() {
if (parser!=null) {
try {
parser.close();
} catch (IOException ex) {
Logger.getLogger(DcatParserAdaptor.class.getName()).log(Level.SEVERE, null, ex);
}
parser = null;
}
}
/**
* Called upon parsing exception thrown during iteration.
* @param ex
*/
protected void onException(Exception ex) {
// TODO: override if needed
LOGGER.log(Level.SEVERE, "Error parsing DCAT response.", ex);
}
@Override
public Iterator<DcatRecord> iterator() {
return new DcatIterator();
}
/**
* DCAT iterator.
*/
private class DcatIterator extends ReadOnlyIterator<DcatRecord> {
private DcatRecord nextRecord;
private boolean firstTime = true;
@Override
public boolean hasNext() {
// no parser? no records
if (parser==null) {
return false;
}
// next records still cached? it's still available
if (nextRecord!=null) {
return true;
}
// create listener
ListenerInternal listener = new ListenerInternal() {
@Override
public boolean onRecord(DcatRecord record) {
LOGGER.log(Level.FINEST, record!=null? record.toString(): "<empty record>");
nextRecord = record;
// always stop parser
return false;
}
};
try {
// if this is first time parsing, start from the beginning; it will stop
// after first record anyway
if (firstTime) {
firstTime = false;
parser.parse(listener);
} else {
// if this is not a first time, just suspend parsing
parser.parseRecords(listener);
}
// check if next records present
boolean hasNext = nextRecord!=null;
if (!hasNext) {
// if not close adaptor
close();
}
return hasNext;
} catch (IOException ex) {
close();
onException(ex);
return false;
} catch (DcatParseException ex) {
close();
onException(ex);
return false;
}
}
@Override
public DcatRecord next() {
if (nextRecord==null) {
throw new NoSuchElementException();
}
DcatRecord next = nextRecord;
// clear cached record (nextRecord)
nextRecord = null;
return next;
}
}
}