Commit c8853b82 authored by PECQUOT's avatar PECQUOT
Browse files

git-svn-id: https://scmforge.ifremer.fr/authscm/lp1ee9d/svn/reefdb/trunk@1876 cd918a83-917d-4a2a-92d7-bc1d03929fc5
parent d71fbd51
......@@ -33,6 +33,7 @@ import fr.ifremer.reefdb.config.ReefDbConfiguration;
import fr.ifremer.reefdb.dao.Daos;
import fr.ifremer.reefdb.dao.referential.ReefDbReferentialDao;
import fr.ifremer.reefdb.dto.ReefDbBeanFactory;
import fr.ifremer.reefdb.dto.ReefDbBeans;
import fr.ifremer.reefdb.dto.data.photo.PhotoDTO;
import fr.ifremer.reefdb.dto.data.sampling.SamplingOperationDTO;
import fr.ifremer.reefdb.service.ReefDbTechnicalException;
......@@ -97,12 +98,28 @@ public class ReefDbPhotoDaoImpl extends PhotoDaoImpl implements ReefDbPhotoDao {
Survey survey = get(SurveyImpl.class, surveyId);
List<Integer> existingPhotosIds = ReefDbBeans.collectIds(getPhotosBySurveyId(surveyId));
for (PhotoDTO source : photos) {
// remove from existing
if (source.getId() != null) {
existingPhotosIds.remove(source.getId());
}
// save if dirty
if (source.isDirty()) {
savePhotoInSurvey(source, survey);
source.setDirty(false);
}
}
// remove the not saved
if (CollectionUtils.isNotEmpty(existingPhotosIds)) {
for (Integer idToRemove : existingPhotosIds) {
remove(idToRemove);
}
}
}
......@@ -150,19 +167,42 @@ public class ReefDbPhotoDaoImpl extends PhotoDaoImpl implements ReefDbPhotoDao {
if (!targetFilePath.equals(photo.getPath())) {
// if file path differs, seems to be a new file to copy or replace
File sourceFile = new File(photo.getPath());
boolean move = false;
// if the source file doesn't exists, it could be a already stored photo in db attachment directory
if (!sourceFile.exists() || !sourceFile.isAbsolute()) {
sourceFile = new File(config.getDbAttachmentDirectory(), photo.getPath());
if (sourceFile.exists()) {
// a move will be performed instead of a copy
move = true;
// the other files should be deleted
ImageUtils.deleteOtherImage(sourceFile);
}
}
File targetFile = new File(config.getDbAttachmentDirectory(), targetFilePath);
if (targetFile.exists()) {
// TODO if it's not possible, throw an exception
targetFile.delete();
}
try {
// copy file
FileUtils.copyFile(sourceFile, targetFile);
if (move) {
// move existing file
FileUtils.moveFile(sourceFile, targetFile);
} else {
// copy new file
FileUtils.copyFile(sourceFile, targetFile);
}
} catch (IOException ex) {
throw new ReefDbTechnicalException(ex);
}
// prepare new image
ImageUtils.prepareImageFile(targetFile);
// update bean
photo.setPath(targetFilePath);
photo.setTempPath(targetFile.getAbsolutePath());
}
// update photo link if differs
......
......@@ -30,6 +30,8 @@ import fr.ifremer.quadrige2.core.dao.referential.StatusImpl;
import fr.ifremer.quadrige2.core.dao.referential.TaxonGroupTypeImpl;
import fr.ifremer.quadrige2.core.dao.referential.taxon.TaxonGroup;
import fr.ifremer.quadrige2.core.dao.referential.taxon.TaxonGroupDaoImpl;
import fr.ifremer.quadrige2.core.dao.referential.taxon.TaxonGroupHistoricalRecord;
import fr.ifremer.quadrige2.core.dao.referential.taxon.TaxonNameImpl;
import fr.ifremer.quadrige2.core.dao.technical.hibernate.TemporaryDataHelper;
import fr.ifremer.quadrige2.core.service.technical.CacheService;
import fr.ifremer.reefdb.dao.Daos;
......@@ -52,6 +54,7 @@ import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.*;
@Repository("reefDbTaxonGroupDao")
public class ReefDbTaxonGroupDaoImpl extends TaxonGroupDaoImpl implements ReefDbTaxonGroupDao {
......@@ -259,7 +262,7 @@ public class ReefDbTaxonGroupDaoImpl extends TaxonGroupDaoImpl implements ReefDb
// Mantis #0027042: when parentTaxonGroupId is set, do a recursive search to populate sub groups
if (CollectionUtils.isNotEmpty(result) && parentTaxonGroupId != null) {
Set<TaxonGroupDTO> subTaxonGroups = Sets.newHashSet();
for (TaxonGroupDTO taxonGroup: result) {
for (TaxonGroupDTO taxonGroup : result) {
// populate sub groups
subTaxonGroups.addAll(findTaxonGroups(taxonGroup.getId(), label, name, isStrictName, statusCodes));
}
......@@ -369,6 +372,55 @@ public class ReefDbTaxonGroupDaoImpl extends TaxonGroupDaoImpl implements ReefDb
getSession().save(target);
taxonGroup.setId(target.getTaxonGroupId());
// taxons
saveTaxonsInTaxonGroup(taxonGroup, target);
}
private void saveTaxonsInTaxonGroup(TaxonGroupDTO source, TaxonGroup target) {
Collection<TaxonGroupHistoricalRecord> existingTaxonGroupHistoricalRecords = target.getTaxonGroupHistoricalRecords();
Map<Integer, TaxonGroupHistoricalRecord> tghrByTaxonId = ReefDbBeans.splitByProperty(existingTaxonGroupHistoricalRecords, "taxonName.taxonNameId");
boolean needUpdate = false;
for (TaxonDTO taxon : source.getTaxons()) {
TaxonGroupHistoricalRecord tghr = tghrByTaxonId.remove(taxon.getId());
if (tghr == null) {
tghr = TaxonGroupHistoricalRecord.Factory.newInstance();
tghr.setTaxonGroupHistRecordId((Integer) TemporaryDataHelper.getNewNegativeIdForTemporaryData(getSession(), TaxonGroupHistoricalRecord.class));
tghr.setTaxonName(load(TaxonNameImpl.class, taxon.getId()));
tghr.setTaxonGroup(target);
getSession().save(tghr);
target.addTaxonGroupHistoricalRecords(tghr);
needUpdate = true;
}
}
if (!tghrByTaxonId.isEmpty()) {
// remove remaining
for (TaxonGroupHistoricalRecord tghrToRemove : tghrByTaxonId.values()) {
target.removeTaxonGroupHistoricalRecords(tghrToRemove);
getSession().delete(tghrToRemove);
}
needUpdate = true;
}
if (needUpdate) {
update(target);
// get all taxon names map
Multimap<Integer, TaxonDTO> taxonMap = taxonNameDao.getAllTaxonNamesMapByTaxonGroupId();
taxonMap.replaceValues(source.getId(), source.getTaxons());
// update taxonNameByTaxonGroupId cache
Cache taxonNameByTaxonGroupIdCache = cacheService.getCache(ReefDbTaxonNameDao.TAXON_NAME_BY_TAXON_GROUP_ID_CACHE);
taxonNameByTaxonGroupIdCache.evict(SimpleKey.EMPTY);
taxonNameByTaxonGroupIdCache.put(SimpleKey.EMPTY, taxonMap);
}
}
private TaxonGroupDTO toTaxonGroupDTO(Iterator<Object> source) {
......
......@@ -31,6 +31,8 @@ import org.nuiton.decorator.Decorator;
*/
public interface DecoratorService extends fr.ifremer.quadrige2.core.service.decorator.DecoratorService {
String COLLECTION_SIZE = "collectionSize";
String WITH_SYMBOL = "withSymbol";
String WITH_CITATION = "withCitation";
......
......@@ -51,6 +51,7 @@ import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
......@@ -133,9 +134,12 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
provider.registerDecorator(SynchronizationStatusDTO.class, "${name}$s", TOKEN_SEPARATOR, SEPARATOR);
provider.registerDecorator(SearchDateDTO.class, "${name}$s", TOKEN_SEPARATOR, SEPARATOR);
// synchro
provider.registerDecorator(new SynchroTableWithCountDecorator());
provider.registerDecorator(WITH_COUNT, new SynchroTableWithCountDecorator(WITH_COUNT));
// misc
provider.registerDecorator(COLLECTION_SIZE, new CollectionSizeDecorator());
provider.registerDecorator(DURATION_IN_MINUTES, new DurationDecorator(DURATION_IN_MINUTES));
provider.registerDecorator(DURATION_IN_DECIMAL_HOURS, new DurationDecorator(DURATION_IN_DECIMAL_HOURS));
provider.registerDecorator(TIME_IN_HOURS_MINUTES, new TimeDecorator());
......@@ -150,9 +154,9 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
});
}
public class TaxonWithCitationDecorator extends Decorator<TaxonDTO> {
private class TaxonWithCitationDecorator extends Decorator<TaxonDTO> {
protected TaxonWithCitationDecorator() {
TaxonWithCitationDecorator() {
super(TaxonDTO.class, "${name}$s#${citation}$s", TOKEN_SEPARATOR, " ", false);
}
......@@ -174,19 +178,19 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
}
}
public class PMFMNameDecorator extends Decorator<PmfmDTO> {
class PMFMNameDecorator extends Decorator<PmfmDTO> {
protected static final String TOKEN_NAME = "name";
static final String TOKEN_NAME = "name";
protected PMFMNameDecorator() {
PMFMNameDecorator() {
this("${" + TOKEN_NAME + "}$s");
}
protected PMFMNameDecorator(String expression) {
PMFMNameDecorator(String expression) {
this(expression, SEPARATOR);
}
public PMFMNameDecorator(String expression, String separatorReplacement) {
PMFMNameDecorator(String expression, String separatorReplacement) {
super(PmfmDTO.class, expression, TOKEN_SEPARATOR, separatorReplacement, true);
}
......@@ -207,21 +211,21 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
}
}
public class PMFMDecorator extends PMFMNameDecorator {
private class PMFMDecorator extends PMFMNameDecorator {
protected PMFMDecorator() {
PMFMDecorator() {
super("${" + TOKEN_NAME + "}$s#${parameter/code}$s#${matrix/name}$s#${fraction/name}$s#${method/name}$s#${unit/symbol}$s");
}
}
public class PMFMExtractionDecorator extends PMFMNameDecorator {
private class PMFMExtractionDecorator extends PMFMNameDecorator {
static final String SEPARATOR = "-";
static final String TOKEN_UNIT = "unit/name";
List<Integer> unitIdsToIgnore;
boolean checkConfig = false;
protected PMFMExtractionDecorator() {
PMFMExtractionDecorator() {
super("${" + TOKEN_NAME + "}$s#${" + TOKEN_UNIT + "}$s", SEPARATOR);
}
......@@ -268,12 +272,12 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
}
}
public class PMFMNameWithUnitDecorator extends PMFMNameDecorator {
private class PMFMNameWithUnitDecorator extends PMFMNameDecorator {
int noUnitId;
boolean checkConfig = false;
protected PMFMNameWithUnitDecorator() {
PMFMNameWithUnitDecorator() {
super("${" + TOKEN_NAME + "}$s#${unit/symbol}$s", "");
}
......@@ -303,14 +307,14 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
/**
* Survey decorator.
*/
public class LightSurveyVODecorator extends Decorator<LightSurveyVO> {
private class LightSurveyVODecorator extends Decorator<LightSurveyVO> {
private static final String SEPARATOR = " - ";
/**
* Constructor.
*/
public LightSurveyVODecorator() {
LightSurveyVODecorator() {
super(LightSurveyVO.class, "${surveyId}$s", "", "", false);
}
......@@ -343,16 +347,16 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
}
/**
* Prelevement decorator.
* Sampling Operation decorator.
*/
public class SamplingOperationDecorator extends Decorator<SamplingOperationDTO> {
private class SamplingOperationDecorator extends Decorator<SamplingOperationDTO> {
private static final String SEPARATOR = " - ";
/**
* Constructor.
*/
public SamplingOperationDecorator() {
SamplingOperationDecorator() {
super(SamplingOperationDTO.class, "${name}$s", "", "", false);
}
......@@ -368,11 +372,11 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
}
/**
* Decorateur pour heures.
* Time decoration.
*/
public class TimeDecorator extends Decorator<Double> {
private class TimeDecorator extends Decorator<Double> {
protected TimeDecorator() {
TimeDecorator() {
super(Double.class, "${time}$s", "", "", false);
}
......@@ -385,7 +389,7 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
/**
* Decorator display duration (Integer representing number of minutes) to days/hours/minutes readable format
*/
public class DurationDecorator extends Decorator<Number> {
private class DurationDecorator extends Decorator<Number> {
private final String type;
......@@ -404,7 +408,7 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
int duration = 0;
switch (type) {
case DURATION_IN_MINUTES:
// statndard case (number should be an Integer)
// standard case (number should be an Integer)
duration = number.intValue();
break;
......@@ -443,17 +447,17 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
}
}
public class SynchroTableWithCountDecorator extends Decorator<SynchroTableDTO> {
private class SynchroTableWithCountDecorator extends Decorator<SynchroTableDTO> {
private final String type;
public SynchroTableWithCountDecorator(String type) {
SynchroTableWithCountDecorator(String type) {
super(SynchroTableDTO.class, "${name}$s", "", "", false);
this.type = type;
Preconditions.checkArgument(type == null || type.equals(WITH_COUNT), "unknown type for this decorator. Expected: null or 'withCount'");
}
public SynchroTableWithCountDecorator() {
SynchroTableWithCountDecorator() {
super(SynchroTableDTO.class, "${name}$s", "", "", false);
this.type = null;
}
......@@ -482,4 +486,23 @@ public class DecoratorServiceImpl extends fr.ifremer.quadrige2.core.service.deco
}
// Decorator for collection of BaseReferentialDTO
private class CollectionSizeDecorator extends Decorator<BaseReferentialDTO> {
CollectionSizeDecorator() {
super(BaseReferentialDTO.class, "${size}$s", "", "", false);
}
@Override
public String toString(Object bean) {
// return directly the collection size
if (bean instanceof Collection) {
Collection collection = (Collection) bean;
return String.valueOf(collection.size());
}
return "";
}
}
}
......@@ -762,62 +762,74 @@ public class ReefDbBeans {
}
}
public static List<String> getErrorMessages(ErrorAware bean, String propertyName, Integer pmfmId) {
List<String> messages = Lists.newArrayList();
if (bean != null && CollectionUtils.isNotEmpty(bean.getErrors())) {
for (ErrorDTO error : bean.getErrors()) {
if (error.isError()
&& Objects.equals(error.getPropertyName(), propertyName)
&& Objects.equals(error.getPmfmId(), pmfmId)) {
messages.add(error.getMessage());
}
}
public static List<ErrorDTO> getErrors(ErrorAware bean) {
if (bean == null || CollectionUtils.isEmpty(bean.getErrors())) {
return new ArrayList<>();
}
return messages;
return filterCollection(bean.getErrors(), new Predicate<ErrorDTO>() {
@Override
public boolean apply(ErrorDTO error) {
return error.isError();
}
});
}
public static List<String> getErrorMessages(ErrorAware bean) {
List<String> messages = Lists.newArrayList();
if (bean != null && CollectionUtils.isNotEmpty(bean.getErrors())) {
for (ErrorDTO error : bean.getErrors()) {
if (error.isError()) {
messages.add(error.getMessage());
}
}
}
return messages;
return collectProperties(getErrors(bean), ErrorDTO.PROPERTY_MESSAGE);
}
public static List<String> getWarningMessages(ErrorAware bean, String propertyName, Integer pmfmId) {
List<String> messages = Lists.newArrayList();
if (bean != null && CollectionUtils.isNotEmpty(bean.getErrors())) {
for (ErrorDTO error : bean.getErrors()) {
if (Objects.equals(error.getPropertyName(), propertyName)
&& Objects.equals(error.getPmfmId(), pmfmId)) {
if (error.isWarning()) {
// add warning message
messages.add(error.getMessage());
} else if (error.isError()) {
// if an error is found, return empty list because error in priority
return Lists.newArrayList();
}
}
public static List<ErrorDTO> getErrors(ErrorAware bean, final String propertyName, final Integer pmfmId) {
if (bean == null || CollectionUtils.isEmpty(bean.getErrors())) {
return new ArrayList<>();
}
return filterCollection(bean.getErrors(), new Predicate<ErrorDTO>() {
@Override
public boolean apply(ErrorDTO error) {
return error.isError()
&& error.containsPropertyName(propertyName)
&& (pmfmId == null || pmfmId.equals(error.getPmfmId()));
}
});
}
public static List<String> getErrorMessages(ErrorAware bean, String propertyName, Integer pmfmId) {
return collectProperties(getErrors(bean, propertyName, pmfmId), ErrorDTO.PROPERTY_MESSAGE);
}
public static List<ErrorDTO> getWarnings(ErrorAware bean) {
if (bean == null || CollectionUtils.isEmpty(bean.getErrors())) {
return new ArrayList<>();
}
return messages;
return filterCollection(bean.getErrors(), new Predicate<ErrorDTO>() {
@Override
public boolean apply(ErrorDTO error) {
return error.isWarning();
}
});
}
public static List<String> getWarningMessages(ErrorAware bean) {
List<String> messages = Lists.newArrayList();
if (bean != null && CollectionUtils.isNotEmpty(bean.getErrors())) {
for (ErrorDTO error : bean.getErrors()) {
if (error.isWarning()) {
// add warning message
messages.add(error.getMessage());
}
}
return collectProperties(getWarnings(bean), ErrorDTO.PROPERTY_MESSAGE);
}
public static List<ErrorDTO> getWarnings(ErrorAware bean, final String propertyName, final Integer pmfmId) {
if (bean == null || CollectionUtils.isEmpty(bean.getErrors())
// if an error is found, return empty list because error is priority
|| !getErrors(bean, propertyName, pmfmId).isEmpty()) {
return new ArrayList<>();
}
return messages;
return filterCollection(bean.getErrors(), new Predicate<ErrorDTO>() {
@Override
public boolean apply(ErrorDTO error) {
return error.isWarning()
&& error.containsPropertyName(propertyName)
&& (pmfmId == null || pmfmId.equals(error.getPmfmId()));
}
});
}
public static List<String> getWarningMessages(ErrorAware bean, String propertyName, Integer pmfmId) {
return collectProperties(getWarnings(bean, propertyName, pmfmId), ErrorDTO.PROPERTY_MESSAGE);
}
public static void addUniqueErrors(ErrorAware bean, Collection<ErrorDTO> errors) {
......@@ -844,7 +856,7 @@ public class ReefDbBeans {
&& error1.isWarning() == error2.isWarning()
&& error1.isControl() == error2.isControl()
&& Objects.equals(error1.getControlElementCode(), error2.getControlElementCode())
&& Objects.equals(error1.getPropertyName(), error2.getPropertyName())
&& Objects.deepEquals(error1.getPropertyName().toArray(), error2.getPropertyName().toArray())
&& Objects.equals(error1.getPmfmId(), error2.getPmfmId())
&& Objects.equals(error1.getIndividualId(), error2.getIndividualId())
&& Objects.equals(error1.getMessage(), error2.getMessage());
......
......@@ -128,15 +128,6 @@ public interface ObservationService {
@PreAuthorize("hasPermission(null, T(fr.ifremer.reefdb.security.ReefDbAuthority).USER)")
List<MeasurementDTO> duplicateMeasurements(List<MeasurementDTO> measurements);
/**
* Delete photos.
*
* @param idsPhoto Photos to delete
*/
@Transactional(readOnly = false)
@PreAuthorize("hasPermission(null, T(fr.ifremer.reefdb.security.ReefDbAuthority).USER)")
void deletePhotos(List<Integer> idsPhoto);
List<ProgramDTO> getAvailablePrograms(Integer campaignId, Integer locationId, Date date, boolean forceNoContext);
// Mantis #0027030 Remove campaigns
......
......@@ -345,13 +345,6 @@ public class ObservationServiceImpl implements ObservationService {
}
}
@Override
public void deletePhotos(List<Integer> idsPhoto) {
for (Integer photoId : ReefDbBeans.getSetWithoutNull(idsPhoto)) {
photoDao.remove(photoId);
}
}
@Override
public SurveyDTO duplicateSurvey(SurveyDTO survey, boolean fullDuplication, boolean copyCoordinates) {
......
......@@ -282,89 +282,89 @@ public class RulesControlServiceImpl implements RulesControlService {
switch (enumValue) {
case CAMPAIGN:
messages.getValidObject(survey.getCampaign(), rule, error);
error.setPropertyName(SurveyDTO.PROPERTY_CAMPAIGN);
error.addPropertyName(SurveyDTO.PROPERTY_CAMPAIGN);
break;
case LOCATION:
messages.getValidObject(survey.getLocation(), rule, error);
error.setPropertyName(SurveyDTO.PROPERTY_LOCATION);
error.addPropertyName(SurveyDTO.PROPERTY_LOCATION);
break;
case PROGRAM:
messages.getValidObject(survey.getProgram(), rule, error);
error.setPropertyName(SurveyDTO.PROPERTY_PROGRAM);
error.addPropertyName(SurveyDTO.PROPERTY_PROGRAM);
break;
case QUALIFICATION_COMMENT:
messages.getValidString(survey.getQualificationComment(), rule, error);
error.setPropertyName(SurveyDTO.PROPERTY_QUALIFICATION_COMMENT);
error.addPropertyName(SurveyDTO.PROPERTY_QUALIFICATION_COMMENT);
break;
case DATE:
messages.getValidDate(survey.getDate(), rule, error);
error.setPropertyName(SurveyDTO.PROPERTY_DATE);
error.addPropertyName(SurveyDTO.PROPERTY_DATE);