GeographyRegionMapServiceImpl.java

/*
 * Copyright 2026 Global Crop Diversity Trust
 *
 * 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.
 */
package org.gringlobal.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.querydsl.core.types.dsl.BooleanExpression;
import org.gringlobal.model.Geography;
import org.gringlobal.model.GeographyRegionMap;
import org.gringlobal.model.QGeography;
import org.gringlobal.model.Region;
import org.gringlobal.persistence.GeographyRegionMapRepository;
import org.gringlobal.persistence.GeographyRepository;
import org.gringlobal.persistence.RegionRepository;
import org.gringlobal.service.GeographyRegionMapService;
import org.gringlobal.service.filter.GeographyRegionMapFilter;

@Service
@Transactional(readOnly = true)
public class GeographyRegionMapServiceImpl extends FilteredCRUDService2Impl<GeographyRegionMap, GeographyRegionMapFilter, GeographyRegionMapRepository> implements GeographyRegionMapService {

	@Autowired
	private GeographyRepository geographyRepository;

	@Autowired
	private RegionRepository regionRepository;

	@Override
	@Transactional
	@PreAuthorize("@ggceSec.actionAllowed('GeographyData', 'WRITE')")
	public GeographyRegionMap create(GeographyRegionMap source) {
		return _lazyLoad(createFast(source));
	}

	@Override
	@Transactional
	@PreAuthorize("@ggceSec.actionAllowed('GeographyData', 'WRITE')")
	public GeographyRegionMap createFast(GeographyRegionMap source) {
		final Long geoId = source.getGeography() != null ? source.getGeography().getId() : null;
		final Long regionId = source.getRegion() != null ? source.getRegion().getId() : null;
		if (geoId == null || regionId == null) {
			throw new IllegalArgumentException("Geography and Region must be provided.");
		}

		Geography geography = geographyRepository.findById(geoId).orElseThrow(() -> new IllegalArgumentException("Geography not found: " + geoId));
		Region region = regionRepository.findById(regionId).orElseThrow(() -> new IllegalArgumentException("Region not found: " + regionId));

		QGeography qGeography = QGeography.geography;
		BooleanExpression predicate = qGeography.countryCode.eq(geography.getCountryCode());
		if (geography.getAdm1() != null) predicate = predicate.and(qGeography.adm1.eq(geography.getAdm1()));
		if (geography.getAdm2() != null) predicate = predicate.and(qGeography.adm2.eq(geography.getAdm2()));
		if (geography.getAdm3() != null) predicate = predicate.and(qGeography.adm3.eq(geography.getAdm3()));
		if (geography.getAdm4() != null) predicate = predicate.and(qGeography.adm4.eq(geography.getAdm4()));

		List<Geography> toMap = jpaQueryFactory.selectFrom(qGeography).where(predicate).fetch();
		if (toMap == null) toMap = new ArrayList<>();
		
		List<GeographyRegionMap> mappingsToCreate = new ArrayList<>();
		for (Geography geo : toMap) {
			GeographyRegionMap existing = repository.findByGeographyAndRegion(geo, region);
			if (existing != null) {
				continue; // skip existing
			}
			GeographyRegionMap mapToSave = new GeographyRegionMap();
			mapToSave.setGeography(geo);
			mapToSave.setRegion(region);
			mappingsToCreate.add(mapToSave);
		}
		repository.saveAllAndFlush(mappingsToCreate);
		return repository.findByGeographyAndRegion(geography, region);
	}

	@Override
	@Transactional
	@PreAuthorize("@ggceSec.actionAllowed('GeographyData', 'WRITE')")
	public GeographyRegionMap update(GeographyRegionMap input, GeographyRegionMap target) {
		throw new UnsupportedOperationException("Geography–Region mapping updates are not permitted.");
	}

	@Override
	@Transactional
	@PreAuthorize("@ggceSec.actionAllowed('GeographyData', 'WRITE')")
	public GeographyRegionMap updateFast(GeographyRegionMap updated, GeographyRegionMap target) {
		throw new UnsupportedOperationException("Geography–Region mapping updates are not permitted.");
	}

	@Override
	@Transactional
	@PreAuthorize("@ggceSec.actionAllowed('GeographyData', 'WRITE')")
	public GeographyRegionMap remove(GeographyRegionMap entity) {
		// throw UnsupportedOperationException?
		return super.remove(entity);
	}
}