package com.revolsys.swing.field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.ListModel;
import javax.swing.event.EventListenerList;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import com.revolsys.io.Reader;
import com.revolsys.record.Record;
import com.revolsys.record.query.BinaryCondition;
import com.revolsys.record.query.Condition;
import com.revolsys.record.query.Q;
import com.revolsys.record.query.Query;
import com.revolsys.record.schema.RecordStore;
import com.revolsys.util.Property;
public class RecordStoreQueryListModel implements ListModel {
private final String displayFieldName;
protected EventListenerList listDataListeners = new EventListenerList();
private int maxResults = Integer.MAX_VALUE;
private List<Record> records = new ArrayList<>();
private final List<Query> queries = new ArrayList<>();
private final RecordStore recordStore;
private String searchText = "";
private Record selectedItem;
public RecordStoreQueryListModel(final RecordStore recordStore, final String displayFieldName,
final List<Query> queries) {
this.recordStore = recordStore;
this.queries.addAll(queries);
this.displayFieldName = displayFieldName;
}
public RecordStoreQueryListModel(final RecordStore recordStore, final String displayFieldName,
final Query... queries) {
this(recordStore, displayFieldName, Arrays.asList(queries));
}
@Override
public void addListDataListener(final ListDataListener l) {
this.listDataListeners.add(ListDataListener.class, l);
}
protected void fireContentsChanged(final Object source, final int index0, final int index1) {
final Object[] listeners = this.listDataListeners.getListenerList();
ListDataEvent e = null;
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ListDataListener.class) {
if (e == null) {
e = new ListDataEvent(source, ListDataEvent.CONTENTS_CHANGED, index0, index1);
}
((ListDataListener)listeners[i + 1]).contentsChanged(e);
}
}
}
public String getDisplayFieldName() {
return this.displayFieldName;
}
@Override
public Record getElementAt(final int index) {
return this.records.get(index);
}
public ListDataListener[] getListDataListeners() {
return this.listDataListeners.getListeners(ListDataListener.class);
}
public List<Record> getRecords() {
return this.records;
}
protected List<Record> getRecords(final String searchParam) {
if (Property.hasValue(searchParam) && searchParam.length() >= 2) {
final Map<String, Record> allObjects = new TreeMap<>();
for (Query query : this.queries) {
if (allObjects.size() < this.maxResults) {
query = query.clone();
query.addOrderBy(this.displayFieldName, true);
final Condition whereCondition = query.getWhereCondition();
if (whereCondition instanceof BinaryCondition) {
final BinaryCondition binaryCondition = (BinaryCondition)whereCondition;
if (binaryCondition.getOperator().equalsIgnoreCase("like")) {
final String likeString = "%"
+ searchParam.toUpperCase().replaceAll("[^A-Z0-9 ]", "%") + "%";
Q.setValue(0, binaryCondition, likeString);
} else {
Q.setValue(0, binaryCondition, searchParam);
}
}
query.setLimit(this.maxResults);
final Reader<Record> reader = this.recordStore.getRecords(query);
try {
final List<Record> objects = reader.toList();
for (final Record object : objects) {
if (allObjects.size() < this.maxResults) {
final String key = object.getString(this.displayFieldName);
if (!allObjects.containsKey(key)) {
if (searchParam.equals(key)) {
this.selectedItem = object;
}
allObjects.put(key, object);
}
}
}
} finally {
reader.close();
}
}
}
return new ArrayList<>(allObjects.values());
} else {
return Collections.emptyList();
}
}
public String getSearchText() {
return this.searchText;
}
public Record getSelectedItem() {
return this.selectedItem;
}
@Override
public int getSize() {
return this.records.size();
}
@Override
public void removeListDataListener(final ListDataListener l) {
this.listDataListeners.remove(ListDataListener.class, l);
}
public void setMaxResults(final int maxResults) {
this.maxResults = maxResults;
}
public void setSearchText(final String searchText) {
if (Property.hasValue(searchText)) {
if (!this.searchText.equals(searchText)) {
this.searchText = searchText;
this.records = getRecords(this.searchText);
fireContentsChanged(this, 0, this.records.size());
}
} else {
this.searchText = "";
this.records = Collections.emptyList();
fireContentsChanged(this, 0, this.records.size());
this.selectedItem = null;
}
}
}