MapstructMapper.java

/*
 * Copyright 2024 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.genesys.server.api.v2.mapper;

import org.apache.commons.lang3.time.StopWatch;
import org.genesys.blocks.model.ClassPK;
import org.genesys.blocks.security.SecurityContextUtil;
import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.blocks.security.serialization.Permissions;
import org.genesys.blocks.util.JsonSidConverter.SidProvider;
import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys.filerepository.model.ImageGallery;
import org.genesys.filerepository.model.RepositoryFile;
import org.genesys.filerepository.model.RepositoryFolder;
import org.genesys.filerepository.model.RepositoryImage;
import org.genesys.server.api.v2.MultiOp;
import org.genesys.server.api.v2.facade.AccessionApiService;
import org.genesys.server.api.v2.facade.PartnerApiService;
import org.genesys.server.api.v2.mapper.MapstructMapper.DataMappingsConfig.AuditNames;
import org.genesys.server.api.v2.mapper.MapstructMapper.DataMappingsConfig.IgnoreAudit;
import org.genesys.server.api.v2.mapper.MapstructMapper.DataMappingsConfig.IgnorePermissions;
import org.genesys.server.api.v2.mapper.MapstructMapper.DataMappingsConfig.IncludePermissions;
import org.genesys.server.api.v2.mapper.MapstructMapper.DataMappingsConfig.IsPublic;
import org.genesys.server.api.v2.model.dataset.DatasetAccessionRefDTO;
import org.genesys.server.api.v2.model.dataset.DatasetCreatorDTO;
import org.genesys.server.api.v2.model.dataset.DatasetCreatorInfo;
import org.genesys.server.api.v2.model.dataset.DatasetDTO;
import org.genesys.server.api.v2.model.dataset.DatasetLangDTO;
import org.genesys.server.api.v2.model.dataset.DatasetLocationDTO;
import org.genesys.server.api.v2.model.dataset.DatasetLocationInfo;
import org.genesys.server.api.v2.model.dataset.TranslatedDatasetDTO;
import org.genesys.server.api.v2.model.dataset.TranslatedDatasetInfo;
import org.genesys.server.api.v2.model.impl.FaoInstituteDTO;
import org.genesys.server.api.v2.model.impl.FaoInstituteSettingInfo;
import org.genesys.server.api.v2.model.impl.PGRFANetworkInfo;
import org.genesys.server.api.v2.model.impl.PartnerDTO;
import org.genesys.server.api.v2.model.impl.AccessionAliasInfo;
import org.genesys.server.api.v2.model.impl.AccessionCollectInfo;
import org.genesys.server.api.v2.model.impl.AccessionDTO;
import org.genesys.server.api.v2.model.impl.AccessionListInfo;
import org.genesys.server.api.v2.model.impl.AccessionRemarkInfo;
import org.genesys.server.api.v2.model.impl.CountryInfo;
import org.genesys.server.api.v2.model.impl.PDCIInfo;
import org.genesys.server.api.v2.model.impl.PartnerInfo;
import org.genesys.server.api.v2.model.bib.AuthorDTO;
import org.genesys.server.api.v2.model.bib.CitationDTO;
import org.genesys.server.api.v2.model.bib.CitationInfo;
import org.genesys.server.api.v2.model.dataset.DatasetInfo;
import org.genesys.server.api.v2.model.genesys.AccessionInfo;
import org.genesys.server.api.v2.model.grin.TaxonomySpeciesInfo;
import org.genesys.server.api.v2.model.impl.ActivityPostDTO;
import org.genesys.server.api.v2.model.impl.ActivityPostLangDTO;
import org.genesys.server.api.v2.model.impl.ArticleDTO;
import org.genesys.server.api.v2.model.impl.ArticleLangDTO;
import org.genesys.server.api.v2.model.impl.ClassPKInfo;
import org.genesys.server.api.v2.model.impl.CropDTO;
import org.genesys.server.api.v2.model.impl.CropDetailsDTO;
import org.genesys.server.api.v2.model.impl.CropInfo;
import org.genesys.server.api.v2.model.impl.CropLangDTO;
import org.genesys.server.api.v2.model.impl.ControlledVocabularyInfo;
import org.genesys.server.api.v2.model.impl.DescriptorDTO;
import org.genesys.server.api.v2.model.impl.DescriptorInfo;
import org.genesys.server.api.v2.model.impl.DescriptorLangDTO;
import org.genesys.server.api.v2.model.impl.DescriptorListDTO;
import org.genesys.server.api.v2.model.impl.DescriptorListInfo;
import org.genesys.server.api.v2.model.impl.DescriptorListLangDTO;
import org.genesys.server.api.v2.model.impl.FaoInstituteInfo;
import org.genesys.server.api.v2.model.impl.ImageGalleryDTO;
import org.genesys.server.api.v2.model.impl.MenuDTO;
import org.genesys.server.api.v2.model.impl.MenuInfo;
import org.genesys.server.api.v2.model.impl.MenuItemDTO;
import org.genesys.server.api.v2.model.impl.MenuItemLangDTO;
import org.genesys.server.api.v2.model.impl.RepositoryFileDTO;
import org.genesys.server.api.v2.model.impl.RepositoryFileInfo;
import org.genesys.server.api.v2.model.impl.RepositoryFolderDTO;
import org.genesys.server.api.v2.model.impl.RepositoryFolderInfo;
import org.genesys.server.api.v2.model.impl.RepositoryImageDTO;
import org.genesys.server.api.v2.model.impl.RepositoryImageInfo;
import org.genesys.server.api.v2.model.impl.SubsetAccessionRefDTO;
import org.genesys.server.api.v2.model.impl.SubsetCreatorDTO;
import org.genesys.server.api.v2.model.impl.SubsetDTO;
import org.genesys.server.api.v2.model.impl.SubsetInfo;
import org.genesys.server.api.v2.model.impl.SubsetLangDTO;
import org.genesys.server.api.v2.model.impl.SubsetVersionsDTO;
import org.genesys.server.api.v2.model.impl.Taxonomy2Info;
import org.genesys.server.api.v2.model.impl.TileClimateInfo;
import org.genesys.server.api.v2.model.impl.TranslatedActivityPostDTO;
import org.genesys.server.api.v2.model.impl.TranslatedArticleDTO;
import org.genesys.server.api.v2.model.impl.TranslatedCropDTO;
import org.genesys.server.api.v2.model.impl.TranslatedDescriptorDTO;
import org.genesys.server.api.v2.model.impl.TranslatedDescriptorInfo;
import org.genesys.server.api.v2.model.impl.TranslatedDescriptorListDTO;
import org.genesys.server.api.v2.model.impl.TranslatedMenuItemDTO;
import org.genesys.server.api.v2.model.impl.TranslatedSubsetDTO;
import org.genesys.server.api.v2.model.impl.TranslatedVocabularyTermDTO;
import org.genesys.server.api.v2.model.impl.VocabularyTermDTO;
import org.genesys.server.api.v2.model.impl.VocabularyTermInfo;
import org.genesys.server.api.v2.model.impl.VocabularyTermLangDTO;
import org.genesys.server.model.Partner;
import org.genesys.server.model.bib.Author;
import org.genesys.server.model.bib.Citation;
import org.genesys.server.model.dataset.Dataset;
import org.genesys.server.model.dataset.DatasetAccessionRef;
import org.genesys.server.model.dataset.DatasetCreator;
import org.genesys.server.model.dataset.DatasetLang;
import org.genesys.server.model.dataset.DatasetLocation;
import org.genesys.server.model.genesys.Accession;
import org.genesys.server.model.genesys.AccessionAlias;
import org.genesys.server.model.genesys.AccessionCollect;
import org.genesys.server.model.genesys.AccessionList;
import org.genesys.server.model.genesys.AccessionRemark;
import org.genesys.server.model.genesys.PDCI;
import org.genesys.server.model.genesys.Taxonomy2;
import org.genesys.server.model.grin.TaxonomySpecies;
import org.genesys.server.model.impl.ActivityPost;
import org.genesys.server.model.impl.ActivityPostLang;
import org.genesys.server.model.impl.Article;
import org.genesys.server.model.impl.ArticleLang;
import org.genesys.server.model.impl.Country;
import org.genesys.server.model.impl.Crop;
import org.genesys.server.model.impl.CropLang;
import org.genesys.server.model.impl.FaoInstitute;
import org.genesys.server.model.impl.FaoInstituteSetting;
import org.genesys.server.model.impl.Menu;
import org.genesys.server.model.impl.MenuItem;
import org.genesys.server.model.impl.MenuItemLang;
import org.genesys.server.model.impl.PGRFANetwork;
import org.genesys.server.model.impl.Subset;
import org.genesys.server.model.impl.SubsetAccessionRef;
import org.genesys.server.model.impl.SubsetCreator;
import org.genesys.server.model.impl.SubsetLang;
import org.genesys.server.model.impl.SubsetVersions;
import org.genesys.server.model.impl.TileClimate;
import org.genesys.server.model.traits.Descriptor;
import org.genesys.server.model.traits.DescriptorLang;
import org.genesys.server.model.traits.DescriptorList;
import org.genesys.server.model.traits.DescriptorListLang;
import org.genesys.server.model.vocab.ControlledVocabulary;
import org.genesys.server.model.vocab.VocabularyTerm;
import org.genesys.server.model.vocab.VocabularyTermLang;
import org.genesys.server.service.AccessionService;
import org.genesys.server.service.ActivityPostTranslationService;
import org.genesys.server.service.ArticleTranslationService;
import org.genesys.server.service.CropService;
import org.genesys.server.service.CropTranslationService;
import org.genesys.server.service.DatasetTranslationService;
import org.genesys.server.service.DescriptorListTranslationService;
import org.genesys.server.service.DescriptorTranslationService;
import org.genesys.server.service.MenuItemTranslationService;
import org.genesys.server.service.PartnerService;
import org.genesys.server.service.SubsetTranslationService;
import org.genesys.server.service.VocabularyTermTranslationService;
import org.mapstruct.BeanMapping;
import org.mapstruct.InjectionStrategy;
import org.mapstruct.Mapper;
import org.mapstruct.MapperConfig;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.SubclassMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import lombok.extern.slf4j.Slf4j;

import javax.validation.constraints.NotNull;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

@Mapper(componentModel = "spring", injectionStrategy = InjectionStrategy.FIELD, config = MapstructMapper.DataMappingsConfig.class)
@Slf4j
public abstract class MapstructMapper {

	@Autowired
	private SidProvider sidNameProvider;

	// Configs and utils

	public <A, B> B[] map(@NotNull A[] source, @NotNull Function<A, B> mapper, @NotNull B[] array) {
		var res = new ArrayList<B>(source.length);
		for (A a : source) {
			res.add(mapper.apply(a));
		}
		return res.toArray(array);
	}

	public <A, B> List<B> map(@NotNull Collection<A> source, @NotNull Function<A, B> mapper) {
		if (source == null) return null;
		var res = new LinkedList<B>();
		source.forEach(x -> res.add(mapper.apply(x)));
		return res;
	}

	public <A, B> Page<B> map(@NotNull Page<A> source, @NotNull Function<A, B> mapper) {
		if (source == null) return null;
		return source.map(mapper);
	}

	public <A, B> MultiOp<B> map(@NotNull MultiOp<A> source, @NotNull Function<A, B> mapper) {
		if (source == null) return null;
		return new MultiOp<>(this.map(source.success, mapper), source.errors);
	}

	@Named("mapStringYN")
	protected boolean mapStringYN(String ynValue) {
		return Objects.equals("Y", ynValue);
	}

	// @Named("mapBooleanYN")
	// default String mapBooleanYN(boolean value) {
	// 	return value ? Y : N;
	// }

	// default Dimension<?> mapDimensionFromDTO(DimensionDTO dimensionDTO) {
	// 	if (dimensionDTO instanceof BooleanDimensionDTO) {
	// 		return map((BooleanDimensionDTO)dimensionDTO);
	// 	} else if (dimensionDTO instanceof StringListDimensionDTO) {
	// 		return map((StringListDimensionDTO)dimensionDTO);
	// 	} else if (dimensionDTO instanceof JpaDimensionDTO) {
	// 		return map((JpaDimensionDTO)dimensionDTO);
	// 	} else if (dimensionDTO instanceof NumericListDimensionDTO) {
	// 		return map((NumericListDimensionDTO) dimensionDTO);
	// 	} else {
	// 		throw new IllegalArgumentException("Dimension type is not supported");
	// 	}
	// }

	// default DimensionDTO mapDimensionDTOFromEntity(Dimension<?> dimension) {
	// 	if (dimension instanceof BooleanDimension) {
	// 		return map((BooleanDimension)dimension);
	// 	} else if (dimension instanceof StringListDimension) {
	// 		return map((StringListDimension)dimension);
	// 	} else if (dimension instanceof JpaDimension) {
	// 		return map((JpaDimension)dimension);
	// 	} else if (dimension instanceof NumericListDimension) {
	// 		return map((NumericListDimension)dimension);
	// 	} else {
	// 		throw new IllegalArgumentException("Dimension type is not supported");
	// 	}
	// }

	@Named("getAclSid")
	public String getAclSid(Long id) {
		if (id == null) {
			// Don't write SID name
			return null;
		}
		return sidNameProvider == null ? id.toString() : sidNameProvider.getSidName(id);
	}

	@Named("isPublic")
	static boolean isPublic(AclAwareModel model) {
		if (model.getId() == null) {
			// Don't write permissions for non-persisted objects
			return false;
		}

		try {
			// StopWatch stopWatch = StopWatch.createStarted();
			var result = SecurityContextUtil.anyoneHasPermission(model, "READ");
			// log.warn("isPublic in {}ms", stopWatch.getTime());
			return result;
		} catch (Throwable e) {
			return false;
		}
	}

	@Named("getPermissions")
	static Permissions getPermissions(AclAwareModel model) {
		if (model.getId() == null) {
			// Don't write permissions for non-persisted objects
			return null;
		}

		StopWatch stopWatch = StopWatch.createStarted();
		log.trace("start getPermissions in {}ms", stopWatch.getTime());
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication == null) {
			return new Permissions().grantNone();
		}

		Permissions perms;
		if (SecurityContextUtil.hasRole("ADMINISTRATOR")) {
			perms = new Permissions().grantAll();
			try {
				perms.isPublic = SecurityContextUtil.anyoneHasPermission(model, "READ");
			} catch (Throwable e) {
				perms.isPublic = false;
			}
			log.trace("ADMINISTRATOR in {}ms", stopWatch.getTime());
		} else {
			try {
				perms = SecurityContextUtil.getPermissions(authentication, model);
				log.trace("permissions in {}ms", stopWatch.getTime());
			} catch (Throwable e) {
				throw new IllegalArgumentException("Could not read current permissions " + e.getMessage(), e);
			}
		}
		log.trace("getPermissions in {}ms", stopWatch.getTime());
		return perms;
	}

	@MapperConfig(imports = {
		Objects.class
	})
	interface DataMappingsConfig {

		@Retention(RetentionPolicy.CLASS)
		@Mapping(source = "createdBy", target = "createdBy", qualifiedByName = "getAclSid")
		@Mapping(source = "lastModifiedBy", target = "lastModifiedBy", qualifiedByName = "getAclSid")
		public @interface AuditNames {
		}

		@Retention(RetentionPolicy.CLASS)
		@Mapping(target = "createdBy", ignore = true)
		@Mapping(target = "lastModifiedBy", ignore = true)
		public @interface IgnoreAudit {
		}

		@Retention(RetentionPolicy.CLASS)
		@Mapping(target = "public", source = ".", qualifiedByName = "isPublic")
		public @interface IsPublic {
		}

		@Retention(RetentionPolicy.CLASS)
		@Mapping(source = ".", target = "_permissions", qualifiedByName = "getPermissions")
		public @interface IncludePermissions {
		}

		@Retention(RetentionPolicy.CLASS)
		@Mapping(target = "_permissions", ignore = true)
		public @interface IgnorePermissions {
		}


		// @Retention(RetentionPolicy.CLASS)
		// @Mapping(source = "accessionId.uuid", target = "uuid")
		// @Mapping(source = "accessionId.imageCount", target = "imageCount")
		// @Mapping(source = "accessionId.subsetCount", target = "subsetCount")
		// @Mapping(source = "accessionId.datasetCount", target = "datasetCount")
		// @Mapping(source = "accessionId.longitude", target = "longitude")
		// @Mapping(source = "accessionId.latitude", target = "latitude")
		// @Mapping(source = "accessionId.elevation", target = "elevation")
		// @Mapping(source = "accessionId.coordinateUncertainty", target = "coordinateUncertainty")
		// @Mapping(source = "accessionId.coordinateDatum", target = "coordinateDatum")
		// @Mapping(source = "accessionId.georeferenceMethod", target = "georeferenceMethod")
		// @Mapping(source = "accessionId.tileIndex", target = "tileIndex")
		// @Mapping(source = "accessionId.tileIndex3min", target = "tileIndex3min")
		// @interface AccessionIdInfoFieldsToDTOMappings {
		// }

		// @Retention(RetentionPolicy.CLASS)
		// @Mapping(target = "accessionId.uuid", source = "uuid")
		// @Mapping(target = "accessionId.imageCount", source = "imageCount")
		// @Mapping(target = "accessionId.subsetCount", source = "subsetCount")
		// @Mapping(target = "accessionId.datasetCount", source = "datasetCount")
		// @Mapping(target = "accessionId.longitude", source = "longitude")
		// @Mapping(target = "accessionId.latitude", source = "latitude")
		// @Mapping(target = "accessionId.elevation", source = "elevation")
		// @Mapping(target = "accessionId.coordinateUncertainty", source = "coordinateUncertainty")
		// @Mapping(target = "accessionId.coordinateDatum", source = "coordinateDatum")
		// @Mapping(target = "accessionId.georeferenceMethod", source = "georeferenceMethod")
		// @Mapping(target = "accessionId.tileIndex", source = "tileIndex")
		// @Mapping(target = "accessionId.tileIndex3min", source = "tileIndex3min")
		// @interface AccessionIdInfoFieldsToEntityMappings {
		// }

		// @AccessionIdInfoFieldsToDTOMappings
		// @Mapping(source = "accessionId.lists", target = "lists")
		// @Mapping(source = "accessionId.pdci", target = "pdci")
		// @Mapping(source = "accessionId.storage", target = "storage")
		// @Mapping(source = "accessionId.duplSite", target = "duplSite")
		// @Mapping(source = "accessionId.coll", target = "coll")
		// @Mapping(source = "accessionId.aliases", target = "aliases")
		// @Mapping(source = "accessionId.remarks", target = "remarks")
		// @Mapping(source = "accessionId.breederCode", target = "breederCode")
		// @Mapping(source = "accessionId.breederName", target = "breederName")
		// @Mapping(source = "accessionId.climate", target = "climate")
		// AccessionDataDTO mapAccessionDataToDTO(AccessionData accessionData);

		// @AccessionIdInfoFieldsToEntityMappings
		// @Mapping(target = "accessionId.lists", source = "lists")
		// @Mapping(target = "accessionId.pdci", source = "pdci")
		// @Mapping(target = "accessionId.storage", source = "storage")
		// @Mapping(target = "accessionId.duplSite", source = "duplSite")
		// @Mapping(target = "accessionId.coll", source = "coll")
		// @Mapping(target = "accessionId.aliases", source = "aliases")
		// @Mapping(target = "accessionId.remarks", source = "remarks")
		// @Mapping(target = "accessionId.breederCode", source = "breederCode")
		// @Mapping(target = "accessionId.breederName", source = "breederName")
		// @Mapping(target = "accessionId.climate", source = "climate")
		// AccessionData mapAccessionDataFromDTO(AccessionDataDTO accessionDataDTO);

		// @AccessionIdInfoFieldsToDTOMappings
		// AccessionDataInfo mapAccessionDataToInfo(AccessionData accessionData);
	}

	// Mappings

	public abstract DatasetAccessionRefDTO map(DatasetAccessionRef accessionRef);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(target = "doi", source = "doi")
	@Mapping(target = "instCode", source = "instCode")
	@Mapping(target = "acceNumb", source = "acceNumb")
	@Mapping(target = "genus", source = "genus")
	@Mapping(target = "species", source = "species")
	@Mapping(target = "accession", source = "accession")
	public abstract DatasetAccessionRef map(DatasetAccessionRefDTO accessionRefDTO);

	public abstract DatasetCreatorInfo mapInfo(DatasetCreator datasetCreator);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "uuid", target = "uuid")
	public abstract DatasetCreator mapInfo(DatasetCreatorInfo info);

	public abstract DatasetCreatorDTO map(DatasetCreator datasetCreator);
	
	@Mapping(target = "dataset", ignore = true)
	public abstract DatasetCreator map(DatasetCreatorDTO datasetCreatorDTO);

	@IncludePermissions
	@AuditNames
	public abstract DatasetDTO map(Dataset dataset);

	@IgnoreAudit
	@Mapping(target = "langs", ignore = true)
	@Mapping(target = "repositoryFiles", ignore = true)
	@Mapping(target = "accessionRefs", ignore = true)
	@Mapping(target = "versions", ignore = true)
	public abstract Dataset map(DatasetDTO datasetDTO);

	@IgnoreAudit
	@Mapping(source = "entityId", target = "entity.id")
	public abstract DatasetLang map(DatasetLangDTO dto);

	@Mapping(source = "entity.id", target = "entityId")
	public abstract DatasetLangDTO map(DatasetLang datasetLang);

	@IncludePermissions
	public abstract DatasetInfo mapInfo(Dataset dataset);

	@Mapping(target = "entity", source = "entity")
	@Mapping(target = "translation", source = "translation")
	@Mapping(target = "descriptors", source = "descriptors")
	@Mapping(target = "entity._permissions", source = "entity", qualifiedByName = "getPermissions")
	public abstract TranslatedDatasetDTO map(DatasetTranslationService.TranslatedDataset translatedDataset);

	@Mapping(source = "entity", target = "entity")
	@Mapping(source = "translation", target = "translation")
	public abstract TranslatedDatasetInfo mapInfo(DatasetTranslationService.TranslatedDataset translatedDataset);

	// @BeanMapping(ignoreByDefault = true)
	// @Mapping(source = "id", target = "id")
	// @Mapping(source = "uuid", target = "uuid")
	// Dataset mapInfo(DatasetInfo datasetDTO);

	public abstract DatasetLocationDTO map(DatasetLocation datasetLocation);

	@Mapping(target = "dataset", ignore = true)
	public abstract DatasetLocation map(DatasetLocationDTO dto);
	
	public abstract DatasetLocationInfo mapInfo(DatasetLocation datasetLocation);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "uuid", target = "uuid")
	public abstract DatasetLocation mapInfo(DatasetLocationInfo datasetLocationDTO);

	// DatasetVersionsDTO map(DatasetVersions datasetVersions);

	// DatasetVersions map(DatasetVersionsDTO datasetVersionsDTO);

	// AccessionAliasDTO map(AccessionAlias accessionAlias);

	// AccessionAlias map(AccessionAliasDTO accessionAliasDTO);

	public abstract AccessionAliasInfo mapInfo(AccessionAlias accessionAlias);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	public abstract AccessionAlias mapInfo(AccessionAliasInfo accessionAliasInfo);

	// AccessionCollectDTO map(AccessionCollect accessionCollect);

	// AccessionCollect map(AccessionCollectDTO accessionCollectDTO);

	public abstract AccessionCollectInfo mapInfo(AccessionCollect accessionCollect);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	public abstract AccessionCollect mapInfo(AccessionCollectInfo accessionCollectInfo);

	@AuditNames
	@Mapping(source = "accessionId.uuid", target = "uuid")
	@Mapping(source = "accessionId.lists", target = "lists")
	@Mapping(source = "accessionId.pdci", target = "pdci")
	@Mapping(source = "accessionId.storage", target = "storage")
	@Mapping(source = "accessionId.duplSite", target = "duplSite")
	@Mapping(source = "accessionId.coll", target = "coll")
	@Mapping(source = "accessionId.aliases", target = "aliases")
	@Mapping(source = "accessionId.remarks", target = "remarks")
	@Mapping(source = "accessionId.breederCode", target = "breederCode")
	@Mapping(source = "accessionId.breederName", target = "breederName")
	@Mapping(source = "accessionId.imageCount", target = "imageCount")
	@Mapping(source = "accessionId.subsetCount", target = "subsetCount")
	@Mapping(source = "accessionId.datasetCount", target = "datasetCount")
	@Mapping(source = "accessionId.longitude", target = "geo.longitude")
	@Mapping(source = "accessionId.latitude", target = "geo.latitude")
	@Mapping(source = "accessionId.elevation", target = "geo.elevation")
	@Mapping(source = "accessionId.coordinateUncertainty", target = "geo.uncertainty")
	@Mapping(source = "accessionId.coordinateDatum", target = "geo.datum")
	@Mapping(source = "accessionId.georeferenceMethod", target = "geo.method")
	@Mapping(target = "geo.referenced", expression = "java(accessionId.getLatitude() != null && accessionId.getLongitude() != null)")
	@Mapping(source = "accessionId.tileIndex", target = "geo.tileIndex")
	@Mapping(source = "accessionId.tileIndex3min", target = "tileIndex3min")
	@Mapping(source = "accessionId.climate", target = "geo.climate")
	public abstract AccessionDTO map(Accession accession);

	@IgnoreAudit
	@Mapping(target = "accessionId.uuid", source = "uuid")
	@Mapping(target = "accessionId.lists", source = "lists")
	@Mapping(target = "accessionId.pdci", source = "pdci")
	@Mapping(target = "accessionId.storage", source = "storage")
	@Mapping(target = "accessionId.duplSite", source = "duplSite")
	@Mapping(target = "accessionId.coll", source = "coll")
	@Mapping(target = "accessionId.aliases", source = "aliases")
	@Mapping(target = "accessionId.remarks", source = "remarks")
	@Mapping(target = "accessionId.breederCode", source = "breederCode")
	@Mapping(target = "accessionId.breederName", source = "breederName")
	@Mapping(target = "accessionId.imageCount", source = "imageCount")
	@Mapping(target = "accessionId.subsetCount", source = "subsetCount")
	@Mapping(target = "accessionId.datasetCount", source = "datasetCount")
	@Mapping(target = "accessionId.longitude", source = "geo.longitude")
	@Mapping(target = "accessionId.latitude", source = "geo.latitude")
	@Mapping(target = "accessionId.elevation", source = "geo.elevation")
	@Mapping(target = "accessionId.coordinateUncertainty", source = "geo.uncertainty")
	@Mapping(target = "accessionId.coordinateDatum", source = "geo.datum")
	@Mapping(target = "accessionId.georeferenceMethod", source = "geo.method")
	@Mapping(target = "accessionId.tileIndex", source = "geo.tileIndex")
	@Mapping(target = "accessionId.tileIndex3min", source = "tileIndex3min")
	@Mapping(target = "accessionId.climate", source = "geo.climate")
	public abstract Accession map(AccessionDTO accessionDTO);

	public abstract AccessionApiService.AccessionDetails map(AccessionService.AccessionDetails details);

	// @InheritConfiguration(name = "mapAccessionDataToDTO")
	// AccessionHistoricDTO map(AccessionHistoric accessionHistoric);

	// @InheritConfiguration(name = "mapAccessionDataFromDTO")
	// AccessionHistoric map(AccessionHistoricDTO accessionHistoricDTO);

	// AccessionIdInfo mapInfo(AccessionId accessionId);

	// @BeanMapping(ignoreByDefault = true)
	// @Mapping(source = "id", target = "id")
	// @Mapping(source = "uuid", target = "uuid")
	// AccessionId mapInfo(AccessionIdInfo accessionIdInfo);

	// @InheritConfiguration(name = "mapAccessionDataToInfo")
	@Mapping(source = "taxonomy.taxonNameHtml", target = "taxonNameHtml")
	public abstract AccessionInfo mapInfo(Accession accession);

	@IgnoreAudit
	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "uuid", target = "accessionId.uuid")
	@Mapping(source = "id", target = "id")
	@Mapping(source = "doi", target = "doi")
	@Mapping(source = "instituteCode", target = "instituteCode")
	@Mapping(source = "genus", target = "genus")
	@Mapping(source = "accessionNumber", target = "accessionNumber")
	public abstract Accession mapInfo(AccessionInfo accessionDTO);

	@IncludePermissions
	public abstract AccessionListInfo mapInfo(AccessionList accessionList);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "uuid", target = "uuid")
	public abstract AccessionList mapInfo(AccessionListInfo accessionListInfo);

	// AccessionRemarkDTO map(AccessionRemark accessionRemark);

	// AccessionRemark map(AccessionRemarkDTO accessionRemarkDTO);

	public abstract AccessionRemarkInfo mapInfo(AccessionRemark accessionRemark);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	public abstract AccessionRemark mapInfo(AccessionRemarkInfo accessionRemarkInfo);

	// AllAccnamesDTO map(AllAccnames allAccnames);

	// AllAccnames map(AllAccnamesDTO allAccnamesDTO);

	// MaterialRequestDTO map(MaterialRequest materialRequest);

	// MaterialRequest map(MaterialRequestDTO materialRequestDTO);

	// MaterialRequestInfo mapInfo(MaterialRequest materialRequest);

	// @BeanMapping(ignoreByDefault = true)
	// @Mapping(source = "id", target = "id")
	// @Mapping(source = "uuid", target = "uuid")
	// MaterialRequest mapInfo(MaterialRequestInfo materialRequestInfo);

	// MaterialSubRequestDTO map(MaterialSubRequest materialSubRequest);

	// MaterialSubRequest map(MaterialSubRequestDTO materialSubRequestDTO);

	// MaterialSubRequestInfo mapInfo(MaterialSubRequest materialSubRequest);

	// @BeanMapping(ignoreByDefault = true)
	// @Mapping(source = "id", target = "id")
	// @Mapping(source = "uuid", target = "uuid")
	// MaterialSubRequest mapInfo(MaterialSubRequestInfo materialSubRequestInfo);

	// PDCIDTO map(PDCI pdci);

	// PDCI map(PDCIDTO pdciDto);

	public abstract PDCIInfo mapInfo(PDCI pdci);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	public abstract PDCI mapInfo(PDCIInfo pdciInfo);

	// PDCIStatisticsDTO map(PDCIStatistics pdciStatistics);

	// PDCIStatistics map(PDCIStatisticsDTO pdciStatisticsDTO);

	// SvalbardDataDTO map(SvalbardData svalbardData);

	// SvalbardData map(SvalbardDataDTO svalbardDataDTO);

	// SvalbardDepositDTO map(SvalbardDeposit svalbardDeposit);

	// SvalbardDeposit map(SvalbardDepositDTO svalbardDepositDTO);

	// Taxonomy2DTO map(Taxonomy2 taxonomy2);

	// Taxonomy2 map(Taxonomy2DTO taxonomy2DTO);


	@Mapping(target = "hybridCode", expression = "java(ts.getTaxonomyGenus() == null ? null : ts.getTaxonomyGenus().getHybridCode())")
	@Mapping(target = "genusName", expression = "java(ts.getTaxonomyGenus() == null ? null : ts.getTaxonomyGenus().getGenusName())")
	@Mapping(target = "specificHybrid", source = "isSpecificHybrid", qualifiedByName = "mapStringYN")
	@Mapping(target = "subspecificHybrid", source = "isSubspecificHybrid", qualifiedByName = "mapStringYN")
	@Mapping(target = "current", expression = "java(ts.getCurrentTaxonomySpecies() != null && Objects.equals(ts.getId(), ts.getCurrentTaxonomySpecies().getId()))")
	public abstract TaxonomySpeciesInfo mapInfo(TaxonomySpecies ts);

	public abstract Taxonomy2Info mapInfo(Taxonomy2 taxonomy2);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	public abstract Taxonomy2 mapInfo(Taxonomy2Info taxonomy2Info);

	// TaxonomyCommonNameDTO map(TaxonomyCommonName taxonomyCommonName);

	// TaxonomyCommonName map(TaxonomyCommonNameDTO taxonomyCommonNameDTO);

	// TaxonomyGenusDTO map(TaxonomyGenus taxonomyGenus);

	// TaxonomyGenus map(TaxonomyGenusDTO taxonomyGenusDTO);

	// TaxonomySpeciesDTO map(TaxonomySpecies taxonomySpecies);

	// TaxonomySpecies map(TaxonomySpeciesDTO taxonomySpeciesDTO);

	// TaxonomySpeciesInfo mapInfo(TaxonomySpecies taxonomySpecies);

	// @BeanMapping(ignoreByDefault = true)
	// @Mapping(source = "id", target = "id")
	// TaxonomySpecies mapInfo(TaxonomySpeciesInfo taxonomySpeciesInfo);

	@AuditNames
	public abstract ActivityPostDTO map(ActivityPost activityPost);

	@IgnoreAudit
	@Mapping(target = "langs", ignore = true)
	public abstract ActivityPost map(ActivityPostDTO activityPostDTO);

	@IgnoreAudit
	@Mapping(source = "entityId", target = "entity.id")
	public abstract ActivityPostLang map(ActivityPostLangDTO dto);

	@Mapping(source = "entity.id", target = "entityId")
	public abstract ActivityPostLangDTO map(ActivityPostLang activityPostLang);

	@Mapping(source = "entity", target = "entity")
	@Mapping(source = "translation", target = "translation")
	public abstract TranslatedActivityPostDTO map(ActivityPostTranslationService.TranslatedActivityPost activityPost);

	@AuditNames
	public abstract ArticleDTO map(Article article);

	@IgnoreAudit
	@Mapping(target = "langs", ignore = true)
	public abstract Article map(ArticleDTO articleDTO);

	@IgnoreAudit
	@Mapping(source = "entityId", target = "entity.id")
	public abstract ArticleLang map(ArticleLangDTO dto);

	@Mapping(source = "entity.id", target = "entityId")
	public abstract ArticleLangDTO map(ArticleLang articleLang);

	@Mapping(source = "entity", target = "entity")
	@Mapping(source = "translation", target = "translation")
	public abstract TranslatedArticleDTO map(ArticleTranslationService.TranslatedArticle translatedArticle);

	// CountryDTO map(Country country);

	// Country map(CountryDTO countryDTO);

	public abstract CountryInfo mapInfo(Country country);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	public abstract Country mapInfo(CountryInfo countryInfo);

	// @IncludePermissions
	// CropDTO map(Crop crop);

	// Crop map(CropDTO cropDTO);

	// CropInfo mapInfo(Crop crop);

	// @BeanMapping(ignoreByDefault = true)
	// @Mapping(source = "id", target = "id")
	// Crop mapInfo(CropInfo cropInfo);

	// DiversityTreeAccessionRefDTO map(DiversityTreeAccessionRef diversityTreeAccessionRef);

	// DiversityTreeAccessionRef map(DiversityTreeAccessionRefDTO dto);

	// DiversityTreeCreatorDTO map(DiversityTreeCreator diversityTreeCreator);

	// DiversityTreeCreator map(DiversityTreeCreatorDTO dto);

	// @IncludePermissions
	// DiversityTreeDTO map(DiversityTree diversityTreeCreator);

	// DiversityTree map(DiversityTreeDTO dto);

	// DiversityTreeInfo mapInfo(DiversityTree diversityTree);

	// @BeanMapping(ignoreByDefault = true)
	// @Mapping(source = "id", target = "id")
	// @Mapping(source = "uuid", target = "uuid")
	// DiversityTree mapInfo(DiversityTreeInfo diversityTreeInfo);

	// DiversityTreeVersionsDTO map(DiversityTreeVersions diversityTreeVersions);

	// DiversityTreeVersions map(DiversityTreeVersionsDTO dto);

	// DownloadLogDTO map(DownloadLog downloadLog);

	// DownloadLog map(DownloadLogDTO dto);

	@IncludePermissions 
	public abstract FaoInstituteDTO map(FaoInstitute faoInstitute);

	public abstract FaoInstitute map(FaoInstituteDTO faoInstituteDTO);

	@Mapping(target = "countryCode3", source = "country.code3")
	public abstract FaoInstituteInfo mapInfo(FaoInstitute faoInstitute);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "code", target = "code")
	public abstract FaoInstitute mapInfo(FaoInstituteInfo faoInstituteInfo);

	public abstract FaoInstituteSettingInfo mapInfo(FaoInstituteSetting faoInstituteSetting);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	public abstract FaoInstituteSetting mapInfo(FaoInstituteSettingInfo faoInstituteSettingDTO);

	// GeoRegionDTO map(GeoRegion geoRegion);

	// GeoRegion map(GeoRegionDTO geoRegionDTO);

	// GeoRegionInfo mapInfo(GeoRegion geoRegion);

	// @BeanMapping(ignoreByDefault = true)
	// @Mapping(source = "id", target = "id")
	// GeoRegion mapInfo(GeoRegionInfo geoRegionInfo);

	// ITPGRFAStatusDTO map(ITPGRFAStatus itpgrfaStatus);

	// ITPGRFAStatus map(ITPGRFAStatusDTO itpgrfaStatusDTO);

	// LicenseDTO map(License license);

	// License map(LicenseDTO licenseDTO);

	public abstract MenuDTO map(Menu menu);

	// Menu map(MenuDTO menuDTO);

	public abstract MenuInfo mapInfo(Menu menu);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	public abstract Menu mapInfo(MenuInfo menuInfo);

	@AuditNames
	public abstract MenuItemDTO map(MenuItem menu);

	@IgnoreAudit
	@Mapping(target = "langs", ignore = true)
	public abstract MenuItem map(MenuItemDTO menuDTO);

	@IgnoreAudit
	@Mapping(source = "entityId", target = "entity.id")
	public abstract MenuItemLang map(MenuItemLangDTO dto);

	@Mapping(source = "entity.id", target = "entityId")
	public abstract MenuItemLangDTO map(MenuItemLang menuItemLang);

	@Mapping(source = "entity", target = "entity")
	@Mapping(source = "translation", target = "translation")
	public abstract TranslatedMenuItemDTO map(MenuItemTranslationService.TranslatedMenuItem translatedMenuItem);

	// MenuItemInfo mapInfo(MenuItem menu);

	// @BeanMapping(ignoreByDefault = true)
	// @Mapping(source = "id", target = "id")
	// MenuItem mapInfo(MenuItemInfo menuItemInfo);

	public abstract PGRFANetworkInfo mapInfo(PGRFANetwork pgrfaNetwork);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	public abstract PGRFANetwork mapInfo(PGRFANetworkInfo info);

	// @IncludePermissions
	// ProjectDTO map(Project project);

	// Project map(ProjectDTO projectDTO);

	public abstract SubsetAccessionRefDTO map(SubsetAccessionRef project);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(target = "doi", source = "doi")
	@Mapping(target = "instCode", source = "instCode")
	@Mapping(target = "acceNumb", source = "acceNumb")
	@Mapping(target = "genus", source = "genus")
	@Mapping(target = "species", source = "species")
	@Mapping(target = "accession", source = "accession")
	public abstract SubsetAccessionRef map(SubsetAccessionRefDTO projectDTO);

	public abstract SubsetCreatorDTO map(SubsetCreator subsetCreator);

	@IgnoreAudit
	@Mapping(target = "subset", ignore = true)
	public abstract SubsetCreator map(SubsetCreatorDTO subsetCreatorDTO);

	@AuditNames
	@IncludePermissions
	@Mapping(source = "wiewsCode", target = "instituteCode")
	public abstract SubsetDTO map(Subset subset);

	@IgnoreAudit
	@Mapping(source = "instituteCode", target = "wiewsCode")
	@Mapping(target = "langs", ignore = true)
	@Mapping(target = "versions", ignore = true)
	@Mapping(target = "accessionRefs", ignore = true)
	public abstract Subset map(SubsetDTO subsetDTO);

	@Mapping(source = "wiewsCode", target = "instituteCode")
	public abstract SubsetInfo mapInfo(Subset subset);

	@IgnoreAudit
	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "uuid", target = "uuid")
	public abstract Subset mapInfo(SubsetInfo subsetInfo);

	public abstract SubsetVersionsDTO map(SubsetVersions subsetVersions);

	public abstract SubsetVersions map(SubsetVersionsDTO subsetVersionsDTO);

	@Mapping(source = "entity", target = "entity")
	@Mapping(source = "translation", target = "translation")
	@Mapping(source = "entity", target = "entity._permissions", qualifiedByName = "getPermissions")
	@Mapping(source = "entity.wiewsCode", target = "entity.instituteCode")
	public abstract TranslatedSubsetDTO map(SubsetTranslationService.TranslatedSubset dto);

	@IgnoreAudit
	@Mapping(source = "entityId", target = "entity.id")
	public abstract SubsetLang map(SubsetLangDTO dto);

	@Mapping(source = "entity.id", target = "entityId")
	public abstract SubsetLangDTO map(SubsetLang subsetLang);

	public abstract TileClimateInfo mapInfo(TileClimate tileClimate);

	// UserDTO map(User user);

	// User map(UserDTO userDTO);

	// VerificationTokenDTO map(VerificationToken verificationToken);

	// VerificationToken map(VerificationTokenDTO verificationTokenDTO);

	// BooleanDimensionDTO map(BooleanDimension booleanDimension);

	// BooleanDimension map(BooleanDimensionDTO booleanDimensionDTO);

	// StringListDimensionDTO map(StringListDimension stringListDimension);

	// StringListDimension map(StringListDimensionDTO stringListDimensionDTO);

	// JpaDimensionDTO map(JpaDimension jpaDimension);

	// JpaDimension map(JpaDimensionDTO jpaDimensionDTO);

	// NumericListDimensionDTO map(NumericListDimension numericListDimension);

	// @Mapping(target = "javaType", ignore = true)
	// NumericListDimension map(NumericListDimensionDTO numericListDimensionDTO);

	// DimensionKeyDTO map(DimensionKey dimensionKey);

	// DimensionKey map(DimensionKeyDTO dimensionKeyDTO);

	// ExecutionDimensionDTO map(ExecutionDimension executionDimension);

	// ExecutionDimension map(ExecutionDimensionDTO executionDimensionDTO);

	// @IncludePermissions
	// ExecutionDTO map(Execution execution);

	// Execution map(ExecutionDTO executionDTO);

	// ExecutionGroupDTO map(ExecutionGroup executionGroup);

	// ExecutionGroup map(ExecutionGroupDTO executionGroupDTO);

	// ExecutionRunDTO map(ExecutionRun executionRun);

	// ExecutionRun map(ExecutionRunDTO executionRunDTO);

	// KPIParameterDTO map(KPIParameter kpiParameter);

	// KPIParameter map(KPIParameterDTO kpiParameterDTO);

	// ObservationDTO map(Observation observation);

	// Observation map(ObservationDTO observationDTO);

	@IncludePermissions
	@AuditNames
	public abstract DescriptorDTO map(Descriptor descriptor);

	@IgnoreAudit
	@Mapping(target = "langs", ignore = true)
	@Mapping(target = "datasets", ignore = true)
	@Mapping(target = "descriptorLists", ignore = true)
	@Mapping(target = "apply", ignore = true)
	public abstract Descriptor map(DescriptorDTO descriptorDTO);

	public abstract DescriptorInfo mapInfo(Descriptor descriptor);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "uuid", target = "uuid")
	public abstract Descriptor mapInfo(DescriptorInfo descriptorInfo);

	@IgnoreAudit
	@Mapping(source = "entityId", target = "entity.id")
	public abstract DescriptorLang map(DescriptorLangDTO dto);

	@Mapping(source = "entity.id", target = "entityId")
	@Mapping(target = "terms", ignore = true)
	public abstract DescriptorLangDTO map(DescriptorLang subsetLang);

	@Mapping(source = "entity", target = "entity")
	@Mapping(source = "translation", target = "translation")
	@Mapping(source = "entity", target = "entity._permissions", qualifiedByName = "getPermissions")
	public abstract TranslatedDescriptorDTO map(DescriptorTranslationService.TranslatedDescriptor translatedDescriptor);

	@Mapping(source = "entity", target = "entity")
	@Mapping(source = "translation", target = "translation")
	public abstract TranslatedDescriptorInfo mapInfo(DescriptorTranslationService.TranslatedDescriptor translatedDescriptor);

	@IncludePermissions
	@AuditNames
	public abstract DescriptorListDTO map(DescriptorList descriptorList);

	@IgnoreAudit
	@Mapping(target = "langs", ignore = true)
	@Mapping(target = "descriptors", ignore = true)
	public abstract DescriptorList map(DescriptorListDTO descriptorListDTO);

	@IgnoreAudit
	@Mapping(source = "entityId", target = "entity.id")
	public abstract DescriptorListLang map(DescriptorListLangDTO dto);

	@Mapping(source = "entity.id", target = "entityId")
	public abstract DescriptorListLangDTO map(DescriptorListLang subsetLang);

	@Mapping(source = "entity", target = "entity")
	@Mapping(source = "translation", target = "translation")
	@Mapping(source = "entity", target = "entity._permissions", qualifiedByName = "getPermissions")
	public abstract TranslatedDescriptorListDTO map(DescriptorListTranslationService.TranslatedDescriptorList translatedDescriptorList);

	public abstract DescriptorListInfo mapInfo(DescriptorList descriptorList);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "uuid", target = "uuid")
	public abstract DescriptorList mapInfo(DescriptorListInfo descriptorListInfo);

	// @IncludePermissions
	// ControlledVocabularyDTO map(ControlledVocabulary controlledVocabulary);

	// ControlledVocabulary map(ControlledVocabularyDTO controlledVocabularyDTO);

	public abstract ControlledVocabularyInfo mapInfo(ControlledVocabulary controlledVocabulary);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "uuid", target = "uuid")
	public abstract ControlledVocabulary mapInfo(ControlledVocabularyInfo controlledVocabularyInfo);

	public abstract VocabularyTermDTO map(VocabularyTerm vocabularyTerm);

	@Mapping(target = "langs", ignore = true)
	@Mapping(target = "descriptor", ignore = true)
	@Mapping(target = "vocabulary", ignore = true)
	public abstract VocabularyTerm map(VocabularyTermDTO vocabularyTermDTO);

	public abstract VocabularyTermInfo mapInfo(VocabularyTerm vocabularyTerm);

	@Mapping(target = "langs", ignore = true)
	@Mapping(target = "descriptor", ignore = true)
	@Mapping(target = "vocabulary", ignore = true)
	public abstract VocabularyTerm mapInfo(VocabularyTermInfo vocabularyTermInfo);

	@IgnoreAudit
	@Mapping(source = "entityId", target = "entity.id")
	public abstract VocabularyTermLang map(VocabularyTermLangDTO dto);

	@Mapping(source = "entity.id", target = "entityId")
	public abstract VocabularyTermLangDTO map(VocabularyTermLang subsetLang);

	@Mapping(source = "entity", target = "entity")
	@Mapping(source = "translation", target = "translation")
	public abstract TranslatedVocabularyTermDTO map(VocabularyTermTranslationService.TranslatedVocabularyTerm translatedVocabularyTerm);

	// AclSidDTO map(AclSid aclSid);

	// AclSid map(AclSidDTO aclSidDTO);

	// ClassPKDTO map(ClassPK classPK);

	// ClassPK map(ClassPKDTO classPKDTO);

	public abstract ClassPKInfo mapInfo(ClassPK classPK);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	public abstract ClassPK mapInfo(ClassPKInfo info);

	@IncludePermissions
	@AuditNames
	public abstract PartnerDTO map(Partner partner);

	@IgnorePermissions
	@IgnoreAudit
	@Mapping(target = "urls", ignore = true)
	public abstract PartnerDTO mapNoAudit(Partner partner);

	@IgnoreAudit
	public abstract Partner map(PartnerDTO partnerDTO);

	public abstract PartnerInfo mapInfo(Partner partner);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "uuid", target = "uuid")
	public abstract Partner mapInfo(PartnerInfo partnerInfo);

	@Mapping(source = "details.id", target = "id")
	@Mapping(source = "details.active", target = "active")
	@Mapping(source = "details.version", target = "version")
	@Mapping(source = "details.uuid", target = "uuid")
	@Mapping(source = "details.shortName", target = "shortName")
	@Mapping(source = "details.name", target = "name")
	@Mapping(source = "details.description", target = "description")
	@Mapping(source = "details.email", target = "email")
	@Mapping(source = "details.phone", target = "phone")
	@Mapping(source = "details.address", target = "address")
	@Mapping(source = "details.urls", target = "urls")
	@Mapping(source = "details.countryCodes", target = "countryCodes")
	@Mapping(source = "details.createdBy", target = "createdBy", qualifiedByName = "getAclSid")
	@Mapping(source = "details.createdDate", target = "createdDate")
	@Mapping(source = "details.lastModifiedBy", target = "lastModifiedBy", qualifiedByName = "getAclSid")
	@Mapping(source = "details.lastModifiedDate", target = "lastModifiedDate")
	@Mapping(source = "details", target = "_permissions", qualifiedByName = "getPermissions")
	public abstract PartnerApiService.PartnerDetails map(PartnerService.PartnerDetails details);

	@IncludePermissions
	public abstract ImageGalleryDTO map(ImageGallery imageGallery);

	@Mapping(target = "apply", ignore = true)
	public abstract ImageGallery map(ImageGalleryDTO imageGalleryDTO);

	@IncludePermissions
	@SubclassMapping(target = RepositoryImageDTO.class, source = RepositoryImage.class)
	public abstract RepositoryFileDTO map(RepositoryFile repositoryFile);

	@SubclassMapping(target = RepositoryImage.class, source = RepositoryImageDTO.class)
	@Mapping(target = "apply", ignore = true)
	public abstract RepositoryFile map(RepositoryFileDTO repositoryFileDTO);

	@IsPublic
	public abstract RepositoryFileInfo mapInfo(RepositoryFile repositoryFile);

	@IncludePermissions
	public abstract RepositoryFolderDTO map(RepositoryFolder repositoryFolder);

	@Mapping(target = "files", ignore = true)
	@Mapping(target = "folderPath", ignore = true)
	@Mapping(target = "gallery", ignore = true)
	@Mapping(target = "parent", ignore = true)
	@Mapping(target = "parentOid", ignore = true)
	public abstract RepositoryFolder map(RepositoryFolderDTO repositoryFolderDTO) throws InvalidRepositoryPathException;

	public abstract RepositoryFolderInfo mapInfo(RepositoryFolder repositoryFolder);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "uuid", target = "uuid")
	public abstract RepositoryFolder mapInfo(RepositoryFolderInfo repositoryFolderInfo) throws InvalidRepositoryPathException;

	@IncludePermissions
	public abstract RepositoryImageDTO map(RepositoryImage repositoryImage);

	@Mapping(target = "apply", ignore = true)
	public abstract RepositoryImage map(RepositoryImageDTO repositoryImageDTO);

	@IsPublic
	public abstract RepositoryImageInfo mapInfo(RepositoryImage repositoryImage);

	@IgnoreAudit
	@BeanMapping(ignoreByDefault = true)
	@Mapping(source = "id", target = "id")
	@Mapping(source = "uuid", target = "uuid")
	public abstract RepositoryImage mapInfo(RepositoryImageInfo repositoryImageInfo);

	@IgnoreAudit
	public abstract Citation map(CitationDTO dto);

	@AuditNames
	public abstract CitationDTO map(Citation citation);

	public abstract CitationInfo mapInfo(Citation citation);

	@BeanMapping(ignoreByDefault = true)
	@Mapping(target = "id", source = "id")
	public abstract Citation mapInfo(CitationInfo citation);

	public abstract Author map(AuthorDTO dto);

	public abstract AuthorDTO map(Author citation);

	@AuditNames
	public abstract CropDTO map(Crop crop);

	@IgnoreAudit
	@Mapping(target = "langs", ignore =  true)
	public abstract Crop map(CropDTO articleDTO);

	@IgnoreAudit
	@Mapping(source = "entityId", target = "entity.id")
	public abstract CropLang map(CropLangDTO dto);

	@Mapping(source = "entity.id", target = "entityId")
	public abstract CropLangDTO map(CropLang articleLang);

	@Mapping(source = "entity", target = "entity")
	@Mapping(source = "translation", target = "translation")
	public abstract TranslatedCropDTO map(CropTranslationService.TranslatedCrop translatedCrop);

	public abstract CropDetailsDTO map(CropService.CropDetails crop);

	@Mapping(target = "id", source = "crop.entity.id")
	@Mapping(target = "shortName", source = "crop.entity.shortName")
	@Mapping(target = "name", source = "crop.entity.name")
	@Mapping(target = "annex1", source = "crop.entity.annex1")
	@Mapping(target = "title", source = "crop.translation.title")
	@Mapping(target = "description", source = "crop.translation.description")
	@Mapping(target = "images", source = "imageGallery.images")
	public abstract CropInfo mapInfo(CropService.CropDetails crop);
}