1 package net.sumaris.core.dao.referential;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import com.google.common.base.Preconditions;
26 import com.google.common.collect.ImmutableList;
27 import com.google.common.collect.Maps;
28 import net.sumaris.core.dao.technical.SortDirection;
29 import net.sumaris.core.dao.technical.hibernate.HibernateDaoSupport;
30 import net.sumaris.core.exception.SumarisTechnicalException;
31 import net.sumaris.core.model.administration.programStrategy.*;
32 import net.sumaris.core.model.administration.user.Department;
33 import net.sumaris.core.model.referential.*;
34 import net.sumaris.core.model.referential.gear.Gear;
35 import net.sumaris.core.model.referential.gear.GearClassification;
36 import net.sumaris.core.model.referential.grouping.Grouping;
37 import net.sumaris.core.model.referential.grouping.GroupingClassification;
38 import net.sumaris.core.model.referential.grouping.GroupingLevel;
39 import net.sumaris.core.model.referential.location.Location;
40 import net.sumaris.core.model.referential.location.LocationClassification;
41 import net.sumaris.core.model.referential.location.LocationLevel;
42 import net.sumaris.core.model.referential.metier.Metier;
43 import net.sumaris.core.model.referential.pmfm.*;
44 import net.sumaris.core.model.referential.taxon.TaxonGroup;
45 import net.sumaris.core.model.referential.taxon.TaxonGroupType;
46 import net.sumaris.core.model.referential.taxon.TaxonName;
47 import net.sumaris.core.model.referential.taxon.TaxonomicLevel;
48 import net.sumaris.core.model.referential.transcribing.TranscribingItem;
49 import net.sumaris.core.model.technical.configuration.Software;
50 import net.sumaris.core.model.technical.extraction.ExtractionProduct;
51 import net.sumaris.core.model.technical.extraction.ExtractionProductTable;
52 import net.sumaris.core.util.Beans;
53 import net.sumaris.core.vo.filter.ReferentialFilterVO;
54 import net.sumaris.core.vo.referential.IReferentialVO;
55 import net.sumaris.core.vo.referential.ReferentialTypeVO;
56 import net.sumaris.core.vo.referential.ReferentialVO;
57 import org.apache.commons.lang3.ArrayUtils;
58 import org.apache.commons.lang3.StringUtils;
59 import org.nuiton.i18n.I18n;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62 import org.springframework.beans.BeanUtils;
63 import org.springframework.dao.DataRetrievalFailureException;
64 import org.springframework.stereotype.Repository;
65
66 import javax.persistence.EntityManager;
67 import javax.persistence.TypedQuery;
68 import javax.persistence.criteria.*;
69 import java.beans.PropertyDescriptor;
70 import java.io.Serializable;
71 import java.sql.Timestamp;
72 import java.util.*;
73 import java.util.stream.Collectors;
74 import java.util.stream.Stream;
75
76 @Repository("referentialDao")
77 public class ReferentialDaoImpl extends HibernateDaoSupport implements ReferentialDao {
78
79
80 private static final Logger log =
81 LoggerFactory.getLogger(ReferentialDaoImpl.class);
82
83 private static Map<String, Class<? extends IReferentialEntity>> entityClassMap = Maps.uniqueIndex(
84 ImmutableList.of(
85 Department.class,
86 Location.class,
87 LocationLevel.class,
88 LocationClassification.class,
89 Gear.class,
90 GearClassification.class,
91 UserProfile.class,
92 SaleType.class,
93 VesselType.class,
94
95 TaxonGroupType.class,
96 TaxonGroup.class,
97
98 TaxonomicLevel.class,
99 TaxonName.class,
100
101 Metier.class,
102
103 Parameter.class,
104 Pmfm.class,
105 Matrix.class,
106 Fraction.class,
107 QualitativeValue.class,
108
109 QualityFlag.class,
110
111 Program.class,
112 Strategy.class,
113 AcquisitionLevel.class,
114
115 TranscribingItem.class,
116
117 GroupingClassification.class,
118 GroupingLevel.class,
119 Grouping.class,
120
121 ExtractionProduct.class,
122 ExtractionProductTable.class,
123
124 Software.class,
125
126 ProgramPrivilege.class
127 ), Class::getSimpleName);
128
129 private Map<String, PropertyDescriptor> levelPropertyNameMap = initLevelPropertyNameMap();
130
131 static {
132 I18n.n("sumaris.persistence.table.location");
133 I18n.n("sumaris.persistence.table.locationLevel");
134 I18n.n("sumaris.persistence.table.gear");
135 I18n.n("sumaris.persistence.table.gearLevel");
136 I18n.n("sumaris.persistence.table.parameter");
137 I18n.n("sumaris.persistence.table.userProfile");
138 I18n.n("sumaris.persistence.table.saleType");
139 I18n.n("sumaris.persistence.table.taxonGroup");
140 I18n.n("sumaris.persistence.table.taxonGroupType");
141 I18n.n("sumaris.persistence.table.taxonomicLevel");
142 I18n.n("sumaris.persistence.table.referenceTaxon");
143 I18n.n("sumaris.persistence.table.taxonName");
144 I18n.n("sumaris.persistence.table.metier");
145 I18n.n("sumaris.persistence.table.parameter");
146 I18n.n("sumaris.persistence.table.pmfm");
147 I18n.n("sumaris.persistence.table.matrix");
148 I18n.n("sumaris.persistence.table.fraction");
149 I18n.n("sumaris.persistence.table.qualitativeValue");
150 I18n.n("sumaris.persistence.table.program");
151 I18n.n("sumaris.persistence.table.acquisitionLevel");
152 I18n.n("sumaris.persistence.table.transcribingItem");
153 I18n.n("sumaris.persistence.table.groupingClassification");
154 I18n.n("sumaris.persistence.table.groupingLevel");
155 I18n.n("sumaris.persistence.table.grouping");
156 I18n.n("sumaris.persistence.table.extractionProduct");
157 I18n.n("sumaris.persistence.table.extractionProductTable");
158 }
159
160 protected static Map<String, PropertyDescriptor> initLevelPropertyNameMap() {
161 Map<String, PropertyDescriptor> result = new HashMap<>();
162
163
164 entityClassMap.values().stream().forEach((clazz) -> {
165 PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(clazz);
166 for (PropertyDescriptor pd: pds) {
167 if (pd.getName().matches("^.*[Ll]evel([A−Z].*)?$")) {
168 result.put(clazz.getSimpleName(), pd);
169 break;
170 }
171 }
172 });
173
174
175 result.put(Fraction.class.getSimpleName(), BeanUtils.getPropertyDescriptor(Fraction.class, Fraction.Fields.MATRIX));
176 result.put(QualitativeValue.class.getSimpleName(), BeanUtils.getPropertyDescriptor(QualitativeValue.class, QualitativeValue.Fields.PARAMETER));
177 result.put(TaxonGroup.class.getSimpleName(), BeanUtils.getPropertyDescriptor(TaxonGroup.class, TaxonGroup.Fields.TAXON_GROUP_TYPE));
178 result.put(TaxonName.class.getSimpleName(), BeanUtils.getPropertyDescriptor(TaxonName.class, TaxonName.Fields.TAXONOMIC_LEVEL));
179 result.put(Strategy.class.getSimpleName(), BeanUtils.getPropertyDescriptor(Strategy.class, Strategy.Fields.PROGRAM));
180 result.put(Metier.class.getSimpleName(), BeanUtils.getPropertyDescriptor(Metier.class, Metier.Fields.GEAR));
181 result.put(GroupingLevel.class.getSimpleName(), BeanUtils.getPropertyDescriptor(GroupingLevel.class, GroupingLevel.Fields.GROUPING_CLASSIFICATION));
182 result.put(Grouping.class.getSimpleName(), BeanUtils.getPropertyDescriptor(Grouping.class, Grouping.Fields.GROUPING_LEVEL));
183 result.put(ExtractionProductTable.class.getSimpleName(), BeanUtils.getPropertyDescriptor(ExtractionProductTable.class, ExtractionProductTable.Fields.PRODUCT));
184 result.put(LocationLevel.class.getSimpleName(), BeanUtils.getPropertyDescriptor(LocationLevel.class, LocationLevel.Fields.LOCATION_CLASSIFICATION));
185 result.put(Gear.class.getSimpleName(), BeanUtils.getPropertyDescriptor(Gear.class, Gear.Fields.GEAR_CLASSIFICATION));
186 result.put(Program.class.getSimpleName(), BeanUtils.getPropertyDescriptor(Program.class, Program.Fields.GEAR_CLASSIFICATION));
187 result.put(Program.class.getSimpleName(), BeanUtils.getPropertyDescriptor(Program.class, Program.Fields.TAXON_GROUP_TYPE));
188
189 return result;
190 }
191
192
193 @Override
194 public List<ReferentialVO> findByFilter(final String entityName,
195 ReferentialFilterVO filter,
196 int offset,
197 int size,
198 String sortAttribute,
199 SortDirection sortDirection) {
200 Preconditions.checkNotNull(entityName, "Missing entityName argument");
201 Preconditions.checkNotNull(filter);
202
203
204 Class<? extends IReferentialEntity> entityClass = getEntityClass(entityName);
205
206 return createFindQuery(entityClass,
207 filter.getLevelId(),
208 filter.getLevelIds(),
209 StringUtils.trimToNull(filter.getSearchText()),
210 StringUtils.trimToNull(filter.getSearchAttribute()),
211 filter.getStatusIds(),
212 sortAttribute,
213 sortDirection, null)
214 .setFirstResult(offset)
215 .setMaxResults(size)
216 .getResultStream()
217 .map(s -> toReferentialVO(entityName, s))
218 .filter(Objects::nonNull)
219 .collect(Collectors.toList());
220 }
221
222 @Override
223 public ReferentialVO findByUniqueLabel(String entityName, String label) {
224 Preconditions.checkNotNull(entityName, "Missing entityName argument");
225 Preconditions.checkNotNull(label);
226
227
228 Class<? extends IReferentialEntity> entityClass = getEntityClass(entityName);
229
230 return toReferentialVO(entityName, createFindByUniqueLabelQuery(entityClass, label).getSingleResult());
231 }
232
233 @Override
234 public List<ReferentialTypeVO> getAllTypes() {
235
236 return entityClassMap.keySet().stream()
237 .map(this::getTypeByEntityName)
238 .collect(Collectors.toList());
239 }
240
241 @Override
242 public List<ReferentialVO> getAllLevels(final String entityName) {
243 Preconditions.checkNotNull(entityName, "Missing entityName argument");
244
245 PropertyDescriptor levelDescriptor = levelPropertyNameMap.get(entityName);
246 if (levelDescriptor == null) {
247 return ImmutableList.of();
248 }
249
250 String levelEntityName = levelDescriptor.getPropertyType().getSimpleName();
251 return findByFilter(levelEntityName, new ReferentialFilterVO(), 0, 100,
252 IItemReferentialEntity.Fields.NAME, SortDirection.ASC);
253 }
254
255 @Override
256 public ReferentialVO getLevelById(String entityName, int levelId) {
257 Preconditions.checkNotNull(entityName, "Missing entityName argument");
258
259 PropertyDescriptor levelDescriptor = levelPropertyNameMap.get(entityName);
260 if (levelDescriptor == null) {
261 throw new DataRetrievalFailureException("Unable to find level with id=" + levelId + " for entityName=" + entityName);
262 }
263
264 Class<?> levelClass = levelDescriptor.getPropertyType();
265 if (!IReferentialEntity.class.isAssignableFrom(levelClass)){
266 throw new DataRetrievalFailureException("Unable to convert class=" + levelClass.getName() + " to a referential bean");
267 }
268 return toReferentialVO(levelClass.getSimpleName(), (IReferentialEntity)entityManager.find(levelClass, levelId));
269 }
270
271 @Override
272 public <T extends IReferentialEntity> ReferentialVO toReferentialVO(T source) {
273 return toReferentialVO(getEntityName(source), source);
274 }
275
276 @Override
277 public <T extends IReferentialVO, S extends IReferentialEntity> Optional<T> toTypedVO(S source, Class<T> targetClazz) {
278
279 if (source == null)
280 return Optional.empty();
281
282 try {
283 T target = targetClazz.newInstance();
284 Beans.copyProperties(source, target);
285 return Optional.of(target);
286 }catch(IllegalAccessException | InstantiationException e) {
287 throw new SumarisTechnicalException(e.getMessage(), e);
288 }
289 }
290
291 @Override
292 public void delete(final String entityName, int id) {
293
294
295 Class<? extends IReferentialEntity> entityClass = getEntityClass(entityName);
296
297 log.debug(String.format("Deleting %s {id=%s}...", entityName, id));
298 delete(entityClass, id);
299 }
300
301 @Override
302 public Long count(String entityName) {
303 Preconditions.checkNotNull(entityName, "Missing entityName argument");
304
305
306 Class<? extends IReferentialEntity> entityClass = getEntityClass(entityName);
307
308 CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
309 CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class);
310 criteriaQuery.select(builder.count(criteriaQuery.from(entityClass)));
311
312 return getEntityManager().createQuery(criteriaQuery).getSingleResult();
313 }
314
315 @Override
316 public Long countByLevelId(String entityName, Integer... levelIds) {
317 Preconditions.checkNotNull(entityName, "Missing entityName argument");
318
319
320 Class<? extends IReferentialEntity> entityClass = getEntityClass(entityName);
321
322 CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
323 CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class);
324
325 Root<? extends IReferentialEntity> entityRoot = criteriaQuery.from(entityClass);
326 criteriaQuery.select(builder.count(entityRoot));
327
328
329 Predicate levelClause = null;
330 ParameterExpression<Collection> levelIdsParam = builder.parameter(Collection.class);
331 PropertyDescriptor pd = levelPropertyNameMap.get(entityClass.getSimpleName());
332 if (pd != null && ArrayUtils.isNotEmpty(levelIds)) {
333 levelClause = builder.in(entityRoot.get(pd.getName()).get(IReferentialEntity.Fields.ID)).value(levelIdsParam);
334 criteriaQuery.where(levelClause);
335 }
336
337 TypedQuery<Long> query = getEntityManager().createQuery(criteriaQuery);
338 if (levelClause != null) {
339 query.setParameter(levelIdsParam, ImmutableList.copyOf(levelIds));
340 }
341
342 return query.getSingleResult();
343 }
344
345 @Override
346 public ReferentialVOl/ReferentialVO.html#ReferentialVO">ReferentialVO save(final ReferentialVO source) {
347 Preconditions.checkNotNull(source);
348
349
350 Class<? extends IReferentialEntity> entityClass = getEntityClass(source.getEntityName());
351
352 EntityManager entityManager = getEntityManager();
353
354 IReferentialEntity entity = null;
355 if (source.getId() != null) {
356 entity = get(entityClass, source.getId());
357 }
358 boolean isNew = (entity == null);
359 if (isNew) {
360 try {
361 entity = entityClass.newInstance();
362 } catch (IllegalAccessException |InstantiationException e) {
363 throw new IllegalArgumentException(String.format("Entity with name [%s] has no empty constructor", source.getEntityName()));
364 }
365 }
366
367 if (!isNew) {
368
369 checkUpdateDateForUpdate(source, entity);
370
371
372
373 }
374
375
376 referentialVOToEntity(source, entity, true);
377
378
379 Timestamp newUpdateDate = getDatabaseCurrentTimestamp();
380 entity.setUpdateDate(newUpdateDate);
381
382
383 if (isNew) {
384
385 entity.setCreationDate(newUpdateDate);
386 source.setCreationDate(newUpdateDate);
387
388 entityManager.persist(entity);
389 source.setId(entity.getId());
390 } else {
391 entityManager.merge(entity);
392 }
393
394 source.setUpdateDate(newUpdateDate);
395
396 entityManager.flush();
397 entityManager.clear();
398
399 return source;
400 }
401
402
403
404 protected ReferentialTypeVO getTypeByEntityName(final String entityName) {
405
406 ReferentialTypeVOferentialTypeVO.html#ReferentialTypeVO">ReferentialTypeVO type = new ReferentialTypeVO();
407 type.setId(entityName);
408
409 PropertyDescriptor levelDescriptor = levelPropertyNameMap.get(entityName);
410 if (levelDescriptor != null) {
411 type.setLevel(levelDescriptor.getPropertyType().getSimpleName());
412 }
413 return type;
414 }
415
416 protected <T extends IReferentialEntity> ReferentialVO toReferentialVO(final String entityName, T source) {
417 Preconditions.checkNotNull(entityName);
418 Preconditions.checkNotNull(source);
419
420 ReferentialVOReferentialVO.html#ReferentialVO">ReferentialVO target = new ReferentialVO();
421
422 Beans.copyProperties(source, target);
423
424
425 target.setStatusId(source.getStatus().getId());
426
427
428 PropertyDescriptor levelDescriptor = levelPropertyNameMap.get(entityName);
429 if (levelDescriptor != null) {
430 try {
431 IReferentialEntity/../net/sumaris/core/model/referential/IReferentialEntity.html#IReferentialEntity">IReferentialEntity level = (IReferentialEntity)levelDescriptor.getReadMethod().invoke(source, new Object[0]);
432 if (level != null) {
433 target.setLevelId(level.getId());
434 }
435 } catch(Exception e) {
436 throw new SumarisTechnicalException(e);
437 }
438 }
439
440
441 target.setEntityName(entityName);
442
443 return target;
444 }
445
446 protected List<ReferentialVO> toReferentialVOs(List<? extends IReferentialEntity> source) {
447 return toReferentialVOs(source.stream());
448 }
449
450 protected List<ReferentialVO> toReferentialVOs(Stream<? extends IReferentialEntity> source) {
451 return source
452 .map(this::toReferentialVO)
453 .filter(Objects::nonNull)
454 .collect(Collectors.toList());
455 }
456
457 public <T> TypedQuery<T> createFindQuery(Class<T> entityClass,
458 Integer levelId,
459 Integer[] levelIds,
460 String searchText,
461 String searchAttribute,
462 Integer[] statusIds,
463 String sortAttribute,
464 SortDirection sortDirection,
465 QueryVisitor<T> queryVisitor) {
466 CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
467 CriteriaQuery<T> query = builder.createQuery(entityClass);
468 Root<T> entityRoot = query.from(entityClass);
469 query.select(entityRoot).distinct(true);
470
471
472 Predicate levelClause = null;
473 ParameterExpression<Collection> levelIdsParam = null;
474 if (ArrayUtils.isNotEmpty(levelIds)) {
475 if (levelIds.length == 1) {
476 levelId = levelIds[0];
477 levelIds = null;
478 } else {
479 levelId = null;
480 levelIdsParam = builder.parameter(Collection.class);
481 PropertyDescriptor pd = levelPropertyNameMap.get(entityClass.getSimpleName());
482 if (pd != null) {
483 levelClause = builder.in(entityRoot.get(pd.getName()).get(IReferentialEntity.Fields.ID)).value(levelIdsParam);
484 }
485 else {
486 log.warn(String.format("Trying to request on level, but no level found for entity {%s}", entityClass.getSimpleName()));
487 }
488 }
489 }
490
491 ParameterExpression<Integer> levelIdParam = null;
492 if (levelId != null) {
493 levelIdParam = builder.parameter(Integer.class);
494 PropertyDescriptor pd = levelPropertyNameMap.get(entityClass.getSimpleName());
495 if (pd != null) {
496 levelClause = builder.equal(entityRoot.get(pd.getName()).get(IReferentialEntity.Fields.ID), levelIdParam);
497 }
498 else {
499 log.warn(String.format("Trying to request on level, but no level found for entity {%s}", entityClass.getSimpleName()));
500 }
501 }
502
503
504 ParameterExpression<String> searchAsPrefixParam = builder.parameter(String.class);
505 ParameterExpression<String> searchAnyMatchParam = builder.parameter(String.class);
506 Predicate searchTextClause = null;
507 if (searchText != null) {
508
509 if (StringUtils.isNotBlank(searchAttribute) && BeanUtils.getPropertyDescriptor(entityClass, searchAttribute) != null) {
510 searchTextClause = builder.or(
511 builder.isNull(searchAnyMatchParam),
512 builder.like(builder.upper(entityRoot.get(searchAttribute)), builder.upper(searchAsPrefixParam))
513 );
514 }
515 else if (IItemReferentialEntity.class.isAssignableFrom(entityClass)) {
516
517 searchTextClause = builder.or(
518 builder.isNull(searchAnyMatchParam),
519 builder.like(builder.upper(entityRoot.get(IItemReferentialEntity.Fields.LABEL)), builder.upper(searchAsPrefixParam)),
520 builder.like(builder.upper(entityRoot.get(IItemReferentialEntity.Fields.NAME)), builder.upper(searchAnyMatchParam))
521 );
522 } else if (BeanUtils.getPropertyDescriptor(entityClass, IItemReferentialEntity.Fields.LABEL) != null) {
523
524 searchTextClause = builder.or(
525 builder.isNull(searchAnyMatchParam),
526 builder.like(builder.upper(entityRoot.get(IItemReferentialEntity.Fields.LABEL)), builder.upper(searchAsPrefixParam))
527 );
528 } else if (BeanUtils.getPropertyDescriptor(entityClass, IItemReferentialEntity.Fields.NAME) != null) {
529
530 searchTextClause = builder.or(
531 builder.isNull(searchAnyMatchParam),
532 builder.like(builder.upper(entityRoot.get(IItemReferentialEntity.Fields.NAME)), builder.upper(searchAnyMatchParam))
533 );
534 }
535 }
536
537
538 ParameterExpression<Collection> statusIdsParam = builder.parameter(Collection.class);
539 Predicate statusIdsClause = null;
540 if (ArrayUtils.isNotEmpty(statusIds)) {
541 statusIdsClause = builder.in(entityRoot.get(IItemReferentialEntity.Fields.STATUS).get(IItemReferentialEntity.Fields.ID)).value(statusIdsParam);
542 }
543
544
545 Expression<Boolean> whereClause = null;
546 if (levelClause != null) {
547 whereClause = levelClause;
548 }
549 if (searchTextClause != null) {
550 whereClause = (whereClause == null) ? searchTextClause : builder.and(whereClause, searchTextClause);
551 }
552
553 if (statusIdsClause != null) {
554 whereClause = (whereClause == null) ? statusIdsClause : builder.and(whereClause, statusIdsClause);
555 }
556
557
558 if (queryVisitor != null) {
559 Expression<Boolean> additionnalWhere = queryVisitor.apply(query, entityRoot);
560 if (additionnalWhere != null) {
561 whereClause = (whereClause == null) ? additionnalWhere : builder.and(whereClause, additionnalWhere);
562 }
563 }
564
565 if (whereClause != null) {
566 query.where(whereClause);
567 }
568
569
570 if (StringUtils.isNotBlank(sortAttribute)) {
571
572
573 if (IReferentialVO.Fields.LEVEL.equals(sortAttribute)) {
574 PropertyDescriptor levelDescriptor = levelPropertyNameMap.get(entityClass.getSimpleName());
575 if (levelDescriptor != null) {
576 sortAttribute = levelDescriptor.getName();
577 }
578 else {
579 sortAttribute = null;
580 }
581 }
582
583 if (StringUtils.isNotBlank(sortAttribute)) {
584 Expression<?> sortExpression = entityRoot.get(sortAttribute);
585 query.orderBy(SortDirection.DESC.equals(sortDirection) ?
586 builder.desc(sortExpression) :
587 builder.asc(sortExpression)
588 );
589 }
590 }
591
592 TypedQuery<T> typedQuery = getEntityManager().createQuery(query);
593
594
595 if (searchTextClause != null) {
596 String searchTextAsPrefix = null;
597 if (StringUtils.isNotBlank(searchText)) {
598 searchTextAsPrefix = (searchText + "*")
599 .replaceAll("[*]+", "*")
600 .replaceAll("[%]", "\\%")
601 .replaceAll("[*]", "%");
602 }
603 String searchTextAnyMatch = StringUtils.isNotBlank(searchTextAsPrefix) ? ("%"+searchTextAsPrefix) : null;
604 typedQuery.setParameter(searchAsPrefixParam, searchTextAsPrefix);
605 typedQuery.setParameter(searchAnyMatchParam, searchTextAnyMatch);
606 }
607 if (levelClause != null) {
608 if (levelIds != null) {
609 typedQuery.setParameter(levelIdsParam, ImmutableList.copyOf(levelIds));
610 }
611 else {
612 typedQuery.setParameter(levelIdParam, levelId);
613 }
614 }
615 if (statusIdsClause != null) {
616 typedQuery.setParameter(statusIdsParam, ImmutableList.copyOf(statusIds));
617 }
618
619 return typedQuery;
620 }
621
622 private <T> TypedQuery<T> createFindByUniqueLabelQuery(Class<T> entityClass, String label) {
623 CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
624 CriteriaQuery<T> query = builder.createQuery(entityClass);
625 Root<T> tripRoot = query.from(entityClass);
626 query.select(tripRoot).distinct(true);
627
628
629 ParameterExpression<String> labelParam = builder.parameter(String.class);
630 query.where(builder.equal(tripRoot.get(IItemReferentialEntity.Fields.LABEL), labelParam));
631
632 return getEntityManager().createQuery(query)
633 .setParameter(labelParam, label);
634 }
635
636 protected Class<? extends IReferentialEntity> getEntityClass(String entityName) {
637 Preconditions.checkNotNull(entityName);
638
639
640 Class<? extends IReferentialEntity> entityClass = entityClassMap.get(entityName);
641 if (entityClass == null)
642 throw new IllegalArgumentException(String.format("No entity with name [%s]", entityName));
643 return entityClass;
644 }
645
646 protected String getTableName(String entityName) {
647
648 return I18n.t("sumaris.persistence.table."+ entityName.substring(0,1).toLowerCase() + entityName.substring(1));
649 }
650
651 protected <T extends IReferentialEntity> String getEntityName(T source) {
652 String classname = source.getClass().getSimpleName();
653 int index = classname.indexOf("$HibernateProxy");
654 if (index > 0) {
655 return classname.substring(0, index);
656 }
657 return classname;
658 }
659
660 protected void referentialVOToEntity(final ReferentialVO source, IReferentialEntity target, boolean copyIfNull) {
661
662 Beans.copyProperties(source, target);
663
664
665 if (copyIfNull || source.getStatusId() != null) {
666 if (source.getStatusId() == null) {
667 target.setStatus(null);
668 }
669 else {
670 target.setStatus(load(Status.class, source.getStatusId()));
671 }
672 }
673
674
675 Integer levelID = source.getLevelId();
676 if (copyIfNull || levelID != null) {
677 PropertyDescriptor levelDescriptor = levelPropertyNameMap.get(source.getEntityName());
678 if (levelDescriptor != null) {
679 try {
680 if (levelID == null) {
681 levelDescriptor.getWriteMethod().invoke(target, new Object[]{null});
682 }
683 else {
684 Object level = load(levelDescriptor.getPropertyType().asSubclass(Serializable.class), levelID);
685 levelDescriptor.getWriteMethod().invoke(target, level);
686 }
687 } catch(Exception e) {
688 throw new SumarisTechnicalException(e);
689 }
690 }
691 }
692
693 }
694
695 }