package org.activityinfo.legacy.shared.adapter;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import org.activityinfo.core.client.InstanceQuery;
import org.activityinfo.core.client.QueryResult;
import org.activityinfo.core.client.ResourceLocator;
import org.activityinfo.core.shared.Projection;
import org.activityinfo.core.shared.criteria.ClassCriteria;
import org.activityinfo.core.shared.criteria.Criteria;
import org.activityinfo.core.shared.criteria.IdCriteria;
import org.activityinfo.legacy.client.Dispatcher;
import org.activityinfo.legacy.shared.adapter.bindings.SiteBinding;
import org.activityinfo.legacy.shared.adapter.bindings.SiteBindingFactory;
import org.activityinfo.legacy.shared.command.GetActivityForm;
import org.activityinfo.legacy.shared.command.GetSites;
import org.activityinfo.legacy.shared.command.UpdateFormClass;
import org.activityinfo.legacy.shared.command.result.SiteResult;
import org.activityinfo.legacy.shared.model.ActivityFormDTO;
import org.activityinfo.legacy.shared.model.SiteDTO;
import org.activityinfo.model.form.FormClass;
import org.activityinfo.model.form.FormInstance;
import org.activityinfo.model.legacy.CuidAdapter;
import org.activityinfo.model.resource.IsResource;
import org.activityinfo.model.resource.ResourceId;
import org.activityinfo.promise.Promise;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Exposes a legacy {@code Dispatcher} implementation as new {@code ResourceLocator}
*/
public class ResourceLocatorAdaptor implements ResourceLocator {
private final Dispatcher dispatcher;
private final ClassProvider classProvider;
public ResourceLocatorAdaptor(Dispatcher dispatcher) {
this.dispatcher = dispatcher;
this.classProvider = new ClassProvider(dispatcher);
}
@Override
public Promise<FormClass> getFormClass(ResourceId classId) {
return classProvider.apply(classId);
}
@Override
public Promise<FormInstance> getFormInstance(ResourceId instanceId) {
if(instanceId.getDomain() == CuidAdapter.SITE_DOMAIN) {
final Promise<SiteResult> site = dispatcher.execute(GetSites.byId(CuidAdapter.getLegacyIdFromCuid(instanceId)));
final Promise<ActivityFormDTO> form = site.join(new Function<SiteResult, Promise<ActivityFormDTO>>() {
@Nullable
@Override
public Promise<ActivityFormDTO> apply(@Nullable SiteResult input) {
if (input != null) {
List<SiteDTO> data = input.getData();
if (data != null && !data.isEmpty()) {
SiteDTO siteDTO = data.get(0);
if (siteDTO != null) {
return dispatcher.execute(new GetActivityForm(siteDTO.getActivityId()));
}
}
}
return Promise.resolved(null);
}
});
return Promise.waitAll(site, form).then(new Function<Void, FormInstance>() {
@Nullable
@Override
public FormInstance apply(@Nullable Void input) {
if (form != null) {
ActivityFormDTO activityFormDTO = form.get();
if (activityFormDTO != null) {
SiteBinding binding = new SiteBindingFactory().apply(activityFormDTO);
if (site != null) {
SiteResult siteResult = site.get();
if (siteResult != null) {
List<SiteDTO> data = siteResult.getData();
if (data != null && !data.isEmpty()) {
SiteDTO siteDTO = data.get(0);
if (siteDTO != null) {
return binding.newInstance(siteDTO);
}
}
}
}
}
}
return null;
}
});
}
return queryInstances(new IdCriteria(instanceId)).then(new SelectSingle());
}
@Override
public Promise<Void> persist(IsResource resource) {
if (resource instanceof FormInstance) {
FormInstance instance = (FormInstance) resource;
if (instance.getId().getDomain() == CuidAdapter.SITE_DOMAIN) {
return new SitePersister(dispatcher).persist(instance);
} else if (instance.getId().getDomain() == CuidAdapter.LOCATION_DOMAIN) {
return new LocationPersister(dispatcher, instance).persist();
}
} else if(resource instanceof FormClass) {
return dispatcher.execute(new UpdateFormClass((FormClass) resource)).thenDiscardResult();
}
return Promise.rejected(new UnsupportedOperationException());
}
@Override
public Promise<Void> persist(List<? extends IsResource> resources) {
final List<Promise<Void>> promises = Lists.newArrayList();
if (resources != null && !resources.isEmpty()) {
for (final IsResource resource : resources) {
promises.add(persist(resource));
}
}
return Promise.waitAll(promises);
}
@Override
public Promise<List<FormInstance>> queryInstances(Criteria criteria) {
return new QueryExecutor(dispatcher, criteria).execute();
}
@Override
public Promise<List<Projection>> query(InstanceQuery query) {
return new Joiner(dispatcher, query.getFieldPaths(), query.getCriteria()).apply(query);
}
public Promise<QueryResult<Projection>> queryProjection(InstanceQuery query) {
return query(query).then(new InstanceQueryResultAdapter(query));
}
@Override
public Promise<Void> remove(Collection<ResourceId> resources) {
return new Eraser(dispatcher, resources).execute();
}
@Override
public Promise<List<FormInstance>> queryInstances(Set<ResourceId> formClassIds) {
return queryInstances(ClassCriteria.union(formClassIds));
}
}