/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
/**
*
*/
package org.mifos.security.authorization;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mifos.core.MifosRuntimeException;
import org.mifos.customers.office.exceptions.OfficeException;
import org.mifos.customers.office.persistence.OfficePersistence;
import org.mifos.framework.exceptions.PersistenceException;
import org.mifos.framework.exceptions.SystemException;
import org.mifos.framework.util.helpers.Constants;
import org.mifos.security.util.Observer;
import org.mifos.security.util.OfficeCacheDto;
import org.mifos.security.util.OfficeSearch;
import org.mifos.security.util.SecurityEvent;
import org.mifos.security.util.UserContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
public class HierarchyManager implements Observer {
private static final Logger logger = LoggerFactory.getLogger(HierarchyManager.class);
private static Map<Short, OfficeCacheDto> hierarchyMap;
private static HierarchyManager hierarchyManager;
private HierarchyManager() {
hierarchyMap = new HashMap<Short, OfficeCacheDto>();
}
public static HierarchyManager getInstance() {
if (hierarchyManager == null) {
hierarchyManager = new HierarchyManager();
}
return hierarchyManager;
}
@Override
public void handleEvent(SecurityEvent e) {
logger.info("Map before" + hierarchyMap);
List<OfficeCacheDto> officeList = convertToOfficeCacheList((List<OfficeSearch>) e.getObject());
if (e.getEventType().equals(Constants.CREATE)) {
updateMapForCreateEvent(officeList);
} else if (e.getEventType().equals(Constants.UPDATE)) {
updateMapForUpdateEvent(officeList);
}
logger.info("Map after " + hierarchyMap);
}
private void updateMapForCreateEvent(List<OfficeCacheDto> officeList) {
addToMap(officeList.get(0));
}
private void updateMapForUpdateEvent(List<OfficeCacheDto> officeList) {
for (int i = 0; i < officeList.size(); i++) {
synchronized (hierarchyMap) {
hierarchyMap.remove(officeList.get(i));
addToMap(officeList.get(i));
}
}
}
private void addToMap(OfficeCacheDto cacheView) {
hierarchyMap.put(cacheView.getOfficeId(), cacheView);
}
private List<OfficeCacheDto> convertToOfficeCacheList(List<OfficeSearch> officeList) {
List<OfficeCacheDto> officeCacheList = new ArrayList<OfficeCacheDto>();
for (int i = 0; i < officeList.size(); i++) {
OfficeCacheDto cacheView = new OfficeCacheDto(officeList.get(i).getOfficeId(), officeList.get(i)
.getParentOfficeId(), officeList.get(i).getSearchId());
officeCacheList.add(cacheView);
}
return officeCacheList;
}
public void init() throws SystemException, OfficeException {
List<OfficeCacheDto> officeList;
try {
officeList = new OfficePersistence().getAllOffices();
} catch (PersistenceException e) {
throw new OfficeException(e);
}
hierarchyMap.clear();
for (int i = 0; i < officeList.size(); i++) {
addToMap(officeList.get(i));
}
}
public BranchLocation compareOfficeInHierarchy(UserContext user, Short officeId) {
Assert.notNull(officeId, "officeId should not be null");
Assert.notNull(user, "userContext should not be null");
short userBranch = user.getBranchId().shortValue();
if (userBranch == officeId) {
return BranchLocation.SAME;
}
/*
* Look into the map now if the passed officeid's searchid on which user wants to perform action starts with the
* user's office searchid it means that office falls under that user hiererchy
*/
String userOfficeSearchId = hierarchyMap.get(user.getBranchId()).getSearchId();
OfficeCacheDto cachedOffice = hierarchyMap.get(officeId);
if (cachedOffice == null) {
try {
init(); // repopulate cachedmap
cachedOffice = hierarchyMap.get(officeId);
} catch (SystemException e) {
throw new MifosRuntimeException(e);
} catch (OfficeException e) {
throw new MifosRuntimeException(e);
}
if (cachedOffice == null) {
throw new IllegalArgumentException("office with id [" + officeId + "] does not exist");
}
}
String operatedOfficeSearchId = cachedOffice.getSearchId();
if (operatedOfficeSearchId.startsWith(userOfficeSearchId)) {
return BranchLocation.BELOW;
}
return BranchLocation.ABOVE_OR_DIFFERENT;
}
public String getSearchId(short branchId) {
return hierarchyMap.get(Short.valueOf(branchId)).getSearchId();
}
public Short getParentOfficeId(Short officeId) {
return hierarchyMap.get(officeId).getParentOfficeId();
}
public enum BranchLocation {
SAME, BELOW, ABOVE_OR_DIFFERENT
};
}