package org.sigmah.client.ui.presenter.contact.dashboardlist;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* 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/gpl-3.0.html>.
* #L%
*/
import java.util.ArrayList;
import java.util.List;
import com.allen_sauer.gwt.log.client.Log;
import com.extjs.gxt.ui.client.widget.Component;
import org.sigmah.client.dispatch.CommandResultHandler;
import org.sigmah.client.dispatch.DispatchAsync;
import org.sigmah.client.dispatch.monitor.LoadingMask;
import org.sigmah.client.dispatch.monitor.ProgressMask;
import org.sigmah.client.i18n.I18N;
import org.sigmah.client.ui.view.contact.dashboardlist.DashboardContact;
import org.sigmah.shared.command.GetContactHistory;
import org.sigmah.shared.command.GetContacts;
import org.sigmah.shared.command.result.ContactHistory;
import org.sigmah.shared.command.result.ListResult;
import org.sigmah.shared.dto.ContactDTO;
/**
* Represents a worker which get contacts chunk by chunk.
*/
final class GetContactsWorker {
/**
* Receives the worker events.
*/
public static interface WorkerListener {
/**
* Method called if a server error occurs.
*
* @param error
* The error.
*/
void serverError(Throwable error);
/**
* Method called when a chunk is retrieved.
*
* @param contact
* The chunk.
*/
void chunkRetrieved(DashboardContact contact);
/**
* Method called after the last chunk has been retrieved.
*/
void ended();
}
/**
* The dispatcher.
*/
private final DispatchAsync dispatch;
/**
* The {@link GetContacts} command to execute.
*/
private final GetContacts cmd;
/**
* The component to mask while the worker runs.
*/
private final Component component;
/**
* Listeners.
*/
private final ArrayList<WorkerListener> listeners;
/**
* The list of contacts to retrieve.
*/
private List<ContactDTO> contactsList;
/**
* The number of contacts to retrieve.
*/
private int contactsSize;
/**
* The async monitor.
*/
private ProgressMask monitor;
/**
* Builds a new worker.
*
* @param dispatch
* The dispatcher.
* @param cmd
* The {@link GetContacts} command to execute.
* @param component
* The component to mask while the worker runs.
*/
public GetContactsWorker(final DispatchAsync dispatch, final GetContacts cmd, final Component component) {
assert dispatch != null;
assert cmd != null;
assert component != null;
this.dispatch = dispatch;
this.cmd = cmd;
this.component = component;
this.listeners = new ArrayList<WorkerListener>();
}
/**
* Adds a listener to this worker.
*
* @param listener
* The new listener.
*/
public void addWorkerListener(final WorkerListener listener) {
this.listeners.add(listener);
}
/**
* Runs the worker.
*/
public void run() {
monitor = new ProgressMask(component, I18N.CONSTANTS.refreshContactListContactLoaded());
// First call to get the list of contacts.
dispatch.execute(cmd, new CommandResultHandler<ListResult<ContactDTO>>() {
@Override
public void onCommandFailure(final Throwable e) {
if (Log.isErrorEnabled()) {
Log.error("[GetContacts command] Error while getting contacts.", e);
}
monitor.initCounter(0);
fireServerError(e);
}
@Override
public void onCommandSuccess(final ListResult<ContactDTO> result) {
// Retrieves contacts by chunks.
if (!result.isEmpty()) {
contactsList = result.getList();
contactsSize = contactsList.size();
monitor.initCounter(contactsSize);
chunk();
} else {
monitor.initCounter(0);
}
}
}, new LoadingMask(component));
}
private void chunk() {
// No more contact to get.
if (contactsList.isEmpty()) {
fireEnded();
return;
}
// Store the next ids to retrieve.
final ContactDTO nextContact = contactsList.remove(0);
// Retrieves these contacts.
dispatch.execute(new GetContactHistory(nextContact.getId()), new CommandResultHandler<ListResult<ContactHistory>>() {
@Override
public void onCommandFailure(final Throwable e) {
if (Log.isErrorEnabled()) {
Log.error("[GetContactHistory command] Error while getting contact history.", e);
}
monitor.increment(contactsSize);
fireServerError(e);
}
@Override
public void onCommandSuccess(final ListResult<ContactHistory> result) {
// Updates the monitor.
monitor.increment(1);
// Fires event.
ContactHistory lastChange = result.isEmpty() ? new ContactHistory() : result.getList().get(0);
DashboardContact contact = new DashboardContact(nextContact, lastChange);
fireChunkRetrieved(contact);
// Next chunk.
chunk();
}
}, monitor);
}
/**
* Method called if a server error occurs.
*
* @param error
* The error.
*/
protected void fireServerError(final Throwable error) {
for (final WorkerListener listener : listeners) {
listener.serverError(error);
}
}
/**
* Method called when a chunk is retrieved.
*
* @param contact
* The chunk.
*/
protected void fireChunkRetrieved(final DashboardContact contact) {
for (final WorkerListener listener : listeners) {
listener.chunkRetrieved(contact);
}
}
/**
* Method called after the last chunk has been retrieved.
*/
protected void fireEnded() {
for (final WorkerListener listener : listeners) {
listener.ended();
}
}
}