Merge branch 'develop' of ssh://dev.e-taxonomy.eu/var/git/cdmlib into develop
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / MediaServiceImpl.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9
10 package eu.etaxonomy.cdm.api.service;
11
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.Set;
15 import java.util.UUID;
16
17 import org.springframework.beans.factory.annotation.Autowired;
18 import org.springframework.stereotype.Service;
19 import org.springframework.transaction.annotation.Transactional;
20
21 import eu.etaxonomy.cdm.api.service.config.DeleteConfiguratorBase;
22 import eu.etaxonomy.cdm.api.service.config.MediaDeletionConfigurator;
23 import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
24 import eu.etaxonomy.cdm.api.service.pager.Pager;
25 import eu.etaxonomy.cdm.api.service.pager.impl.DefaultPagerImpl;
26 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
27 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
28 import eu.etaxonomy.cdm.model.common.CdmBase;
29 import eu.etaxonomy.cdm.model.common.ICdmBase;
30 import eu.etaxonomy.cdm.model.description.DescriptionBase;
31 import eu.etaxonomy.cdm.model.description.IDescribable;
32 import eu.etaxonomy.cdm.model.description.MediaKey;
33 import eu.etaxonomy.cdm.model.description.SpecimenDescription;
34 import eu.etaxonomy.cdm.model.description.TaxonDescription;
35 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
36 import eu.etaxonomy.cdm.model.description.TextData;
37 import eu.etaxonomy.cdm.model.location.NamedArea;
38 import eu.etaxonomy.cdm.model.media.Media;
39 import eu.etaxonomy.cdm.model.media.MediaRepresentation;
40 import eu.etaxonomy.cdm.model.media.Rights;
41 import eu.etaxonomy.cdm.model.name.TaxonName;
42 import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
43 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
44 import eu.etaxonomy.cdm.model.taxon.Taxon;
45 import eu.etaxonomy.cdm.persistence.dao.media.IMediaDao;
46 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
47
48 @Service
49 @Transactional(readOnly=true)
50 public class MediaServiceImpl extends IdentifiableServiceBase<Media,IMediaDao> implements IMediaService {
51
52 @Override
53 @Autowired
54 protected void setDao(IMediaDao dao) {
55 this.dao = dao;
56 }
57
58 @Autowired
59 private IOccurrenceService specimenService;
60 @Autowired
61 private ITaxonService taxonService;
62 @Autowired
63 private INameService nameService;
64
65
66 @Override
67 public Pager<MediaKey> getMediaKeys(Set<Taxon> taxonomicScope, Set<NamedArea> geoScopes, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
68 long numberOfResults = dao.countMediaKeys(taxonomicScope, geoScopes);
69
70 List<MediaKey> results = new ArrayList<>();
71 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
72 results = dao.getMediaKeys(taxonomicScope, geoScopes, pageSize, pageNumber, propertyPaths);
73 }
74
75 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
76 }
77
78 @Override
79 public Pager<Rights> getRights(Media t, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
80 long numberOfResults = dao.countRights(t);
81
82 List<Rights> results = new ArrayList<>();
83 if(numberOfResults > 0) { // no point checking again //TODO use AbstractPagerImpl.hasResultsInRange(numberOfResults, pageNumber, pageSize)
84 results = dao.getRights(t, pageSize, pageNumber,propertyPaths);
85 }
86
87 return new DefaultPagerImpl<>(pageNumber, numberOfResults, pageSize, results);
88 }
89
90 @Override
91 @Transactional(readOnly = false)
92 public UpdateResult updateCaches(Class<? extends Media> clazz, Integer stepSize, IIdentifiableEntityCacheStrategy<Media> cacheStrategy, IProgressMonitor monitor) {
93 if (clazz == null){
94 clazz = Media.class;
95 }
96 return super.updateCachesImpl(clazz, stepSize, cacheStrategy, monitor);
97 }
98
99 @Override
100 @Transactional(readOnly=false)
101 public DeleteResult delete(UUID mediaUuid, MediaDeletionConfigurator config) {
102 DeleteResult result = new DeleteResult();
103 Media media = this.load(mediaUuid);
104 if (media == null){
105 return result;
106 }
107 result = isDeletable(mediaUuid, config);
108 if (result.isOk()){
109 Set<CdmBase> references = commonService.getReferencingObjectsForDeletion(media);
110 for (CdmBase ref: references){
111
112 IDescribable<?> updatedObject = null;
113 IService<ICdmBase> service = null;
114 if (ref instanceof TextData){
115
116 TextData textData = HibernateProxyHelper.deproxy(ref, TextData.class);
117 DescriptionBase<?> description = HibernateProxyHelper.deproxy(textData.getInDescription(), DescriptionBase.class);
118
119 IDescribable<?> objectToUpdate = null;
120 boolean deleteIsMatchingInstance = false;
121 if (description instanceof TaxonDescription){
122 objectToUpdate = ((TaxonDescription)description).getTaxon();
123 deleteIsMatchingInstance = config.getDeleteFrom() instanceof Taxon;
124 service = (IService)taxonService;
125 }else if (description instanceof SpecimenDescription){
126 objectToUpdate = ((SpecimenDescription)description).getDescribedSpecimenOrObservation();
127 deleteIsMatchingInstance = config.getDeleteFrom() instanceof SpecimenOrObservationBase;
128 service = (IService)specimenService;
129 }else if (description instanceof TaxonNameDescription){
130 objectToUpdate = ((TaxonNameDescription)description).getTaxonName();
131 deleteIsMatchingInstance = config.getDeleteFrom() instanceof TaxonName;
132 service = (IService)nameService;
133 }else{
134 throw new RuntimeException("Unsupported DescriptionBase class");
135 }
136
137 if (objectToUpdate == null ){
138 continue;
139 } else if ( (config.isDeleteFromDescription() && deleteIsMatchingInstance &&
140 config.getDeleteFrom().getId() == objectToUpdate.getId())
141 || config.isDeleteFromEveryWhere()){
142 updatedObject = handleDeleteMedia(media, textData, description,
143 (IDescribable)objectToUpdate);
144 } else {
145 // this should not be happen, because it is not deletable. see isDeletable
146 result.setAbort();
147 }
148
149 // } else if (ref instanceof MediaSpecimen && config.getDeleteFrom().getId() == ref.getId() && config.getDeleteFrom() instanceof MediaSpecimen){
150 // MediaSpecimen mediaSpecimen = HibernateProxyHelper.deproxy(ref, MediaSpecimen.class);
151 // mediaSpecimen.setMediaSpecimen(null);
152 // updatedObject = mediaSpecimen;
153 // service = (IService)specimenService;
154 }else if (ref instanceof MediaRepresentation){
155 continue;
156 }else {
157 result.setAbort();
158 }
159
160 if (updatedObject != null){
161 service.update(updatedObject); //service should always be != null if updatedObject != null
162 result.addUpdatedObject((CdmBase)updatedObject);
163 }
164 }
165 if (result.isOk()){
166 dao.delete(media);
167 result.addDeletedObject(media);
168 }
169
170 }
171 return result;
172 }
173
174 /**
175 * @param media
176 * @param textData
177 * @param desc
178 * @param taxon
179 */
180 private IDescribable<DescriptionBase<?>> handleDeleteMedia(Media media, TextData textData,
181 DescriptionBase<?> desc, IDescribable<DescriptionBase<?>> describable) {
182 while(textData.getMedia().contains(media)){
183 textData.removeMedia(media);
184 }
185 //if the textData contains text it should not be deleted
186 if (textData.getMedia().isEmpty() && textData.getMultilanguageText().isEmpty()){
187 desc.removeElement(textData);
188 }
189 if (desc.getElements().isEmpty()){
190 describable.removeDescription(desc);
191 }
192 return describable;
193 }
194
195
196 @Override
197 public DeleteResult isDeletable(UUID mediaUuid, DeleteConfiguratorBase config){
198 DeleteResult result = new DeleteResult();
199 Media media = this.load(mediaUuid);
200 Set<CdmBase> references = commonService.getReferencingObjectsForDeletion(media);
201 MediaDeletionConfigurator mediaConfig = (MediaDeletionConfigurator)config;
202 CdmBase deleteFrom = mediaConfig.getDeleteFrom();
203
204 if (mediaConfig.isDeleteFromEveryWhere()){
205 return result;
206 }
207 for (CdmBase ref: references){
208 String message = null;
209 if (ref instanceof MediaRepresentation){
210 continue;
211 }
212 if (ref instanceof TextData){
213 TextData textData = HibernateProxyHelper.deproxy(ref, TextData.class);
214 DescriptionBase description = HibernateProxyHelper.deproxy(textData.getInDescription(), DescriptionBase.class);
215
216 if (description instanceof TaxonDescription){
217 TaxonDescription desc = HibernateProxyHelper.deproxy(description, TaxonDescription.class);
218 if (desc.getTaxon() == null || (mediaConfig.isDeleteFromDescription() && (deleteFrom instanceof Taxon && ((Taxon)deleteFrom).getId() == desc.getTaxon().getId()))){
219 continue;
220 } else{
221 message = "The media can't be deleted from the database because it is referenced by a taxon. ("+desc.getTaxon().getTitleCache()+")";
222 result.setAbort();
223 }
224
225 } else if (description instanceof SpecimenDescription){
226 SpecimenDescription desc = HibernateProxyHelper.deproxy(description, SpecimenDescription.class);
227 if (desc.getDescribedSpecimenOrObservation() == null || (mediaConfig.isDeleteFromDescription() && (deleteFrom instanceof SpecimenOrObservationBase && ((SpecimenOrObservationBase)deleteFrom).getId() == desc.getDescribedSpecimenOrObservation().getId()))){
228 continue;
229 } else{
230 message = "The media can't be deleted from the database because it is referenced by a specimen or observation. ("+desc.getDescribedSpecimenOrObservation().getTitleCache()+")";
231 result.setAbort();
232 }
233 } else if (description instanceof TaxonNameDescription){
234 TaxonNameDescription desc = HibernateProxyHelper.deproxy(description, TaxonNameDescription.class);
235 if (desc.getTaxonName() == null || (mediaConfig.isDeleteFromDescription() && (deleteFrom instanceof TaxonName && ((TaxonName)deleteFrom).getId() == desc.getTaxonName().getId()))){
236 continue;
237 } else{
238 message = "The media can't be deleted from the database because it is referenced by a scientific name. ("+desc.getTaxonName().getTitleCache()+")";
239 result.setAbort();
240 }
241 }
242
243 }if (ref instanceof MediaSpecimen){
244 message = "The media can't be deleted from the database because it is referenced by a mediaspecimen. ("+((MediaSpecimen)ref).getTitleCache()+")";
245 result.setAbort();
246 }else {
247 message = "The media can't be completely deleted because it is referenced by another " + ref.getUserFriendlyTypeName() ;
248 result.setAbort();
249 }
250 if (message != null){
251 result.addException(new ReferencedObjectUndeletableException(message));
252 result.addRelatedObject(ref);
253
254 }
255
256 }
257
258 return result;
259 }
260 }