package org.sigmah.client.cache;
/*
* #%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.HashMap;
import java.util.Map;
import org.sigmah.shared.dto.organization.OrganizationDTO;
import org.sigmah.shared.dto.orgunit.OrgUnitDTO;
import com.google.gwt.user.client.rpc.AsyncCallback;
/**
* Local cached organization.
*
* @author Denis Colliot (dcolliot@ideia.fr)
*/
public class LocalCachedOrganization {
/**
* Job to get the organization.
*
* @author tmi
*/
private static final class OrganizationAsyncCallback {
private final AsyncCallback<OrganizationDTO> callback;
private OrganizationAsyncCallback(AsyncCallback<OrganizationDTO> callback) {
this.callback = callback;
}
}
/**
* Job to get an organizational unit.
*
* @author tmi
*/
private static final class OrgUnitAsyncCallback {
private final Integer id;
private final AsyncCallback<OrgUnitDTO> callback;
private OrgUnitAsyncCallback(Integer id, AsyncCallback<OrgUnitDTO> callback) {
this.id = id;
this.callback = callback;
}
}
/**
* Cache of the organization.
*/
private OrganizationDTO organization;
/**
* The current user root organizational unit id.
*/
private Integer currentUserOrgUnitId;
/**
* Cache of the organizational units (for the current user only).
*/
private final HashMap<Integer, OrgUnitDTO> mapOrgUnits;
/**
* If the cache has been set.
*/
private boolean hasBeenSet;
/**
* Waiting jobs to get the organization instance.
*/
private final ArrayList<OrganizationAsyncCallback> queueOrganization;
/**
* Waiting jobs to get an org unit instance.
*/
private final ArrayList<OrgUnitAsyncCallback> queueOrgUnit;
/**
* Waiting jobs to get the root org unit instance for the current user.
*/
private final ArrayList<OrgUnitAsyncCallback> queueUserOrgUnit;
public LocalCachedOrganization() {
mapOrgUnits = new HashMap<Integer, OrgUnitDTO>();
hasBeenSet = false;
queueOrganization = new ArrayList<OrganizationAsyncCallback>();
queueOrgUnit = new ArrayList<OrgUnitAsyncCallback>();
queueUserOrgUnit = new ArrayList<OrgUnitAsyncCallback>();
}
/**
* Gets the organization for the current user. If the cache isn't available immediately, the callback will be called
* after the cache has been set by the first server call.
*
* @param callback
* The callback.
*/
public void getOrganization(AsyncCallback<OrganizationDTO> callback) {
// If the cache is available, returns it immediately.
if (hasBeenSet) {
callback.onSuccess(organization);
}
// Else put the callback in queue to be called later.
else {
queueOrganization.add(new OrganizationAsyncCallback(callback));
}
}
/**
* Tries to get the organization of the current user without waiting.
*
* @return The organization if the cache has been set, <code>null</code> otherwise.
*/
public OrganizationDTO getOrganization() {
return organization;
}
/**
* Gets the root organizational unit for the current user. If the cache isn't available immediately, the callback will
* be called after the cache has been set by the first server call.
*
* @param callback
* The callback.
*/
public void get(AsyncCallback<OrgUnitDTO> callback) {
// If the cache is available, returns it immediately.
if (hasBeenSet) {
callback.onSuccess(mapOrgUnits.get(currentUserOrgUnitId));
}
// Else put the callback in queue to be called later.
else {
queueUserOrgUnit.add(new OrgUnitAsyncCallback(currentUserOrgUnitId, callback));
}
}
/**
* Tries to get the root organizational unit of the current user without waiting.
*
* @return The organizational unit if the cache has been set, <code>null</code> otherwise.
*/
public OrgUnitDTO get() {
return get(currentUserOrgUnitId);
}
/**
* Gets the an organizational unit. If the cache isn't available immediately, the callback will be called after the
* cache has been set by the first server call.
*
* @param id
* The id.
* @param callback
* The callback.
*/
public void get(Integer id, AsyncCallback<OrgUnitDTO> callback) {
// If the requested id is null, returns immediatly a null result.
if(id == null) {
callback.onSuccess(null);
}
// If the cache is available, returns it immediately.
if (hasBeenSet) {
callback.onSuccess(mapOrgUnits.get(id));
}
// Else put the callback in queue to be called later.
else {
queueOrgUnit.add(new OrgUnitAsyncCallback(id, callback));
}
}
/**
* Tries to get an organizational unit without waiting.
*
* @param id
* The id.
* @return The organizational unit if the cache has been set, <code>null</code> otherwise.
*/
public OrgUnitDTO get(Integer id) {
if (hasBeenSet) {
return mapOrgUnits.get(id);
} else {
return null;
}
}
/**
* Sets the organization and call all waiting jobs.
*
* @param currentUserOrgUnitId
* The root organizational unit for the current user.
* @param organization
* The organization.
*/
protected void set(OrganizationDTO organization, Integer currentUserOrgUnitId) {
// // This method is called once.
// if (hasBeenSet) {
// return;
// }
this.currentUserOrgUnitId = currentUserOrgUnitId;
this.organization = organization;
// Stores entities.
if (organization != null) {
crawlOrgUnit(mapOrgUnits, organization.getRoot());
}
// Calls the waiting jobs.
for (final OrganizationAsyncCallback job : queueOrganization) {
job.callback.onSuccess(organization);
}
for (final OrgUnitAsyncCallback job : queueOrgUnit) {
job.callback.onSuccess(mapOrgUnits.get(job.id));
}
for (final OrgUnitAsyncCallback job : queueUserOrgUnit) {
job.callback.onSuccess(mapOrgUnits.get(currentUserOrgUnitId));
}
// Clears the queues.
queueOrganization.clear();
queueOrgUnit.clear();
queueUserOrgUnit.clear();
hasBeenSet = true;
}
/**
* Crawls among the organizational units tree and store them in the map.
*
* @param map
* The map.
* @param root
* The root organizational unit.
*/
private static void crawlOrgUnit(Map<Integer, OrgUnitDTO> map, OrgUnitDTO root) {
if (root == null) {
return;
}
map.put(root.getId(), root);
if (root.getChildren() == null) {
return;
}
for (final OrgUnitDTO child : root.getChildrenOrgUnits()) {
if (child.getDeleted() == null) {
crawlOrgUnit(map, child);
}
}
}
}