2 * Copyright (C) 2024 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.api
.service
.portal
;
11 import java
.util
.ArrayList
;
12 import java
.util
.List
;
14 import java
.util
.UUID
;
15 import java
.util
.stream
.Collectors
;
17 import org
.apache
.commons
.lang3
.StringUtils
;
19 import eu
.etaxonomy
.cdm
.api
.application
.ICdmRepository
;
20 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.AnnotatableDto
;
21 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.AnnotationDto
;
22 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.CdmBaseDto
;
23 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.ContainerDto
;
24 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.MarkerDto
;
25 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.MediaDto2
;
26 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.SingleSourcedDto
;
27 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.SourceDto
;
28 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.SourcedDto
;
29 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.TaxonPageDto
;
30 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.TaxonPageDto
.MediaRepresentationDTO
;
31 import eu
.etaxonomy
.cdm
.api
.dto
.portal
.config
.IAnnotatableLoaderConfiguration
;
32 import eu
.etaxonomy
.cdm
.format
.common
.TypedLabel
;
33 import eu
.etaxonomy
.cdm
.format
.reference
.OriginalSourceFormatter
;
34 import eu
.etaxonomy
.cdm
.model
.common
.AnnotatableEntity
;
35 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
36 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
37 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
38 import eu
.etaxonomy
.cdm
.model
.common
.ICdmBase
;
39 import eu
.etaxonomy
.cdm
.model
.common
.IPublishable
;
40 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
41 import eu
.etaxonomy
.cdm
.model
.common
.LanguageString
;
42 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
43 import eu
.etaxonomy
.cdm
.model
.common
.MultilanguageTextHelper
;
44 import eu
.etaxonomy
.cdm
.model
.common
.SingleSourcedEntityBase
;
45 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionBase
;
46 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
47 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementSource
;
48 import eu
.etaxonomy
.cdm
.model
.media
.ExternalLink
;
49 import eu
.etaxonomy
.cdm
.model
.media
.ImageFile
;
50 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
51 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
52 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentationPart
;
53 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
54 import eu
.etaxonomy
.cdm
.model
.reference
.ISourceable
;
55 import eu
.etaxonomy
.cdm
.model
.reference
.NamedSource
;
56 import eu
.etaxonomy
.cdm
.model
.reference
.NamedSourceBase
;
57 import eu
.etaxonomy
.cdm
.model
.reference
.OriginalSourceBase
;
58 import eu
.etaxonomy
.cdm
.model
.reference
.OriginalSourceType
;
59 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
60 import eu
.etaxonomy
.cdm
.model
.term
.Representation
;
61 import eu
.etaxonomy
.cdm
.model
.term
.TermBase
;
62 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ICdmGenericDao
;
63 import eu
.etaxonomy
.cdm
.strategy
.cache
.TaggedText
;
69 public abstract class TaxonPageDtoLoaderBase
{
71 protected ICdmRepository repository
;
72 protected ICdmGenericDao dao
;
74 public TaxonPageDtoLoaderBase(ICdmRepository repository
, ICdmGenericDao dao
) {
75 this.repository
= repository
;
79 //currently only used by fact loader
80 protected String
getTermLabel(TermBase term
, Language localeLang
) {
84 Representation rep
= term
.getPreferredRepresentation(localeLang
);
85 String label
= rep
== null ?
null : rep
.getLabel();
86 label
= label
== null ? term
.getLabel() : label
;
90 protected <P
extends IPublishable
> List
<P
> filterPublished(List
<P
> listToPublish
) {
91 if (listToPublish
== null) {
94 return listToPublish
.stream().filter(s
->s
.isPublish()).collect(Collectors
.toList());
98 protected <P
extends IPublishable
> Set
<P
> filterPublished(Set
<P
> setToPublish
) {
99 if (setToPublish
== null) {
102 return setToPublish
.stream().filter(s
->s
.isPublish()).collect(Collectors
.toSet());
106 public static void loadBaseData(IAnnotatableLoaderConfiguration config
, CdmBase cdmBase
, CdmBaseDto dto
) {
107 dto
.setId(cdmBase
.getId());
108 dto
.setUuid(cdmBase
.getUuid());
110 loadAnnotatable(config
, cdmBase
, dto
);
111 loadSources(config
, cdmBase
, dto
);
112 //loadIdentifiable(cdmBase, dto);
115 static void loadAnnotatable(IAnnotatableLoaderConfiguration config
, CdmBase cdmBase
, CdmBaseDto dto
) {
116 if (dto
instanceof AnnotatableDto
&& cdmBase
.isInstanceOf(AnnotatableEntity
.class)) {
117 AnnotatableEntity annotatable
= CdmBase
.deproxy(cdmBase
, AnnotatableEntity
.class);
118 AnnotatableDto annotatableDto
= (AnnotatableDto
)dto
;
120 for (Annotation annotation
: annotatable
.getAnnotations()) {
121 if ((annotation
.getAnnotationType() != null
122 //config == null currently needs to be allowed as it is also used by DistributionInfoBuilder an
123 //also for now empty annotation types needs to be interpreted as "no filter" as we do not distinguish
124 //null and empty yet, this may change in future
125 && (config
== null || config
.getAnnotationTypes().isEmpty()
126 || config
.getAnnotationTypes().contains(annotation
.getAnnotationType().getUuid())))
127 || (annotation
.getAnnotationType() == null && config
!= null && config
.getAnnotationTypes().contains(AnnotationType
.uuidUntyped
))
128 && StringUtils
.isNotBlank(annotation
.getText())) {
130 AnnotationDto annotationDto
= new AnnotationDto();
131 annotatableDto
.addAnnotation(annotationDto
);
132 //TODO id needed? but need to adapt dto and container then
133 loadBaseData(config
, annotation
, annotationDto
);
134 annotationDto
.setText(annotation
.getText());
135 UUID uuidAnnotationType
= annotation
.getAnnotationType() == null ?
null :annotation
.getAnnotationType().getUuid();
136 annotationDto
.setTypeUuid(uuidAnnotationType
);
137 //language etc. currently not yet used
138 }else if (config
!= null && !config
.getAnnotationTypes().isEmpty() && config
.getAnnotationTypes().contains(AnnotationType
.uuidUntyped
) && (annotation
.getAnnotationType() == null)){
139 AnnotationDto annotationDto
= new AnnotationDto();
140 annotatableDto
.addAnnotation(annotationDto
);
141 //TODO id needed? but need to adapt dto and container then
142 loadBaseData(config
, annotation
, annotationDto
);
143 annotationDto
.setText(annotation
.getText());
144 UUID uuidAnnotationType
= null;
145 annotationDto
.setTypeUuid(uuidAnnotationType
);
151 for (Marker marker
: annotatable
.getMarkers()) {
152 if (marker
.getMarkerType() != null
153 //TODO markertype filter
154 // && marker.getMarkerType().getUuid().equals(AnnotationType.uuidEditorial)
157 MarkerDto markerDto
= new MarkerDto();
158 annotatableDto
.addMarker(markerDto
);
159 //TODO id needed? but need to adapt dto and container then
160 loadBaseData(config
, marker
, markerDto
);
161 if (marker
.getMarkerType() != null) {
162 markerDto
.setTypeUuid(marker
.getMarkerType().getUuid());
164 markerDto
.setType(marker
.getMarkerType().getTitleCache());
166 markerDto
.setValue(marker
.getValue());
172 static void loadSources(IAnnotatableLoaderConfiguration config
, CdmBase cdmBase
, CdmBaseDto dto
) {
173 if (dto
instanceof SingleSourcedDto
&& cdmBase
.isInstanceOf(SingleSourcedEntityBase
.class)) {
175 SingleSourcedEntityBase sourced
= CdmBase
.deproxy(cdmBase
, SingleSourcedEntityBase
.class);
176 SingleSourcedDto sourcedDto
= (SingleSourcedDto
)dto
;
177 NamedSource source
= sourced
.getSource();
178 if (source
!= null && isPublicSource(source
) && !source
.checkEmpty()) {
179 SourceDto sourceDto
= makeSource(config
, source
);
180 sourcedDto
.setSource(sourceDto
);
182 } else if (dto
instanceof SourcedDto
&& cdmBase
instanceof ISourceable
) {
183 @SuppressWarnings("unchecked")
184 ISourceable
<OriginalSourceBase
> sourced
= (ISourceable
<OriginalSourceBase
>)cdmBase
;
185 SourcedDto sourcedDto
= (SourcedDto
)dto
;
186 for (OriginalSourceBase source
: sourced
.getSources()) {
187 if (isPublicSource(source
)) {
188 SourceDto sourceDto
= makeSource(config
, source
);
189 sourcedDto
.addSource(sourceDto
);
193 //load description sources for facts
194 if (cdmBase
.isInstanceOf(DescriptionElementBase
.class)){
195 DescriptionBase
<?
> db
= CdmBase
.deproxy(cdmBase
, DescriptionElementBase
.class).getInDescription();
196 if (db
!= null) { //test sometime do not have a description for facts
197 SourcedDto sourcedDto
= (SourcedDto
)dto
;
198 for (OriginalSourceBase source
: db
.getSources()) {
199 if (isPublicSource(source
)) {
200 SourceDto sourceDto
= new SourceDto();
201 loadSource(config
, source
, sourceDto
);
202 sourcedDto
.addSource(sourceDto
);
209 private static void loadSource(IAnnotatableLoaderConfiguration config
, OriginalSourceBase source
, SourceDto sourceDto
) {
211 source
= CdmBase
.deproxy(source
);
213 loadBaseData(config
, source
, sourceDto
);
215 ICdmBase linkedObject
= source
.getCitation();
216 if (linkedObject
== null) {
218 linkedObject
= source
.getCdmSource();
221 //citation doi & uri & links
222 Reference ref
= source
.getCitation();
224 sourceDto
.setDoi(ref
.getDoiString());
225 sourceDto
.setUri(ref
.getUri());
226 sourceDto
.setUuid(ref
.getUuid());
227 sourceDto
.setOriginalInfo(source
.getOriginalInfo());
228 Set
<ExternalLink
> links
= ref
.getLinks();
230 if(source
.getAccessed() != null) {
231 sourceDto
.setAccessed(source
.getAccessed().toString());
233 for (ExternalLink link
: links
) {
234 if (link
.getUri() != null) {
235 sourceDto
.addLink(link
.getUri());
241 //TODO this probably does not use specimen or cdmSource if necessary,
242 // also long citation is still preliminary
243 String label
= OriginalSourceFormatter
.INSTANCE_LONG_CITATION
.format(source
);
244 TypedLabel typedLabel
= new TypedLabel(source
, label
);
245 sourceDto
.addLabel(typedLabel
);
246 sourceDto
.setType(source
.getType() != null ? source
.getType().toString() : null);
248 if (source
.isInstanceOf(NamedSourceBase
.class)) {
249 NamedSourceBase ns
= CdmBase
.deproxy(source
, NamedSourceBase
.class);
252 TaxonName name
= ns
.getNameUsedInSource();
254 List
<TaggedText
> taggedName
= name
.cacheStrategy().getTaggedTitle(name
);
256 sourceDto
.setNameInSource(taggedName
);
257 sourceDto
.setNameInSourceUuid(name
.getUuid());
261 if (source
.isInstanceOf(DescriptionElementSource
.class)) {
262 DescriptionElementSource des
= CdmBase
.deproxy(source
, DescriptionElementSource
.class);
263 if (linkedObject
== null) {
264 linkedObject
= des
.getSpecimen();
269 sourceDto
.setLinkedUuid(getUuid(linkedObject
));
270 String linkedObjectStr
= linkedObject
== null ?
null : CdmBase
.deproxy(linkedObject
).getClass().getSimpleName();
271 sourceDto
.setLinkedClass(linkedObjectStr
);
274 protected static SourceDto
makeSource(IAnnotatableLoaderConfiguration config
, OriginalSourceBase source
) {
275 if (source
== null) {
278 SourceDto sourceDto
= new SourceDto();
279 loadSource(config
, source
, sourceDto
);
283 protected static UUID
getUuid(ICdmBase cdmBase
) {
284 return cdmBase
== null ?
null : cdmBase
.getUuid();
287 protected static boolean isPublicSource(OriginalSourceBase source
) {
288 if (source
.getType() == null) {
289 return false; //should not happen
291 OriginalSourceType type
= source
.getType();
292 //TODO 3 make source type configurable
293 return type
.isPublicSource();
297 protected void makeMediaContainer(IAnnotatableLoaderConfiguration config
, TaxonPageDto result
, List
<Media
> medias
) {
298 ContainerDto
<MediaDto2
> container
= new ContainerDto
<>();
300 for (Media media
: medias
) {
301 handleSingleMedia(config
, container
, media
);
304 if (container
.getCount() > 0) {
305 result
.setMedia(container
);
309 protected void handleSingleMedia(IAnnotatableLoaderConfiguration config
, ContainerDto
<MediaDto2
> container
, Media media
) {
311 MediaDto2 dto
= new MediaDto2();
312 loadBaseData(config
, media
, dto
);
315 dto
.setLabel(media
.getTitleCache());
317 List
<Language
> languages
= new ArrayList
<>();
318 LanguageString description
= MultilanguageTextHelper
.getPreferredLanguageString(media
.getAllDescriptions(), languages
);
319 dto
.setDescription(description
== null ?
null : description
.getText());
322 ContainerDto
<MediaRepresentationDTO
> representations
= new ContainerDto
<>();
323 for (MediaRepresentation rep
: media
.getRepresentations()) {
324 MediaRepresentationDTO repDto
= new MediaRepresentationDTO();
325 loadBaseData(config
, rep
, repDto
);
326 repDto
.setMimeType(rep
.getMimeType());
327 repDto
.setSuffix(rep
.getSuffix());
328 if (!rep
.getParts().isEmpty()) {
329 //TODO handle message if n(parts) > 1
330 MediaRepresentationPart part
= rep
.getParts().get(0);
331 repDto
.setUri(part
.getUri());
332 repDto
.setClazz(part
.getClass().getSimpleName());
333 repDto
.setSize(part
.getSize());
334 if (part
.isInstanceOf(ImageFile
.class)) {
335 ImageFile image
= CdmBase
.deproxy(part
, ImageFile
.class);
336 repDto
.setHeight(image
.getHeight());
337 repDto
.setWidth(image
.getWidth());
339 //TODO AudioFile etc.
341 representations
.addItem(repDto
);
343 if (representations
.getCount() > 0) {
344 dto
.setRepresentations(representations
);
346 //TODO load representation data
347 container
.addItem(dto
);