package com.revolsys.record.io.format.mapguide;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.xml.namespace.QName;
import com.revolsys.collection.iterator.AbstractIterator;
import com.revolsys.geometry.model.GeometryFactory;
import com.revolsys.io.FileUtil;
import com.revolsys.logging.Logs;
import com.revolsys.record.Record;
import com.revolsys.record.RecordFactory;
import com.revolsys.record.RecordState;
import com.revolsys.record.io.RecordReader;
import com.revolsys.record.io.format.xml.StaxReader;
import com.revolsys.record.schema.RecordDefinition;
import com.revolsys.spring.resource.Resource;
public class MapGuideServerFeatureIterator extends AbstractIterator<Record>
implements RecordReader {
private static final String FEATURE = "Feature";
private static final String PROPERTY = "Property";
private static final QName NAME = new QName("Name");
private static final QName VALUE = new QName("Value");
private StaxReader reader;
private boolean closed;
private RecordDefinition recordDefinition;
private RecordFactory<?> recordFacory;
private GeometryFactory geometryFactory;
private int totalRecordCount = 0;
private int currentRecordCount = 0;
private Map<String, Object> queryParameters;
private final int queryOffset;
private final int queryLimit;
private int serverLimit;
private final boolean supportsPaging;
private final FeatureLayer layer;
private final String geometryFieldName;
public MapGuideServerFeatureIterator(final FeatureLayer layer,
final Map<String, Object> queryParameters, final int offset, final int limit,
final RecordFactory<?> recordFactory) {
this.layer = layer;
this.queryParameters = queryParameters;
this.queryOffset = offset;
this.queryLimit = limit;
this.serverLimit = layer.getMaxRecordCount();
if (this.queryLimit < this.serverLimit) {
this.serverLimit = this.queryLimit;
}
this.recordDefinition = layer.getRecordDefinition();
this.recordFacory = recordFactory;
this.geometryFactory = this.recordDefinition.getGeometryFactory();
this.geometryFieldName = this.recordDefinition.getGeometryFieldName();
this.supportsPaging = false;
}
@Override
protected void closeDo() {
FileUtil.closeSilent(this.reader);
this.reader = null;
this.geometryFactory = null;
this.queryParameters = null;
this.recordDefinition = null;
this.recordFacory = null;
}
@Override
protected void finalize() throws Throwable {
close();
}
@Override
protected Record getNext() throws NoSuchElementException {
if (this.closed) {
throw new NoSuchElementException();
} else {
if (this.totalRecordCount < this.queryLimit) {
StaxReader parser = this.reader;
if (parser == null) {
parser = newParser();
}
if (!parser.skipToStartElement(FEATURE)) {
if (this.supportsPaging && this.currentRecordCount == this.serverLimit) {
parser = newParser();
}
if (!parser.skipToStartElement(FEATURE)) {
throw new NoSuchElementException();
}
}
} else {
throw new NoSuchElementException();
}
if (!this.closed) {
try {
final Record record = this.recordFacory.newRecord(this.recordDefinition);
record.setState(RecordState.INITIALIZING);
final int featureDepth = this.reader.getDepth();
while (this.reader.skipToStartElement(featureDepth, PROPERTY)) {
final int propertyDepth = this.reader.getDepth();
String name = null;
Object value = null;
while (this.reader.skipToStartElements(propertyDepth, NAME, VALUE)) {
if (this.reader.isStartElementLocalName(NAME)) {
name = this.reader.getElementText();
} else if (this.reader.isStartElementLocalName(VALUE)) {
value = this.reader.getElementText();
}
}
if (value != null && name.equals(this.geometryFieldName)) {
value = this.geometryFactory.geometry(value.toString());
}
record.setValue(name, value);
}
record.setState(RecordState.PERSISTED);
this.currentRecordCount++;
this.totalRecordCount++;
return record;
} catch (final Throwable e) {
if (!this.closed) {
Logs.debug(this,
"Error reading: " + this.layer.getResource(this.queryParameters).getUriString(), e);
}
close();
}
}
}
throw new NoSuchElementException();
}
@Override
public RecordDefinition getRecordDefinition() {
return this.recordDefinition;
}
protected StaxReader newParser() {
if (this.closed) {
throw new NoSuchElementException();
} else {
this.currentRecordCount = 0;
if (this.supportsPaging) {
this.queryParameters.put("resultOffset", this.queryOffset + this.totalRecordCount);
if (this.serverLimit > 0) {
this.queryParameters.put("resultRecordCount", this.serverLimit);
}
}
final Resource resource = this.layer.getResource(this.queryParameters);
this.reader = StaxReader.newXmlReader(resource);
if (!this.reader.skipToStartElement("Features")) {
throw new NoSuchElementException();
}
return this.reader;
}
}
}