/*
* WBI Indicator Explorer
*
* Copyright 2015 Sebastian Nogara <snogaraleal@gmail.com>
*
* This file is part of WBI.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.managers.models;
import java.util.ArrayList;
import java.util.List;
import rpc.client.ClientRequest;
import models.Indicator;
import client.managers.Manager;
import client.managers.models.watcher.IndicatorWatcher;
import client.services.WBIExplorationService;
import client.services.WBIManagementService;
/**
* {@link Manager} in charge of the current {@link Indicator} selection.
*
* @see Manager
*/
public class IndicatorManager implements Manager {
/**
* Interface for views that interact with an {@link IndicatorManager}.
*/
public static interface View extends Manager.View<IndicatorManager> {}
/**
* Interface for {@link IndicatorManager} listeners.
*/
public static interface Listener {
/**
* Handle search results.
*
* @param indicators Search results.
* @param selectedIndicator Currently selected indicator.
*/
void onSearch(
List<Indicator> indicators,
Indicator selectedIndicator);
/**
* Handle change in {@link Indicator}.
*
* @param indicator Indicator that changed.
*/
void onChange(Indicator indicator);
/**
* Handle change of {@link Indicator}.
*
* @param indicator Indicator that was just selected.
*/
void onSelect(Indicator indicator);
}
/**
* {@code Listener} objects listening to changes in this manager.
*/
private List<Listener> listeners = new ArrayList<Listener>();
/**
* {@code ClientRequest.Listener} for search requests.
*/
private ClientRequest.Listener<List<Indicator>> searchRequestListener;
/**
* {@code ClientRequest.Listener} for {@code Indicator} load requests.
*/
private ClientRequest.Listener<Indicator> loadRequestListener;
/**
* {@code ClientRequest.Listener} for {@code Indicator} unload requests.
*/
private ClientRequest.Listener<Indicator> unloadRequestListener;
/**
* Last search query.
*/
private String lastQuery;
/**
* Last search {@code ClientRequest}.
*/
private ClientRequest<List<Indicator>> lastSearchRequest;
/**
* Last search results.
*/
private List<Indicator> lastSearchIndicators;
/**
* Currently selected {@code Indicator}.
*/
private Indicator selectedIndicator;
/**
* {@code IndicatorWatcher} providing real-time changes in
* {@code Indicator} objects.
*/
private IndicatorWatcher watcher;
/**
* Initialize {@code IndicatorManager}.
*/
public IndicatorManager() {
selectedIndicator = null;
/*
* Create {@code IndicatorWatcher}.
*/
watcher = IndicatorWatcher.create();
watcher.addListener(new IndicatorWatcher.Listener() {
@Override
public void onChange(Indicator indicator) {
change(indicator);
if (selectedIndicator.equals(indicator)) {
if (!selectedIndicator.isReady() && indicator.isReady()) {
selectedIndicator = indicator;
for (Listener listener : listeners) {
listener.onSelect(indicator);
}
}
}
}
});
watcher.start();
/*
* Initialize {@code ClientRequest.Listener} for search.
*/
searchRequestListener = new ClientRequest.Listener<List<Indicator>>() {
@Override
public void onSuccess(List<Indicator> list) {
lastSearchIndicators = list;
for (Listener listener : listeners) {
listener.onSearch(list, selectedIndicator);
}
}
@Override
public void onFailure(ClientRequest.Error error) {
}
};
/*
* Initialize {@code ClientRequest.Listener} for
* {@code Indicator} loading.
*/
loadRequestListener = new ClientRequest.Listener<Indicator>() {
@Override
public void onSuccess(Indicator indicator) {
change(indicator);
watcher.watchUntilStatusEquals(
indicator, Indicator.Status.READY);
}
@Override
public void onFailure(ClientRequest.Error error) {
}
};
/*
* Initialize {@code ClientRequest.Listener} for
* {@code Indicator} unloading.
*/
unloadRequestListener = new ClientRequest.Listener<Indicator>() {
@Override
public void onSuccess(Indicator indicator) {
change(indicator);
watcher.watchUntilStatusEquals(
indicator, Indicator.Status.AVAILABLE);
}
@Override
public void onFailure(ClientRequest.Error error) {
}
};
}
/**
* Get the currently selected {@code Indicator}.
*
* @return Selected indicator.
*/
public Indicator getSelectedIndicator() {
return selectedIndicator;
}
/**
* Attach {@code Listener}.
*
* @param listener Listener to attach.
*/
public void addListener(Listener listener) {
if (lastSearchIndicators != null) {
listener.onSearch(lastSearchIndicators, selectedIndicator);
}
listeners.add(listener);
}
/**
* Detach {@code Listener}.
*
* @param listener Listener to detach.
*/
public void removeListener(Listener listener) {
listeners.remove(listener);
}
/**
* Clear the current search.
*/
public void clearSearch() {
lastQuery = null;
}
/**
* Perform search.
*
* @param query Search terms.
*/
public void search(String query) {
if (query.equals(lastQuery)) {
return;
}
if (lastSearchRequest != null) {
lastSearchRequest.cancel();
}
lastQuery = query;
// Make RPC request
lastSearchRequest = WBIExplorationService.queryIndicatorList(
query, searchRequestListener);
}
/**
* Exhibit changes in an {@code Indicator}.
*
* @param indicator Indicator changed.
*/
private void change(Indicator indicator) {
for (Listener listener : listeners) {
listener.onChange(indicator);
}
}
/**
* Request an {@code Indicator} to be loaded.
*
* @param indicator {@code Indicator} to load.
*/
public void load(Indicator indicator) {
indicator.setStatus(Indicator.Status.LOADING);
change(indicator);
// Make RPC request
WBIManagementService.load(indicator.getId(), loadRequestListener);
}
/**
* Request an {@code Indicator} to be unloaded.
*
* @param indicator {@code Indicator} to unload.
*/
public void unload(Indicator indicator) {
indicator.setStatus(Indicator.Status.LOADING);
change(indicator);
// Make RPC request
WBIManagementService.unload(indicator.getId(), unloadRequestListener);
}
/**
* Select an {@code Indicator}.
*
* @param indicator Indicator to select.
*/
public void select(Indicator indicator) {
if (indicator.equals(selectedIndicator)) {
return;
}
this.selectedIndicator = indicator;
if (indicator.isReady()) {
for (Listener listener : listeners) {
listener.onSelect(indicator);
}
} else {
load(indicator);
}
}
}