/*******************************************************************************
* Copyright 2013 Geoscience Australia
*
* 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 au.gov.ga.earthsci.discovery.darwin;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
import au.gov.ga.earthsci.core.retrieve.IRetrieval;
import au.gov.ga.earthsci.core.retrieve.IRetrievalListener;
import au.gov.ga.earthsci.core.retrieve.RetrievalAdapter;
import au.gov.ga.earthsci.core.retrieve.RetrievalServiceFactory;
import au.gov.ga.earthsci.core.retrieve.retriever.HttpRetrievalProperties;
import au.gov.ga.earthsci.discovery.AbstractDiscovery;
import au.gov.ga.earthsci.discovery.DiscoveryIndexOutOfBoundsException;
import au.gov.ga.earthsci.discovery.DiscoveryResultNotFoundException;
import au.gov.ga.earthsci.discovery.IDiscovery;
import au.gov.ga.earthsci.discovery.IDiscoveryParameters;
import au.gov.ga.earthsci.discovery.IDiscoveryResultLabelProvider;
/**
* {@link IDiscovery} implementation for DARWIN.
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
public class DarwinDiscovery extends AbstractDiscovery<DarwinDiscoveryService, IDiscoveryParameters>
{
private final DarwinDiscoveryResultLabelProvider labelProvider = new DarwinDiscoveryResultLabelProvider();
private final Map<Integer, DarwinDiscoveryResult> results = new HashMap<Integer, DarwinDiscoveryResult>();
private final Map<IRetrieval, String> retrievals = new HashMap<IRetrieval, String>();
private final Map<IRetrieval, Integer> retrievalStarts = new HashMap<IRetrieval, Integer>();
private final Set<String> retrievalIds = new HashSet<String>();
public DarwinDiscovery(DarwinDiscoveryService service, IDiscoveryParameters parameters)
{
super(service, parameters);
}
@Override
public IDiscoveryResultLabelProvider getLabelProvider()
{
return labelProvider;
}
@Override
public void start()
{
retrieve(0, 0);
}
@Override
public void cancel()
{
synchronized (retrievals)
{
for (IRetrieval retrieval : retrievals.keySet())
{
retrieval.cancel();
}
retrievals.clear();
retrievalIds.clear();
retrievalStarts.clear();
}
}
@Override
public DarwinDiscoveryResult getResult(int index) throws DiscoveryResultNotFoundException,
DiscoveryIndexOutOfBoundsException
{
synchronized (retrievals)
{
if (index < 0 || (resultCount != null && index >= resultCount))
{
throw new DiscoveryIndexOutOfBoundsException();
}
if (results.containsKey(index))
{
return results.get(index);
}
int pageSize = getPageSize();
int start = (index / pageSize) * pageSize;
retrieve(start, pageSize);
return null;
}
}
@Override
public boolean supportsCustomPageSize()
{
return true;
}
protected void retrieve(int start, int length)
{
synchronized (retrievals)
{
String id = start + "_" + length; //$NON-NLS-1$
if (retrievalIds.contains(id))
{
//already retrieving this range
return;
}
HttpRetrievalProperties retrievalProperties = new HttpRetrievalProperties();
retrievalProperties.setRequestMethod("POST"); //$NON-NLS-1$
retrievalProperties.setUseCache(false);
retrievalProperties.setContentType("application/json"); //$NON-NLS-1$
JSONObject jsonObject = new JSONObject();
jsonObject.put("searchTerm", parameters.getQuery()); //$NON-NLS-1$
jsonObject.put("startPosition", start); //$NON-NLS-1$
jsonObject.put("count", length); //$NON-NLS-1$
String json = jsonObject.toString();
try
{
byte[] payload = json.getBytes("UTF-8"); //$NON-NLS-1$
retrievalProperties.setRequestPayload(payload);
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
IRetrieval retrieval =
RetrievalServiceFactory.getServiceInstance().retrieve(this, service.getServiceURL(),
retrievalProperties, true);
retrievalIds.add(id);
retrievals.put(retrieval, id);
retrievalStarts.put(retrieval, start);
retrieval.addListener(retrievalListener);
retrieval.start();
loading = true;
}
}
private IRetrievalListener retrievalListener = new RetrievalAdapter()
{
@Override
public void complete(IRetrieval retrieval)
{
synchronized (retrievals)
{
String id = retrievals.remove(retrieval);
if (id == null)
{
return;
}
retrievalIds.remove(id);
int startIndex = retrievalStarts.remove(retrieval);
loading = !retrievals.isEmpty();
if (retrieval.getResult().isSuccessful())
{
InputStream is = null;
try
{
is = retrieval.getData().getInputStream();
JSONTokener tokener = new JSONTokener(is);
JSONObject json = new JSONObject(tokener);
int totalResultCount = json.getInt("numberOfRecordsMatched"); //$NON-NLS-1$
int numberOfRecordsReturned = json.getInt("numberOfRecordsReturned"); //$NON-NLS-1$
if (resultCount == null || resultCount != totalResultCount)
{
resultCount = totalResultCount;
listeners.resultCountChanged(DarwinDiscovery.this);
}
if (numberOfRecordsReturned > 0)
{
JSONArray results = json.optJSONArray("searchResults"); //$NON-NLS-1$
if (results == null)
{
throw new Exception("JSON response doesn't contain searchResults array"); //$NON-NLS-1$
}
else if (results.length() != numberOfRecordsReturned)
{
throw new Exception(
"Number of record elements in the JSON response doesn't match the number of records attribute"); //$NON-NLS-1$
}
for (int i = 0; i < numberOfRecordsReturned; i++)
{
JSONObject resultJson = results.getJSONObject(i);
int index = startIndex + i;
DarwinDiscoveryResult result =
new DarwinDiscoveryResult(DarwinDiscovery.this, index, resultJson);
DarwinDiscovery.this.results.put(index, result);
listeners.resultAdded(DarwinDiscovery.this, result);
}
}
}
catch (Exception e)
{
error = e;
e.printStackTrace();
}
finally
{
if (is != null)
{
try
{
is.close();
}
catch (IOException e)
{
}
}
}
}
else if (error == null)
{
error = retrieval.getResult().getError();
}
}
}
};
}