package org.activityinfo.ui.client.page.entry;
/*
* #%L
* ActivityInfo Server
* %%
* Copyright (C) 2009 - 2013 UNICEF
* %%
* 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 com.extjs.gxt.ui.client.Style.SortDir;
import com.extjs.gxt.ui.client.data.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gwt.user.client.rpc.AsyncCallback;
import org.activityinfo.legacy.client.Dispatcher;
import org.activityinfo.legacy.shared.Log;
import org.activityinfo.legacy.shared.command.Filter;
import org.activityinfo.legacy.shared.command.GetSites;
import org.activityinfo.legacy.shared.command.PivotSites;
import org.activityinfo.legacy.shared.command.PivotSites.PivotResult;
import org.activityinfo.legacy.shared.command.PivotSites.ValueType;
import org.activityinfo.legacy.shared.command.result.Bucket;
import org.activityinfo.legacy.shared.command.result.SiteResult;
import org.activityinfo.legacy.shared.model.SiteDTO;
import org.activityinfo.legacy.shared.reports.content.MonthCategory;
import org.activityinfo.legacy.shared.reports.content.YearCategory;
import org.activityinfo.legacy.shared.reports.model.DateDimension;
import org.activityinfo.legacy.shared.reports.model.DateRange;
import org.activityinfo.legacy.shared.reports.model.DateUnit;
import org.activityinfo.legacy.shared.reports.model.Dimension;
import java.util.List;
public class SiteTimeTreeLoader extends BaseTreeLoader<ModelData> implements SiteTreeLoader {
private TreeProxy treeProxy;
public SiteTimeTreeLoader(Dispatcher dispatcher) {
super(new TreeProxy(dispatcher));
treeProxy = (TreeProxy) proxy;
}
@Override
public void setFilter(Filter filter) {
treeProxy.setFilter(filter);
}
@Override
public String getKey(ModelData model) {
if (model instanceof YearModel) {
return ((YearModel) model).getKey();
} else if (model instanceof MonthModel) {
return ((MonthModel) model).getKey();
} else if (model instanceof SiteDTO) {
return "S" + ((SiteDTO) model).getId();
} else {
return "X" + model.hashCode();
}
}
@Override
public boolean hasChildren(ModelData parent) {
return parent instanceof YearModel || parent instanceof MonthModel;
}
private static class TreeProxy extends SafeRpcProxy<List<ModelData>> {
private static final DateDimension YEAR_DIMENSION = new DateDimension(DateUnit.YEAR);
private static final DateDimension MONTH_DIMENSION = new DateDimension(DateUnit.MONTH);
private final Dispatcher dispatcher;
private Filter filter;
public TreeProxy(Dispatcher dispatcher) {
super();
this.dispatcher = dispatcher;
}
public void setFilter(Filter filter) {
this.filter = filter;
}
@Override
protected void load(Object parentNode, AsyncCallback<List<ModelData>> callback) {
if (parentNode == null) {
loadYears(callback);
} else if (parentNode instanceof YearModel) {
loadMonths((YearModel) parentNode, callback);
} else if (parentNode instanceof MonthModel) {
loadSites((MonthModel) parentNode, callback);
}
}
private void loadYears(final AsyncCallback<List<ModelData>> callback) {
PivotSites pivot = new PivotSites();
pivot.setDimensions(Sets.<Dimension>newHashSet(YEAR_DIMENSION));
pivot.setFilter(filter);
pivot.setValueType(ValueType.TOTAL_SITES);
dispatcher.execute(pivot, new AsyncCallback<PivotResult>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override
public void onSuccess(PivotResult result) {
List<ModelData> years = Lists.newArrayList();
for (Bucket bucket : result.getBuckets()) {
years.add(new YearModel((YearCategory) bucket.getCategory(YEAR_DIMENSION)));
}
callback.onSuccess(years);
}
});
}
private void loadMonths(YearModel parentNode, final AsyncCallback<List<ModelData>> callback) {
PivotSites pivot = new PivotSites();
pivot.setDimensions(Sets.<Dimension>newHashSet(MONTH_DIMENSION));
pivot.setFilter(narrowFilter(parentNode.getDateRange()));
pivot.setValueType(ValueType.TOTAL_SITES);
dispatcher.execute(pivot, new AsyncCallback<PivotResult>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override
public void onSuccess(PivotResult result) {
List<ModelData> months = Lists.newArrayList();
for (Bucket bucket : result.getBuckets()) {
months.add(new MonthModel((MonthCategory) bucket.getCategory(MONTH_DIMENSION)));
}
callback.onSuccess(months);
}
});
}
private void loadSites(MonthModel parentEntity, final AsyncCallback<List<ModelData>> callback) {
GetSites siteQuery = new GetSites();
siteQuery.setFilter(narrowFilter(parentEntity.getDateRange()));
siteQuery.setSortInfo(new SortInfo("date2", SortDir.ASC));
dispatcher.execute(siteQuery, new AsyncCallback<SiteResult>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override
public void onSuccess(SiteResult result) {
callback.onSuccess((List) result.getData());
}
});
}
private Filter narrowFilter(DateRange range) {
Filter narrowed = new Filter(filter);
narrowed.setDateRange(DateRange.intersection(filter.getDateRange(), range));
return narrowed;
}
}
/**
* Clone for RPC Proxy that does not swallow exceptions.
*
* @param <D>
*/
public abstract static class SafeRpcProxy<D> implements DataProxy<D> {
@Override
public void load(final DataReader<D> reader, final Object loadConfig, final AsyncCallback<D> callback) {
load(loadConfig, new AsyncCallback<D>() {
@Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
@Override @SuppressWarnings("unchecked")
public void onSuccess(Object result) {
try {
D data = null;
if (reader != null) {
data = reader.read(loadConfig, result);
} else {
data = (D) result;
}
callback.onSuccess(data);
} catch (Exception e) {
Log.error("Rpc load failed: " + e.getMessage(), e);
callback.onFailure(e);
}
}
});
}
/**
* Subclasses should make RPC call using the load configuration.
*
* @param callback the callback to be used when making the rpc call.
*/
protected abstract void load(Object loadConfig, AsyncCallback<D> callback);
}
}