package com.eswaraj.core.service.impl;
import java.io.InputStream;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.eswaraj.core.convertors.LocationBoundaryFileConvertor;
import com.eswaraj.core.convertors.LocationConvertor;
import com.eswaraj.core.convertors.LocationTypeConvertor;
import com.eswaraj.core.convertors.LocationTypeJsonConvertor;
import com.eswaraj.core.exceptions.ApplicationException;
import com.eswaraj.core.service.FileService;
import com.eswaraj.core.service.LocationService;
import com.eswaraj.core.util.DateTimeUtil;
import com.eswaraj.domain.nodes.DataClient;
import com.eswaraj.domain.nodes.Location;
import com.eswaraj.domain.nodes.LocationBoundaryFile;
import com.eswaraj.domain.nodes.LocationType;
import com.eswaraj.domain.repo.DataClientRepository;
import com.eswaraj.domain.repo.LocationBoundaryFileRepository;
import com.eswaraj.domain.repo.LocationRepository;
import com.eswaraj.domain.repo.LocationTypeRepository;
import com.eswaraj.web.dto.BoundaryDto;
import com.eswaraj.web.dto.GeoPointDto;
import com.eswaraj.web.dto.LocationBoundaryFileDto;
import com.eswaraj.web.dto.LocationDto;
import com.eswaraj.web.dto.LocationTypeDto;
import com.eswaraj.web.dto.LocationTypeJsonDto;
@Component
@Transactional
public class LocationServiceImpl implements LocationService {
@Autowired
private DateTimeUtil dateTimeUtil;
@Autowired
private LocationRepository locationRepository;
@Autowired
private LocationConvertor locationConvertor;
@Autowired
private LocationBoundaryFileRepository locationBoundaryFileRepository;
@Autowired
private LocationBoundaryFileConvertor locationBoundaryFileConvertor;
@Autowired
private LocationTypeRepository locationTypeRepository;
@Autowired
private LocationTypeConvertor locationTypeConvertor;
@Autowired
private LocationTypeJsonConvertor locationTypeJsonConvertor;
@Autowired
private DataClientRepository dataClientRepository;
private String baseDirectoryForlocationFiles = "/tmp";
private String indiaEswarajClientName = "Eswaraj-India";
private String indiaEswarajRootLocationTypeName = "Country";
@Override
public LocationDto saveLocation(LocationDto locationDto) throws ApplicationException{
Location location = locationConvertor.convert(locationDto);
//Check Parent child rule
checkParentChildRule(location);
locationRepository.save(location);
return locationConvertor.convertBean(location);
}
private void checkParentChildRule(Location location) throws ApplicationException{
//LocationType parentLocationType = locationTypeRepository.findOne(location.getParentLocation().getLocationType().getId());
if(location.getParentLocation() == null){
if(location.getLocationType().getParentLocationType() != null){
throw new ApplicationException("Can not create a Location of type ["+location.getLocationType().getName()+"], without a parent Location");
}
}else{
Location parentLocation = location.getParentLocation();
if(!location.getLocationType().getParentLocationType().getId().equals(parentLocation.getLocationType().getId())){
LocationType parentLocationType = locationTypeRepository.findOne(parentLocation.getLocationType().getId());
throw new ApplicationException("Can not create a Location of type ["+location.getLocationType().getName()+"], under location type ["+parentLocationType.getName()+"]");
}
}
}
@Override
public LocationDto getLocationById(Long id) throws ApplicationException{
Location dbLocation = locationRepository.findOne(id);
return locationConvertor.convertBean(dbLocation);
}
@Override
public List<LocationDto> getChildLocationsOfParent(Long parentLocationId) throws ApplicationException{
Location parenLocation = locationRepository.findOne(parentLocationId);
Collection<Location> childLocations = locationRepository.findLocationByParentLocation(parenLocation);
return locationConvertor.convertBeanList(childLocations);
}
@Override
public LocationBoundaryFileDto createNewLocationBoundaryFile(Long locationId, InputStream inputStream, FileService fileService) throws ApplicationException {
Location location = locationRepository.findOne(locationId);
if(location == null){
throw new ApplicationException("No such location exists[id="+locationId+"]");
}
String currenttime = dateTimeUtil.getCurrentTimeYYYYMMDDHHMMSS();
String fileName = UUID.randomUUID().toString()+"_"+currenttime;
//save file to a storage
fileService.saveFile(baseDirectoryForlocationFiles, fileName, inputStream);
//create LocationBoudaryFile
LocationBoundaryFile locationBoundaryFile = new LocationBoundaryFile();
locationBoundaryFile.setLocation(location);
locationBoundaryFile.setFileNameAndPath(baseDirectoryForlocationFiles + fileName);
locationBoundaryFile.setStatus("Pending");
locationBoundaryFile.setUploadDate(new Date());
locationBoundaryFile = locationBoundaryFileRepository.save(locationBoundaryFile);
return locationBoundaryFileConvertor.convertBean(locationBoundaryFile);
}
@Override
public BoundaryDto saveBoundary(BoundaryDto boundaryDto) throws ApplicationException {
// TODO Auto-generated method stub
return null;
}
@Override
public GeoPointDto saveBoundaryPoint(GeoPointDto geoPointDto) throws ApplicationException {
// TODO Auto-generated method stub
return null;
}
private DataClient getOrCreateDataClientIndiaEswaraj(){
DataClient dataClient = dataClientRepository.getDataClientByName(indiaEswarajClientName);
if(dataClient == null){
dataClient = new DataClient();
dataClient.setName(indiaEswarajClientName);
dataClient = dataClientRepository.save(dataClient);
}
return dataClient;
}
private LocationType getOrCreateRootLocationTypeIndiaEswaraj(DataClient dataClient){
LocationType locationType = locationTypeRepository.getRootLocationTypeByDataClient(dataClient.getName());
if(locationType == null){
locationType = new LocationType();
locationType.setName(indiaEswarajRootLocationTypeName);
locationType.setDataClient(dataClient);
locationType = locationTypeRepository.save(locationType);
}
return locationType;
}
private void checkIfRootLocationAlreadyExists(LocationType locationType, DataClient dataClient) throws ApplicationException {
if(locationType.getParentLocationType() == null){
//now check if one ROOT Location already exists for this Data client
//If yes then throw exception as we can not have more then one Root Location(usually country) for a Data client
LocationType existingRootLocationType = locationTypeRepository.getRootLocationTypeByDataClient(dataClient.getName());
if(existingRootLocationType != null){
throw new ApplicationException("One root location type already exists["+ existingRootLocationType.getName()+","+existingRootLocationType.getId()+"], you can not create more then one root location Type. If you are trying to create child location type then make sure you set parentLocationType");
}
}
}
@Override
public LocationTypeDto saveLocationType(LocationTypeDto locationTypeDto) throws ApplicationException {
LocationType locationType = locationTypeConvertor.convert(locationTypeDto);
//get the data Client, right now its hard coded for eswaraj-India, in future we will get it from client
DataClient dataClient = getOrCreateDataClientIndiaEswaraj();
locationType.setDataClient(dataClient);
if(locationType.getId() == null){
//means we are trying to create new location type
checkIfRootLocationAlreadyExists(locationType, dataClient);
}
locationType = locationTypeRepository.save(locationType);
return locationTypeConvertor.convertBean(locationType);
}
@Override
public LocationDto getRootLocationForSwarajIndia() throws ApplicationException {
DataClient dataClient = getOrCreateDataClientIndiaEswaraj();
LocationType locationType = getOrCreateRootLocationTypeIndiaEswaraj(dataClient);
Location location = locationRepository.getRootLocationByLocationType(locationType.getId());
if(location == null){
//create default location India
location = new Location();
location.setLocationType(locationType);
location.setName("India");
location = locationRepository.save(location);
}
return locationConvertor.convertBean(location);
}
@Override
public LocationTypeJsonDto getLocationTypes(String clientName) throws ApplicationException {
//Ignoring passed client name and will use hardcoded client name
DataClient dataClient = getOrCreateDataClientIndiaEswaraj();
Collection<LocationType> locationTypes = locationTypeRepository.getAllLocationTypeOfDataClient(dataClient.getId());
return locationTypeJsonConvertor.convertToJsonBean(locationTypes);
}
}